[
  {
    "path": ".gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nproject.xcworkspace\n\n# Android/IJ\n#\n.idea\n.gradle\nlocal.properties\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\n\narticle-web/article-web.zip\nexample/react-native-photos-framework/src/\n\n# REMINDER: do not edit Icon^M^M Carriage Returns\nIcon\r\r\n# END REMINDER\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: objective-c\n\nosx_image: xcode8.2\n\ninstall:\n  - nvm use 6.9.1\n  - wget https://github.com/yarnpkg/yarn/releases/download/v0.18.1/yarn-0.18.1.js\n  - export yarn=\"node $(pwd)/yarn-0.18.1.js\"\n  - $yarn install\n  - cd example && $yarn install && cd ..\n\nscript:\n  - if [[ \"$TEST_TYPE\" = objc-ios ]]; then set -o pipefail && xcodebuild test -verbose -project example/ios/Example.xcodeproj -scheme Example -destination 'id=E40727B3-41FB-4D6E-B4CB-BFA87109EB12' | xcpretty; fi\n  - if [[ \"$TEST_TYPE\" = js ]]; then npm test -- --maxWorkers=1; fi\n\nenv:\n  matrix:\n    - TEST_TYPE=objc-ios\n    - TEST_TYPE=js\n\nbranches:\n  only:\n    - master\n    - /^.*-stable$/\n\nnotifications:\n  email:\n    recipients:\n      - olof.dahlbom@me.com\n    on_failure: change\n    on_success: change\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Debug Android\",\n            \"program\": \"${workspaceRoot}/.vscode/launchReactNative.js\",\n            \"type\": \"reactnative\",\n            \"request\": \"launch\",\n            \"platform\": \"android\",\n            \"internalDebuggerPort\": 9090,\n            \"sourceMaps\": true,\n            \"outDir\": \"${workspaceRoot}/.vscode/.react\"\n        },\n        {\n            \"name\": \"Debug iOS\",\n            \"program\": \"${workspaceRoot}/.vscode/launchReactNative.js\",\n            \"type\": \"reactnative\",\n            \"request\": \"launch\",\n            \"platform\": \"ios\",\n            \"target\": \"iPhone 5s\",\n            \"internalDebuggerPort\": 9090,\n            \"sourceMaps\": true,\n            \"outDir\": \"${workspaceRoot}/.vscode/.react\"\n        }\n    ]\n}"
  },
  {
    "path": ".watchmanconfig",
    "content": "{\n  \"ignore_dirs\": [\n    \".git\",\n    \"node_modules\"\n  ]\n}\n\n\n123\n\n\nffmpeg -i ~/Desktop/Untitled.mov -s 304x540 -pix_fmt rgb24 -r 15 -f gif - | gifsicle --optimize=4 --delay=4 > ~/Desktop/out.gif\n\ncp ~/Desktop/out.gif ~/Dropbox/Public/screenshots/Screencast-`date +\"%Y.%m.%d-%H.%M\"`.gif\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 Juli Racca\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "test:\n\txcodebuild test -workspace ios/RNPhotosFramework.xcworkspace -scheme RNPhotosFramework -destination 'platform=iOS Simulator,name=iPhone 5s'\n"
  },
  {
    "path": "README.md",
    "content": "# react-native-photos-framework [![Build Status](https://travis-ci.org/olofd/react-native-photos-framework.svg?branch=master)](https://travis-ci.org/olofd/react-native-photos-framework) [![npm version](https://badge.fury.io/js/react-native-photos-framework.svg)](https://badge.fury.io/js/react-native-photos-framework) [![Beerpay](https://beerpay.io/olofd/react-native-photos-framework/badge.svg?style=beer)](https://beerpay.io/olofd/react-native-photos-framework)\n\n### Example project\n#### NOTE: This is not a GUI-component, it's an API. The example project just shows off some of the the capabilities of this API.\n![](https://media.giphy.com/media/3o6Ztqdc8OF3FAgAiQ/source.gif)\n\n#### Breaking Changes\nreact-native header imports have changed in v0.40, and that means breaking changes for all! [Reference PR & Discussion](https://github.com/lwansbrough/react-native-camera/pull/544).\nThis library is updated to work with the new imports.\nUse version < 0.0.64 if your still < RN 0.40.\n\n### Description\nLoad photos/videos and more from CameraRoll and iCloud.\nUses Apples photos framework. \n- Advanced options for loading and filtering.\n- Support for displaying both Images and Videos simply in your app.\n- Create, modify, delete photos, videos and albums.\n- Support for sending photos and videos to a server using Ajax. \n- Change-tracking. (eg. someone takes a new photo while your app is open, this library will provide you with events to refresh your collection so it will display the latest changes to the photo-library).\n\nReact Native comes with it's own CameraRoll library.\nThis however uses ALAssetLibrary which is a deprecated API from Apple\nand can only load photos and videos stored on the users device.\nThis is not what your user expects today. Most users photos live on iCloud and these won't show if you use ALAssetLibrary.\n\nIf you use this library (Photos framework) you can display the users local resources and the users iCloud resources.\n\n### Installation:\n`npm i react-native-photos-framework --save && react-native link react-native-photos-framework`\n\nNOTE: When running `npm install` this library will try to automatically add `NSPhotoLibraryUsageDescription` to your Info.plist.\nCheck that it is there after the install or update it's value from the default:\n`Using photo library to select pictures`\n (Will not do anything if you have already defined this key in Info.plist)\n\n# Simple example:\n\n~~~js\n/**\n * Sample React Native App\n * https://github.com/facebook/react-native\n * @flow\n */\n\nimport React, {Component} from 'react';\nimport {AppRegistry, StyleSheet, Text, View, Image} from 'react-native';\nimport RNPhotosFramework from 'react-native-photos-framework';\n\nexport default class AwesomeProject extends Component {\n\n    constructor() {\n      super();\n      this.state = {\n        images : []\n      };\n    }\n\n    componentDidMount() {\n        RNPhotosFramework.requestAuthorization().then((statusObj) => {\n            if (statusObj.isAuthorized) {\n                RNPhotosFramework.getAlbums({\n                    type: 'smartAlbum',\n                    subType: 'smartAlbumUserLibrary',\n                    assetCount: 'exact',\n                    fetchOptions: {\n                        sortDescriptors: [\n                            {\n                                key: 'title',\n                                ascending: true\n                            }\n                        ],\n                        includeHiddenAssets: false,\n                        includeAllBurstAssets: false\n                    },\n                    //When you say 'trackInsertsAndDeletes or trackChanges' for an albums query result,\n                    //They will be cached and tracking will start.\n                    //Call queryResult.stopTracking() to stop this. ex. on componentDidUnmount\n                    trackInsertsAndDeletes: true,\n                    trackChanges: false\n\n                }).then((queryResult) => {\n                    const album = queryResult.albums[0];\n                    return album.getAssets({\n                        //The fetch-options from the outer query will apply here, if we get\n                        startIndex: 0,\n                        endIndex: 10,\n                        //When you say 'trackInsertsAndDeletes or trackAssetsChange' for an albums assets,\n                        //They will be cached and tracking will start.\n                        //Call album.stopTracking() to stop this. ex. on componentDidUnmount\n                        trackInsertsAndDeletes: true,\n                        trackChanges: false\n                    }).then((response) => {\n                        this.setState({\n                          images : response.assets\n                        });\n                    });\n                });\n            }\n        });\n    }\n\n    renderImage(asset, index) {\n      return (\n        <Image key={index} source={asset.image} style={{width : 100, height : 100}}></Image>\n      );\n    }\n\n    render() {\n        return (\n            <View style={styles.container}>\n                {this.state.images.map(this.renderImage.bind(this))}\n            </View>\n        );\n    }\n}\n\nconst styles = StyleSheet.create({\n    container: {\n        flex: 1,\n        justifyContent: 'center',\n        alignItems: 'center',\n        backgroundColor: '#F5FCFF'\n    },\n    welcome: {\n        fontSize: 20,\n        textAlign: 'center',\n        margin: 10\n    },\n    instructions: {\n        textAlign: 'center',\n        color: '#333333',\n        marginBottom: 5\n    }\n});\n\nAppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);\n\n~~~\n\n# API-documentation:\n\n## Library (Top level):\n\n## Static methods:\n\n### authorizationStatus\n~~~js\n  RNPhotosFramework.authorizationStatus().then(() => {\n  });\n~~~\n\nSignature: `RNPhotosFramework.authorizationStatus() : Promise<{status : string, isAuthorized : boolean}>`.\nFetches the current authorization-status.\nNOTE: You can receive the following statuses :\n* `notDetermined` //Before user has granted permission,\n* `restricted` //User is restricted by policy, cannot use Photos,\n* `denied` //User has denied permission,\n* `authorized` //User has granted permission\n\n### requestAuthorization\n~~~js\n  RNPhotosFramework.requestAuthorization().then((statusObj) => {\n    if(statusObj.isAuthorized) {\n      ...start using the library.\n    }\n  });\n~~~\n\nSignature: `RNPhotosFramework.requestAuthorization() : Promise<{status : string, isAuthorized : boolean}>`.\nThis will prompt the user to grant access to the user library at first start.\nIf you do not call this method explicitly before using any of the other functions in this library, the grant-access-dialog will appear for the user automatically at the first function-call into the library. But only one function-call can automatically\ntrigger this dialog, so if another call comes into Photos Framework before the user has granted you access, that function-call will fail. Therefore I urge you to call this method explicitly before you start using the rest of the library to not experience unexpected behaviour.\nNOTE: You do not have to first check the authorizationStatus before calling this. If the user has granted access before, this will just return authorized-status.\nNOTE: See available statuses in doc. about: `authorizationStatus`\n\n## Working with Content:\n##### `fetchOptions`\nfetchOptions is a query-object which can be sent both when fetching albums with\n`getAlbums` and when fetching assets with `getAssets`. Below you can see the available options\nfor fetchOptions. You can also read Apple's documentation around [PHFetchOptions here](https://developer.apple.com/reference/photos/phfetchoptions).\n(Many of the args map one-to-one with native data structures.)\n\n| Prop  | Default  | Type | Description |\n| :------------ |:---------------:| :---------------:| :-----|\n| mediaTypes (Only for `getAssets`) | - | `array<string>` | Defines what mediaType the asset should be. Array combined with OR-operator. e.g. ['image', 'video'] will return both photos and videos. Converted in Native to PHAssetMediaType. Accepted values: `image`, `video`, `audio`, `unknown` |\n| mediaSubTypes (Only for `getAssets`) | - | `array<string>` | Defines what subtype the asset should be. Array combined with OR-operator. e.g. ['photoPanorama', 'photoHDR'] will return both panorama and HDR-assets. Converted in Native to PHAssetMediaSubtype. Accepted enum-values: `none`, `photoPanorama`, `photoHDR`, `photoScreenshot`, `photoLive`, `videoStreamed`, `videoHighFrameRate`, `videoTimeLapse` (mediaTypes and mediaSubTypes are combined with AND-operator) |\n| sourceTypes (Only for `getAssets`) | - | `array<string>` | Defines where the asset should come from originally. Array combined with OR-operator. Converted in Native to PHAssetSourceType. Accepted enum-values: `none`, `userLibrary`, `cloudShared`, `itunesSynced`. (not supported and ignored in iOS 8) |\n| includeHiddenAssets | false | `boolean` | A Boolean value that determines whether the fetch result includes assets marked as hidden. |\n| includeAllBurstAssets | false | `boolean` | A Boolean value that determines whether the fetch result includes all assets from burst photo sequences. |\n| fetchLimit | 0 | `number` | The maximum number of objects to include in the fetch result. Remember to not use this in the wrong way combined with startIndex and endIndex. 0 means unlimited. |\n| sortDescriptors | - | `array<{key : <string>, ascending : <boolean>}>` |  Multiple sortDescriptors which decide how the result should be sorted. |\n\n# Retrieving Assets (photos/videos/audio):\n~~~js\nimport RNPhotosFramework from 'react-native-photos-framework';\n\n  RNPhotosFramework.getAssets({\n    //Example props below. Many optional.\n    // You can call this function multiple times providing startIndex and endIndex as\n    // pagination.\n    startIndex: 0,\n    endIndex: 100,\n\n    fetchOptions : {\n      // Media types you wish to display. See table below for possible options. Where\n      // is the image located? See table below for possible options.\n      sourceTypes: ['userLibrary'],\n\n      sortDescriptors : [\n        {\n          key: 'creationDate',\n          ascending: true,\n        }\n      ]\n    }\n  }).then((response) => console.log(response.assets));\n\n~~~\n\n###### Props to `getAssets`\n\n| Prop  | Default  | Type | Description |\n| :------------ |:---------------:| :---------------:| :-----|\n| fetchOptions | - | `object` | See above. |\n| startIndex | 0 | `number` | startIndex-offset for fetching |\n| endIndex | 0 | `number` | endIndex-offset stop for fetching |\n| includeMetadata | false | `boolean` | Include a lot of metadata about the asset (See below). You can also choose to get this metaData at a later point by calling `asset.getMetadata()` (See below) |\n| includeResourcesMetadata | false | `boolean` | Include metadata about the orginal resources that make up the asset. Like type and original filename. You can also choose to get this metaData at a later point by calling `asset.getResourcesMetadata()`. |\n| prepareForSizeDisplay | - | `Rect(width, height)` | The size of the image you soon will display after running the query. This is highly optional and only there for optimizations of big lists. Prepares the images for display in Photos by using PHCachingImageManager |\n| prepareScale | 2.0 | `number` | The scale to prepare the image in. |\n| assetDisplayStartToEnd | false | `boolean` | Retrieves assets from the beginning of the library when set to true. Using this sorting option preserves the native order of assets as they are viewed in the Photos app.  |\n| assetDisplayBottomUp | false | `boolean` | Used to arrange assets from the bottom to top of screen when scrolling up to view paginated results. |\n\n### Example of asset response with `includeMetadata : true`\n~~~\ncreationDate : 1466766146\nduration : 17.647 (video)\nwidth : 1920\nheight : 1080\nisFavorite : false\nisHidden : false\nlocalIdentifier : \"3D5E6260-2B63-472E-A38A-3B543E936E8C/L0/001\"\nlocation : Object\nmediaSubTypes : null\nmediaType : \"video\"\nmodificationDate : 1466766146\nsourceType : \"userLibrary\"\nuri : \"photos://3D5E6260-2B63-472E-A38A-3B543E936E8C/L0/001\"\n~~~\n\n(`sourceType` is not supported in iOS 8)\n\n# Retrieving albums and enumerating their assets:\n~~~js\n  RNPhotosFramework.getAlbums({\n    type: 'album',\n    subType: 'any',\n    assetCount: 'exact',\n    fetchOptions: {\n      sortDescriptors : [\n        {\n          key: 'title',\n          ascending: true\n        }\n      ],\n      includeHiddenAssets: false,\n      includeAllBurstAssets: false\n    },\n    //When you say 'trackInsertsAndDeletes or trackChanges' for an albums query result,\n    //They will be cached and tracking will start.\n    //Call queryResult.stopTracking() to stop this. ex. on componentDidUnmount\n    trackInsertsAndDeletes : true,\n    trackChanges : false\n\n  }).then((queryResult) => {\n    const album = queryResult.albums[0];\n    return album.getAssets({\n      //The fetch-options from the outer query will apply here, if we get\n      startIndex: 0,\n      endIndex: 10,\n      //When you say 'trackInsertsAndDeletes or trackAssetsChange' for an albums assets,\n      //They will be cached and tracking will start.\n      //Call album.stopTracking() to stop this. ex. on componentDidUnmount\n      trackInsertsAndDeletes : true,\n      trackChanges : false\n    }).then((response) => {\n      console.log(response.assets, 'The assets in the first album');\n    });\n  });\n~~~\n\n###### Props to `getAlbums`\n\nGet albums allow to query the Photos Framework for asset-albums. Both User-created ones and Smart-albums.\nNote that Apple creates a lot of dynamic, so called Smart Albums, like : 'Recently added', 'Favourites' etc.\n\nNOTE: There is also another method called `getAlbumsMany`. This could be considered a low-level-method of the API. It is constructed so that this library can build more accessible methods on top of one joint native-call: like getUserTopAlbums in pure JS.\nThe getAlbumsMany-api can take multiple queries (array<albumquery>) and return an array<albumqueryresult></albumqueryresult>.\n\nNOTE about Apple Bug for album titles in iOS 10.\nThe album.title property is suppose to be localized\nto your language out of the box. But this will only work if\nyou have a language translation file included in your\nproject. The native property is called localizedTitle.\nIf you only see english names as titles for smart albums,\neg. 'All Photos' even though you run on a different language\niPhone, check this question out:\nhttp://stackoverflow.com/questions/42579544/ios-phassetcollection-localizedtitle-always-returning-english-name\n\n| Prop  | Default  | Type | Description |\n| :------------ |:---------------:| :---------------:| :-----|\n| fetchOptions | - | `object` | See above. |\n| assetFetchOptions | - | `object` | Fetch options used when loading assets from album returned. You can choose to pass these fetchOptions here to affect `previewAssets` and `assetCount` in the album according to these options. Note: If you supply fetchOptions when later calling getAssets, those options will override these options.  |\n| type | `album` | `string` | Defines what type of album/collection you wish to retrieve. Converted in Native to PHAssetCollectionType. Accepted enum-values: `album`, `smartAlbum`, `moment` |\n| subType | `any` | `string` | Defines what subType the album/collection you wish to retrieve should have. Converted in Native to PHAssetCollectionSubtype. Accepted enum-values: `any`, `albumRegular`, `syncedEvent`, `syncedFaces`, `syncedAlbum`, `imported`, `albumMyPhotoStream`, `albumCloudShared`, `smartAlbumGeneric`, `smartAlbumPanoramas`, `smartAlbumVideos`, `smartAlbumFavorites`, `smartAlbumTimelapses`, `smartAlbumAllHidden`, `smartAlbumRecentlyAdded`, `smartAlbumBursts`, `smartAlbumSlomoVideos`, `smartAlbumUserLibrary`, `smartAlbumSelfPortraits`, `smartAlbumScreenshots` |\n| assetCount | `estimated` | `string/enum` | You can choose to get `estimated` count of the collection or `exact`-count. Of course these have different performance-impacts. Returns -1 if the estimated count can't be fetched quickly. Remember that your of course fetchOptions affects this count. |\n| previewAssets | - | `number` | If you set this to a number, say 2, you will get the first two images from the album included in the album-response. This is so you can show a small preview-thumbnail for the album if you like to. |\n| includeMetadata | false | `boolean` | Include some meta data about the album. You can also choose to get this metaData at a later point by calling album.getMetadata (See below) |\n| noCache | `false` | `boolean` | If you set this flag to true. The result won't get cached or tracked for changes. |\n| preCacheAssets | `false` | `boolean` | If you set this property to true all assets of all albums your query returned will be cached and change-tracking will start. |\n| trackInsertsAndDeletes | `false` | `boolean` | If you set this to true. You will get called back on `queryResult.onChange` when a Insert or Delete happens. See observing changes below for more details. |\n| trackChanges | `false` | `boolean` | If you set this to true. You will get called back on `queryResult.onChange` when a Change happens to the query-result. See observing changes below for more details. |\n\n# Working with Albums:\n\n## Static methods:\n\n### Base methods:\n~~~js\n//Fetches albums for params. See above\nRNPhotosFramework.getAlbums(params)\n//Fetches many queries\n//as SingleQueryResult : boolean. if true, will return response as one single response.\nRNPhotosFramework.getAlbumsMany([params, params...], asSingleQueryResult);\n//Prebuilt query for fetching the most typical albums:\n//Camera-Roll, User-albums and user-shared-albums.\nRNPhotosFramework.getAlbumsCommon(params)\n~~~\n\n### createAlbum\n~~~js\n  RNPhotosFramework.createAlbum('test-album').then((album) => {\n    //You can now use the album like any other album:\n    return album.getAssets().then((photos) => {});\n  });\n~~~\n\nSignature: RNPhotosFramework.createAlbum(albumTitle) : Promise<album>.\nThere is also another multi-method you can use here:\nSignature: RNPhotosFramework.createAlbums(albumTitles) : Promise<album>.\n\nNOTE: Alums can have the same name. All resources in Photos are unique on their\nlocalIdentifier. You can use the below methods to tackle this:\n\n### getAlbumsByTitle\n~~~js\n  RNPhotosFramework.getAlbumsByTitle('test-album').then((albums) => {});\n~~~\nSignature: RNPhotosFramework.getAlbumsByTitle(albumTitle) : Promise<array<album>>.\nMany albums can have the same title. Returns all matching albums.\nThere is also another multi-method you can use here:\nSignature: RNPhotosFramework.getAlbumsByTitles(albumTitles) : Promise<array<album>>.\nSignature: RNPhotosFramework.getAlbumsWithParams({albumTitles, ...otherThingLikeFetchOptionsOrType/SubType}) : Promise<array<album>>.\n\n### getAlbumByLocalIdentifier and getAlbumByLocalIdentifiers\n~~~js\n  RNPhotosFramework.getAlbumByLocalIdentifier(localIdentifier).then((album) => {});\n~~~\nSignature: RNPhotosFramework.getAlbumByLocalIdentifier(localIdentifier) : Promise<album>.\nAll alums carry their localIdentifier on album.localIdentifier.\n\n## Album instance-methods:\n\n### addAssetToAlbum and addAssetsToAlbum\n~~~js\n  album.addAssetToAlbum(asset).then((status) => {});\n~~~\nSignature: album.addAssetToAlbum(asset) : Promise<status>.\nAdd an asset/assets to an album.\nNOTE: Can only be called with assets that are stored in the library already.\nIf you have a image that you want to save to the library see createAsset.\n\n\n### removeAssetFromAlbum and removeAssetsFromAlbum\n~~~js\n  album.removeAssetFromAlbum(asset).then((status) => {});\n~~~\nSignature: album.removeAssetFromAlbum(asset) : Promise<status>.\nRemove asset from album.\nNOTE: Can only be called with assets that are stored in the library already.\nIf you have a image that you want to save to the library see createAsset.\n\n### updateTitle\n~~~js\n  album.updateTitle(newTitle).then((status) => {});\n~~~\nSignature: album.updateTitle(string) : Promise<status>.\nChange title on an album.\n\n### delete\n~~~js\n  album.delete().then((status) => {});\n~~~\nSignature: album.delete() : Promise<status>.\nDelete an album.\n\n### getMetadata\n~~~js\n  album.getMetadata().then((mutatedAlbumWithMetadata) => {});\n~~~\nFetch meta data for a specific album. You can also include metadata on all albums in the first `getAlbum`-call\nby explicitly setting option `includeMetadata: true`.\n\n\n# Working with Assets (Images/Photos):\nWhen you retrieve assets from the API you will get back an Asset object.\nThere is nothing special about this object. I've defined it as a class so\nthat it can have some instance-methods.\n\n## All Assets. (Video/Image)\nThese are methods and options that apply to all kinds of assets.\n(NOTE: Creating new assets has it's own chapter down below).\n\n## Asset instance-methods:\n\n#### setHidden\n~~~js\n  asset.setHidden(hiddenBoolean).then((resultOfOperation) => {\n\n  });\n~~~\nHides or un-hides a specific asset. Will prompt the user when an asset is about to be hidden.\n\n#### setFavorite\n~~~js\n  asset.setFavorite(favoriteBoolean).then((resultOfOperation) => {\n\n  });\n~~~\nMarks/Unmarks the asset as favorite.\n\n#### setCreationDate\n~~~js\n  asset.setCreationDate(jsDate).then((resultOfOperation) => {\n\n  });\n~~~\nUpdates the assets creationDate.\n\n#### setLocation\n~~~js\n  asset.setLocation({\n    lat : Number //required,\n    lng : Number //required,\n    altitude : Number //optional, Altitue above sea-level\n    heading : Number //optional, cource/heading from 0 (North) to 359.9.\n    speed : Number //optional, speed in m/s.\n    timeStamp : JSDate //optional, timestamp. Defaults to Now.\n  }).then((resultOfOperation) => {\n\n  });\n~~~\nUpdates the assets location.\n\n#### getMetadata\n~~~js\n  asset.getMetadata().then((mutatedAssetWithMetadata) => {});\n~~~\nFetch metadata for a specific asset. You can also include metadata on all assets in the first `getAsset`-call by explicitly setting option `includeMetadata: true`.\n\n#### getResourcesMetadata\n~~~js\n  asset.getResourcesMetadata().then((mutatedAssetWithResourcesMetadata) => {\n    console.log(mutatedAssetWithResourcesMetadata.resourcesMetadata);\n  });\n~~~\nFetch resource-metadata for a specific asset, this includes original filename, type, uti (uniformTypeIdentifier) and localidentifier. You can also include resource-metadata on all assets in the first `getAsset`-call by explicitly setting option `includeResourcesMetadata: true`.\n\n### Update Asset metaData\nNOTE: When updating metaData, there is two ways of dealing with the result of the update operation.\nEither your asset-collection updates automatically by using `Change-Tracking` (See below).\nThis means that the updated asset will be replaced in your collection, but the asset you \nexecuted the change on will be unaffected. So calling `setHidden(true)` will still\nhave isHidden : false, after your update, but it will be replaced with a new asset\nin your collection via `Change-Tracking`. (Remember to track changes with `trackChanges : true` when calling `getAssets`)\n\nIf you choose to NOT use `Change-Tracking` you can call `refreshMetadata` on the asset\nafter your update-operation:\n~~~js\n  asset.setHidden(hiddenBoolean).then((resultOfOperation) => {\n      asset.refreshMetadata().then(() => {\n          console.log('The JS-asset should now reflect your changes');\n       });\n  });\n~~~\n\nNOTE2: You can update multiple assets at once by calling \n~~~js\nRNPhotosFramework.updateAssets({\n  [assetOne.localIdentifier] : {\n    //Will only update properties provided:\n    hidden, favorite, creationDate, location\n  },\n  [assetTwo.localIdentifier] : {\n    hidden, favorite, creationDate, location\n  }\n  ...etc\n});\n~~~\n\n#### delete\n~~~js\n  asset.delete().then((status) => {\n  });\n~~~\nDelete asset.\n\n\n## Images/Photo-Assets\nAn Image/Photo-asset is fully compatible with RN's `<Image source={asset.image}></Image>`-tag.\nThis includes all resizeModes.\nNOTE: Use the property `.image` on an asset for the `<Image>`-tag. Otherwise\nRN will freeze your asset object. And they are, right now at least, mutable.\n\n## Image-Asset instance-methods:\n\n#### getImageMetadata\n~~~js\n  asset.getImageMetadata().then((mutatedAssetWithImageMetadata) => {\n    console.log(mutatedAssetWithResourcesMetadata.imageMetadata);\n  });\n~~~\nFetch image specific metadata for a specific image-asset, this includes formats and sizes.\n\n## withOptions for Images/Photos\n`withOptions` define special rules and options when loading an asset.\nIf you want to know more about how an asset is loaded. Read below on chapter `About Asset-Loaders`.\n\n### deliveryMode\nApple's Photo Framework will download images from iCloud on demand, and will generally be very smart about caching and loading resources quickly. You can however define how an Image should be loaded. We have 3 different options in PHImageRequestOptionsDeliveryMode:\n\n~~~\nPHImageRequestOptionsDeliveryModeOpportunistic = 0, // client may get several image results when the call is asynchronous or will get one result when the call is synchronous\nPHImageRequestOptionsDeliveryModeHighQualityFormat = 1, // client will get one result only and it will be as asked or better than asked (sync requests are automatically processed this way regardless of the specified mode)\nPHImageRequestOptionsDeliveryModeFastFormat = 2 // client will get one result only and it may be degraded\n~~~\n\nThis library defaults to loading assets with `PHImageRequestOptionsDeliveryModeHighQualityFormat`.\nThis can be considered to be the same as RN normally loads images. It will simply download the image in the size of your <Image> (iCloud-images are stored in multiple sizes, and Photos Framework will download the one closest to your target size) and display it.\n\nBut you can choose to use the other two deliveryMode's to. you do this by calling:\n~~~js\n  const assetWithNewDeliveryMode = asset.withOptions({\n      //one of opportunistic|highQuality|fast\n      deliveryMode : 'opportunistic'\n  });\n~~~\nIf you choose to use opportunistic here you will see a low-res-version of the image displayed\nwhile the highQuality version of the resource is downloaded. NOTE: This library will call correct lifecycle callback's on your image-tag when this is used: the\n`<Image onPartialLoad={//Low-res-callback} onLoad={//High-res-callback} onProgress={//downloadCallback}>`\n\n\n## Video-Assets\nVideo assets can be played by using a special branch of the great library `react-native-video`.\nThis branch adds the capability of loading Videos from Photos-framework and works\nas expected, but is otherwise the same as the orignal project. So you can play \nlocal or remote files as well and if you already use `react-native-video` for\nother content, you should just be able to replace the version.\n\nNOTE: Let me and the `react-native-video`-guys know if you want this to go into thir master.\n\n### Install `react-native-video`:\n`npm install git://github.com/olofd/react-native-video.git#react-native-photos-framework --save && react-native link`\n\nor add : `\"react-native-video\": \"git://github.com/olofd/react-native-video.git#react-native-photos-framework\"`  to your package.json and run npm install.\n\n### Displaying video\n~~~jsx\n      <Video source={this.props.asset.video} //Use the asset.video-property.\n        ref={(ref) => {\n          this.player = ref\n        }}\n        resizeMode='cover'\n        muted={false}\n        paused={this.state.videoPaused}  \n        style={styles.thumbVideo}/>\n~~~\nFor more info on supported properties see:\n[react-native-video](https://github.com/olofd/react-native-video/tree/react-native-photos-framework)\n\n## withOptions for Video-Asset.\n`withOptions` define special rules and options when loading an asset.\n(Implemented in [react-native-video)](https://github.com/olofd/react-native-video/tree/react-native-photos-framework)\n\n| Prop  | Default  | Type | Description |\n| :------------ |:---------------:| :---------------:| :-----|\n| deliveryMode | `'automatic'` | `string/enum` | Maps to native [PHVideoRequestOptionsDeliveryMode (Apple's docs)](https://developer.apple.com/reference/photos/phvideorequestoptionsdeliverymode?language=objc).  Possible values : `automatic`, `mediumQuality`, `highQuality`, `fast`|\n| version | `'current'` | `string/enum` | Maps to native [PHVideoRequestOptionsVersion (Apple's docs)](https://developer.apple.com/reference/photos/phvideorequestoptionsversion).  Possible values : `current`, `original`|\n\n### withOptions example usage for video:\n~~~js\n  const assetWithNewDeliveryMode = asset.withOptions({\n      deliveryMode : 'mediumQuality'\n  });\n~~~\n\n### About Asset-Loaders:\n~~~\nNOTE about RN's concept of Image loaders:\nRN has a plugin-like system for displaying Images/Photos.\nThis means that any library (like this library) can define it's own\nImageLoader. When RN later gets a request to display a <Image> it will query\nall ImageLoaders loaded in the system and ask which loader can load a specific resource.\nIf the resource starts with `https://` for instance, RN's own network-image-loader will take care of loading that resource. While if the scheme of the resource is `asset-library://` another ImageLoader will load that Image.\n\nThis library defines it's own ImageLoader which can load images from iCloud. (RN actually already have a ImageLoader that can load iCloud images, but we define our own/extend their original loader so we can have some extra functionality on our loader. (See deliveryMode below)).\nA ´uri´ that our loader can load is defined in scheme: `photos://` and localIdentifier eg: `9509A678-2A07-405F-B3C6-49FD806915CC/L0/001`\nURI-example: photos://9509A678-2A07-405F-B3C6-49FD806915CC/L0/001\n~~~\n\n# Creating Assets:\nYou can use this library to save images and videos to the users iCloud library.\nNOTE: Creating image-assets uses RN's ImageLoader-system behind the scenes and should therefore be able to accept/save any image/photo that you can display in RN.\n\n### Static methods:\n\n### createImageAsset\n~~~js\n  RCTCameraRollRNPhotosFrameworkManager.createImageAsset(imageWithUriProp);\n~~~\nSignature: album.createImageAsset(params) : Promise<Asset>.\nCreate a image-asset\n\n### createVideoAsset\n~~~js\n  RCTCameraRollRNPhotosFrameworkManager.createVideoAsset(videoWithUriProp);\n~~~\nSignature: album.createVideoAsset(params) : Promise<Asset>.\nCreate a image-asset\n\n### createAssets\n~~~js\n  RCTCameraRollRNPhotosFrameworkManager.createAssets({\n    images : [{ uri : 'https://some-uri-local-or-remote.jpg' }],\n    videos : [{ uri : 'https://some-uri-local-or-remote.jpg' }]\n    album : album //(OPTIONAL) some album that you want to add the asset to when it's been added to the library.\n    includeMetadata : true //The result of this function call will return new assets. should this have metadata on them? See docs of getAssets for more info.\n  });\n~~~\nSignature: album.createAssets(params) : Promise<array<Asset>>.\nBase function for creating assets. Will return the successfully created new assets.\nIf the function returns less Assets then you sent as input, the ones not returned did fail.\n\n# Sending assets to server using AJAX\n\nThis library implements the interface `RCTURLRequestHandler`. This means\nit supports sending assets as files with AJAX to your server of choice out of the box.\nYou can send both Images and Videos with your ajax-library of choice.\nThe simplest way of doing this is by doing it the good old way:\n\n~~~js\n//Create a JS object with these props.\n//The only thing required is the asset.uri and a name of the file.\nconst photo = {\n    uri: asset.uri,\n    type: 'image/jpeg',\n    name: 'photo.jpg',\n};\n\nconst body = new FormData();\nbody.append('photo', photo);\nconst xhr = new XMLHttpRequest();\nxhr.open('POST', 'http://your-server-url/upload');\nxhr.send(body);\n~~~\n\n### Ajax-Helper.\n\nThis library does however include a helper to abstract over a simple upload.\nThis helper does promisify and help you to simply sending assets over the wire.\nIt also loads the original filename of the assets and their mimeType before sending.\nYou can supply your own `modifyAssetData` callback to change the name if you want to before \nsending. This helper operates over multiple Assets, so you always give it an array of Assets (Can contain only one item). It will upload the assets async in parallell and give you progress of the overall operation as well (For progressbars etc.).\n\nThis helper sits outside of the rest of the library to not bloat for people not wanting it, and needs to be required/imported seperatly. (See example below).\n\n~~~js\nimport {postAssets} from 'react-native-photos-framework/src/ajax-helper';\nconst ajaxPromise = postAssets(assets, {\n     url: 'http://localhost:3000/upload',\n     headers : {},\n     onProgress: (progressPercentage, details) => {\n         console.log('On Progress called', progressPercentage);\n     },\n     onComplete : (asset, status, responseText, xhr) => {\n         console.log('Asset upload completed successfully');\n     },\n     onError : (asset, status, responseText, xhr) => {\n         console.log('Asset upload failed');\n     },\n     onFinnished : (completedItems) => {\n         console.log('Operation complete');\n     },\n     modifyAssetData : (postableAsset, asset) => {\n         postableAsset.name = `${postableAsset.name}-special-name-maybe-guid.jpg`;\n         return postableAsset;\n     }\n }).then((result) => {\n     console.log('Operation complete, promise resolved', result);\n     return result;\n });\n~~~\n\n\n# Change-Tracking/Observing library changes\nYou can register listeners for library-change-detection on different levels of the api.\n\n## Library-level\nYou can detect globally if the library changed by:\n~~~js\nRNPhotosFramework.onLibraryChange(() => {\n  console.log('Library Change');\n});\n~~~\nNo details provided\n\n## AlbumQueryResult-level\nYou can register a listener that receives updates when any of the albums that result contains\nchanges (Not if their assets change, only the Albums get those messages, see below).\nYou currently receive the following events: `AlbumTitleChanged` (More to come).\n~~~js\nconst unsubscribeFunc = albumsFetchResult.onChange((changeDetails, update) => {\n    if(changeDetails.hasIncrementalChanges) {\n      update((updatedFetchResult) => {\n         this.setState({albumsFetchResult: updatedFetchResult});\n      });\n    } else {\n      //Do full reload here..\n    }\n});\n~~~\nNOTE: If a change occures that affects one of the AlbumQueryResults albums that change will also be passed along to the album.\n\n## Album/Assets-level\nTo receive change-updates on an album's assets you need to supply at least one of these\ntwo arguments when calling `getAssets` on that album:\n`trackInsertsAndDeletes : true` or\n`trackChanges : true`\n(See `Retrieving albums and enumerating their assets` above)\n\nOn an album object you can do:\n~~~js\nconst unsubscribeFunc = album.onChange((changeDetails, update) => {\n  if(changeDetails.hasIncrementalChanges) {\n    //Important! Assets must be supplied in original fetch-order.\n    update(this.state.assets, (updatedAssetArray) => {\n      this.setState({\n        assets : updatedAssetArray\n      });\n    }, \n    //If RNPF needs to retrive more assets to complete the change,\n    //eg. a move happened that moved a previous out of array-index asset into your corrently loaded assets.\n    //Here you can apply a param obj for options on how to load those assets. eg. ´includeMetadata : true´.\n    {\n      includeMetadata : true\n    });\n  }else {\n    //Do full reload here..\n  }\n});\n~~~\nThe update-function will apply the changes to your collection.\n\nCall the unsubscribeFunc in order to unsubscribe from the onChange event.\n~~~js\ncomponentDidUnmount: function () {\n  unsubscribeFunc();\n  album.stopTracking();\n}\n~~~\n\n## Support on Beerpay\nHey dude! Help me out for a couple of :beers:!\n\n[![Beerpay](https://beerpay.io/olofd/react-native-photos-framework/badge.svg?style=beer-square)](https://beerpay.io/olofd/react-native-photos-framework)  [![Beerpay](https://beerpay.io/olofd/react-native-photos-framework/make-wish.svg?style=flat-square)](https://beerpay.io/olofd/react-native-photos-framework?focus=wish)\n"
  },
  {
    "path": "__tests__/change-observer-handler.test.js",
    "content": "import {\n    assetArrayObserverHandler,\n    collectionArrayObserverHandler\n} from '../src/change-observer-handler.js';\n\nfunction toNumberedCollectionIndex(arr) {\n    return arr.reduce((str, asset) => {\n        if (!asset || asset.collectionIndex === undefined || asset.id === undefined) {\n            return 'ERROR';\n        }\n        return str += asset.collectionIndex.toString() + asset.id.toString();\n    }, '');\n}\n\n//START--------------------BASIC FUNCTIONALLITY--------------------START\n\n//START---------SINGULAR ADD--------------START\ndescribe('SINGULAR ADD', () => {\n    it('insert singular in middle of assetCollection with normal order starting from 0', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'b',\n                    collectionIndex: 1\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'c',\n            collectionIndex: 1\n        }, {\n            id: 'd',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1b2c3d');\n        });\n    });\n\n    it('insert singular before array starts should not insert only increment collectionIndecies', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'a',\n                    collectionIndex: 0\n                }\n            }]\n        };\n        const arr = [{\n            id: 'b',\n            collectionIndex: 3\n        }, {\n            id: 'c',\n            collectionIndex: 4\n        }, {\n            id: 'd',\n            collectionIndex: 5\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('4b5c6d');\n        });\n    });\n\n    it('insert singular before array starts should not insert only increment collectionIndecies', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'a',\n                    collectionIndex: 0\n                }\n            }]\n        };\n        const arr = [{\n            id: 'd',\n            collectionIndex: 8\n        }, {\n            id: 'c',\n            collectionIndex: 7\n        }, {\n            id: 'b',\n            collectionIndex: 6\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('9d8c7b');\n        });\n    });\n\n    it('insert singular in middle of assetCollection with normal order starting from 3', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'b',\n                    collectionIndex: 4\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 3\n        }, {\n            id: 'c',\n            collectionIndex: 4\n        }, {\n            id: 'd',\n            collectionIndex: 5\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('3a4b5c6d');\n        });\n    });\n\n    it('insert singular in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'b',\n                    collectionIndex: 2\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 2\n        }, {\n            id: 'c',\n            collectionIndex: 1\n        }, {\n            id: 'd',\n            collectionIndex: 0\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('3a2b1c0d');\n        });\n    });\n});\n//END---------SINGULAR ADD--------------END\n\n//START---------PLURALIS ADD--------------START\ndescribe('PLURALIS ADD', () => {\n    it('insert multiple in middle of assetCollection with normal order', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'a',\n                    collectionIndex: 0\n                }\n            }, {\n                obj: {\n                    id: 'c',\n                    collectionIndex: 2\n                }\n            }]\n        };\n        const arr = [{\n            id: 'b',\n            collectionIndex: 0\n        }, {\n            id: 'd',\n            collectionIndex: 1\n        }, {\n            id: 'e',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1b2c3d4e');\n        });\n    });\n\n    it('insert multiple in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'd',\n                    collectionIndex: 3\n                }\n            }, {\n                obj: {\n                    id: 'e',\n                    collectionIndex: 4\n                }\n            }]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('4e3d2c1b0a');\n        });\n    });\n\n    it('insert multiple in empty collection and expect reversed order', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    id: 'b',\n                    collectionIndex: 0\n                }\n            }, {\n                obj: {\n                    id: 'a',\n                    collectionIndex: 1\n                }\n            }]\n        };\n        const arr = [];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, undefined, 'reversed').then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('1a0b');\n        });\n    });\n\n});\n//END---------PLURALIS ADD--------------END\n\n//START---------SINGULAR REMOVE--------------START\ndescribe('SINGULAR REMOVE', () => {\n    it('remove singular in middle of assetCollection with normal order', () => {\n        const changeDetails = {\n            removedObjects: [{\n                obj: {\n                    id: 'b',\n                    collectionIndex: 1\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1c');\n        });\n    });\n\n    it('remove singular in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            removedObjects: [{\n                obj: {\n                    id: 'c',\n                    collectionIndex: 2\n                }\n            }]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('1b0a');\n        });\n    });\n\n    it('remove singular before array starts should not remove only decrement collectionIndecies, normal', () => {\n        const changeDetails = {\n            removedObjects: [{\n                obj: {\n                    id: 'a',\n                    collectionIndex: 0\n                }\n            }]\n        };\n        const arr = [{\n            id: 'b',\n            collectionIndex: 7\n        }, {\n            id: 'c',\n            collectionIndex: 8\n        }, {\n            id: 'd',\n            collectionIndex: 9\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('6b7c8d');\n        });\n    });\n\n    it('remove singular before array starts should not remove only decrement collectionIndecies, reversed', () => {\n        const changeDetails = {\n            removedObjects: [{\n                obj: {\n                    id: 'a',\n                    collectionIndex: 0\n                }\n            }]\n        };\n        const arr = [{\n            id: 'd',\n            collectionIndex: 3\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('2d1c0b');\n        });\n    });\n});\n\n//END---------SINGULAR REMOVE--------------END\n\n//START---------PLURALIS REMOVE--------------START\ndescribe('PLURALIS REMOVE', () => {\n    it('remove multiple in middle of assetCollection with normal order', () => {\n        const changeDetails = {\n            removedObjects: [\n                //1b2c\n                {\n                    obj: {\n                        id: 'a',\n                        collectionIndex: 1\n                    }\n                },\n                //1b\n                {\n                    obj: {\n                        id: 'c',\n                        collectionIndex: 3\n                    }\n                }\n            ]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 1\n        }, {\n            id: 'b',\n            collectionIndex: 2\n        }, {\n            id: 'c',\n            collectionIndex: 3\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('1b');\n        });\n    });\n\n    it('remove multiple in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            removedObjects: [\n                //2b1a\n                {\n                    obj: {\n                        id: 'c',\n                        collectionIndex: 3\n                    }\n                }, {\n                    obj: {\n                        id: 'a',\n                        collectionIndex: 1\n                    }\n                }\n            ]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 3\n        }, {\n            id: 'b',\n            collectionIndex: 2\n        }, {\n            id: 'a',\n            collectionIndex: 1\n        }];\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('1b');\n        });\n    });\n});\n//END---------PLURALIS REMOVE--------------END\n\n//START---------SINGULAR CHANGE--------------START\ndescribe('SINGULAR CHANGE', () => {\n    it('change singular in middle of assetCollection with normal order', () => {\n        const changeDetails = {\n            changedObjects: [{\n                obj: {\n                    id: 'b-changed',\n                    collectionIndex: 1\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1b-changed2c');\n        });\n    });\n\n    it('change singular in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            changedObjects: [{\n                obj: {\n                    id: 'a-changed',\n                    collectionIndex: 0\n                }\n            }]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('2c1b0a-changed');\n        });\n    });\n});\n\n//END---------SINGULAR CHANGE--------------END\n\n//START---------PLURALIS CHANGE--------------START\ndescribe('PLURALIS CHANGE', () => {\n    it('change multiple in middle of assetCollection with normal order', () => {\n        const changeDetails = {\n            changedObjects: [{\n                obj: {\n                    id: 'a-changed',\n                    collectionIndex: 0\n                }\n            }, {\n                obj: {\n                    id: 'c-changed',\n                    collectionIndex: 2\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a-changed1b2c-changed');\n        });\n    });\n\n    it('change multiple in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            changedObjects: [{\n                obj: {\n                    id: 'c-changed',\n                    collectionIndex: 2\n                }\n            }, {\n                obj: {\n                    id: 'a-changed',\n                    collectionIndex: 0\n                }\n            }]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('2c-changed1b0a-changed');\n        });\n    });\n});\n//END---------PLURALIS CHANGE--------------END\n\n//START---------SINGULAR MOVE--------------START\ndescribe('SINGULAR MOVE', () => {\n    it('move singular in middle of assetCollection with normal order', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [1, 2, 2, 1]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1c2b');\n        });\n    });\n\n    it('move singular in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            moves: [1, 2, 2, 1]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('2b1c0a');\n        });\n    });\n});\n\n//END---------SINGULAR MOVE--------------END\n\n//START---------PLURALIS MOVE--------------START\ndescribe('PLURALIS MOVE', () => {\n    it('move pluralis in middle of assetCollection with normal order', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [0, 2, 2, 0, 3, 1, 1, 3]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'd',\n            collectionIndex: 3\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0c1d2a3b');\n        });\n    });\n\n    it('move pluralis in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            moves: [0, 2, 2, 0, 3, 1, 1, 3]\n        };\n        const arr = [{\n            id: 'd',\n            collectionIndex: 3\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('3b2a1d0c');\n        });\n    });\n});\n\n//END---------PLURALIS MOVE--------------END\n//END--------------------BASIC FUNCTIONALLITY--------------------END\n\n\n//START--------------------EDGE CASES AND OUTSIDE INDEX CHANGES--------------------START\n//START---------EDGES--------------START\ndescribe('ERRONEOUS INPUT', () => {\n    it('should throw when input is scrambled', () => {\n        const changeDetails = {\n            insertedObjects: [{\n                obj: {\n                    collectionIndex: 1\n                }\n            }]\n        };\n        const arr = [{\n            collectionIndex: 1\n        }, {\n            collectionIndex: 0\n        }, {\n            collectionIndex: 2\n        }];\n        expect(() => {\n            return assetArrayObserverHandler(changeDetails, arr, (obj) => {});\n        }).toThrow();\n    });\n});\n\nit('should do nothing to input if hasIncrementalChanges is false', () => {\n    const changeDetails = {\n        hasIncrementalChanges: false,\n        insertedObjects: [{\n            obj: {\n                id: 'b',\n                collectionIndex: 1\n            }\n        }]\n    };\n    const arr = [{\n        id: 'a',\n        collectionIndex: 0\n    }, {\n        id: 'c',\n        collectionIndex: 1\n    }, {\n        id: 'd',\n        collectionIndex: 2\n    }];\n\n    return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n        return obj;\n    }).then((result) => {\n        expect(toNumberedCollectionIndex(result)).toBe('0a1c2d');\n    });\n});\n//END---------EDGES--------------END\n\n//START---------OUTSIDE INDEX MOVE--------------START\ndescribe('OUTSIDE INDEX MOVE', () => {\n    it('move asset from outside of index bounds should trigger fetch request', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [1, 3, 3, 1]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n\n        let f = jest.fn();\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, (missingIndecies, finnishFunc) => {\n            expect(missingIndecies[0]).toBe(1);\n            finnishFunc();\n        }).then((result) => {});\n    });\n\n    it('moves outside of collection should not change collection', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [5, 6, 6, 7]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 1\n        }, {\n            id: 'b',\n            collectionIndex: 2\n        }, {\n            id: 'c',\n            collectionIndex: 3\n        }];\n\n        let f = jest.fn();\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, f).then((result) => {\n            expect(f).not.toHaveBeenCalled();\n            expect(toNumberedCollectionIndex(result)).toBe('1a2b3c');\n        });\n    });\n\n    it('moves from side to side should not change collection', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [0, 4, 4, 0]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 1\n        }, {\n            id: 'b',\n            collectionIndex: 2\n        }, {\n            id: 'c',\n            collectionIndex: 3\n        }];\n\n        let f = jest.fn();\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, f).then((result) => {\n            expect(f).not.toHaveBeenCalled();\n            expect(toNumberedCollectionIndex(result)).toBe('1a2b3c');\n        });\n    });\n\n    it('move singular asset from outside of index bounds should trigger fetch request and insert that index', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [1, 5, 5, 1]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'e',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, (arrayOfMissingIndecies, finnishFunc) => {\n            return finnishFunc(arrayOfMissingIndecies.map((index) => {\n                return {\n                    collectionIndex: index,\n                    id: 'b'\n                }\n            }));\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1b2c');\n        });\n    });\n\n    it('move pluralis assets from outside of index bounds should trigger fetch request and insert at those indecies', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [5, 1, 1, 5, 2, 7, 7, 2]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'e',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, (arrayOfMissingIndecies, finnishFunc) => {\n            return finnishFunc(arrayOfMissingIndecies.map((index) => {\n                return {\n                    collectionIndex: index,\n                    id: index === 1 ? 'b' : 'c'\n                }\n            }));\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1b2c');\n        });\n    });\n\n    it('move pluralis assets from outside of index bounds, if asset is not returned return non-error-output', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [5, 1, 1, 5, 2, 7, 7, 2]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'e',\n            collectionIndex: 1\n        }, {\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'd',\n            collectionIndex: 3\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, (arrayOfMissingIndecies, finnishFunc) => {\n            return finnishFunc([{\n                collectionIndex: 1,\n                id: 'b'\n            }]);\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1b2d');\n        });\n    });\n\n    it('should be able to handle simple out of index move', () => {\n        //Changes in position always happens like this, in paired atomic steps:\n        const changeDetails = {\n            moves: [1, 0, 0, 1]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'a',\n            collectionIndex: 1\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, (arrayOfMissingIndecies, finnishFunc) => {\n            expect(arrayOfMissingIndecies[0]).toBe(1);\n            finnishFunc([{\n                collectionIndex: 1,\n                id: 'b'\n            }]);\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('2c1b');\n        });\n    });\n\n    it('move singular in middle of assetCollection with reversed order', () => {\n        const changeDetails = {\n            moves: [1, 2, 2, 1]\n        };\n        const arr = [{\n            id: 'c',\n            collectionIndex: 2\n        }, {\n            id: 'b',\n            collectionIndex: 1\n        }, {\n            id: 'a',\n            collectionIndex: 0\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('2b1c0a');\n        });\n    });\n});\n\n//END---------OUTSIDE INDEX MOVE--------------END\n\n//START---------MIXED OPAERTAIONS--------------START\n\ndescribe('MIXED OPERATIONS', () => {\n    it('Handle a mixed operation with REMOVE, INSERT, MOVE and CHANGE', () => {\n        const changeDetails = {\n            removedObjects: [{\n                obj: {\n                    id: 'c',\n                    collectionIndex: 1\n                }\n            }],\n            insertedObjects: [{\n                obj: {\n                    id: 'x',\n                    collectionIndex: 0\n                }\n            }],\n            moves: [0, 1, 1, 0, 9, 7, 7, 9],\n            changedObjects: [{\n                obj: {\n                    id: 'k',\n                    collectionIndex: 1\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 0\n        }, {\n            id: 'c',\n            collectionIndex: 1\n        }, {\n            id: 'd',\n            collectionIndex: 2\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, () => {}, 'normal', (step, arr) => {\n            if (step === 'remove') {\n                expect(toNumberedCollectionIndex(arr)).toBe('0a1d');\n            }\n            if (step === 'insert') {\n                expect(toNumberedCollectionIndex(arr)).toBe('0x1a2d');\n            }\n            if (step === 'move') {\n                expect(toNumberedCollectionIndex(arr)).toBe('0a1x2d');\n            }\n            if (step === 'change') {\n                expect(toNumberedCollectionIndex(arr)).toBe('0a1k2d');\n            }\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('0a1k2d');\n        });\n    });\n\n    it('Handle a mixed operation with REMOVE, INSERT, MOVE and CHANGE with normal indecies and fetches', () => {\n        const changeDetails = {\n            insertedObjects: [\n                //6g5f4d\n                {\n                    obj: {\n                        id: 'a',\n                        collectionIndex: 0\n                    }\n                }, {\n                    obj: {\n                        id: 'e',\n                        collectionIndex: 4\n                    }\n                }\n            ]\n        };\n        const arr = [{\n            id: 'd',\n            collectionIndex: 3\n        }, {\n            id: 'f',\n            collectionIndex: 4\n        }, {\n            id: 'g',\n            collectionIndex: 5\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, () => {}, 'normal', (step, arr) => {\n            if (step === 'insert') {\n                expect(toNumberedCollectionIndex(arr)).toBe('4e5d6f7g');\n            }\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('4e5d6f7g');\n        });\n    });\n\n    it('Handle a mixed operation with REMOVE, INSERT, MOVE and CHANGE with reverse indecies and fetches', () => {\n        const changeDetails = {\n            insertedObjects: [\n                //6g5f4d\n                {\n                    obj: {\n                        id: 'a',\n                        collectionIndex: 0\n                    }\n                }, {\n                    obj: {\n                        id: 'e',\n                        collectionIndex: 4\n                    }\n                }\n            ]\n        };\n        const arr = [{\n            id: 'g',\n            collectionIndex: 5\n        }, {\n            id: 'f',\n            collectionIndex: 4\n        }, {\n            id: 'd',\n            collectionIndex: 3\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, () => {}, 'normal', (step, arr) => {\n            if (step === 'insert') {\n                expect(toNumberedCollectionIndex(arr)).toBe('7g6f5d4e');\n            }\n        }).then((result) => {\n            expect(toNumberedCollectionIndex(result)).toBe('7g6f5d4e');\n        });\n    });\n\n    it('Handle a mixed operation with REMOVE, INSERT, MOVE and CHANGE with reverse indecies and fetches', () => {\n        const changeDetails = {\n            removedObjects: [{\n                obj: {\n                    id: 'd',\n                    collectionIndex: 3\n                }\n            }],\n            insertedObjects: [{\n                obj: {\n                    id: 'q',\n                    collectionIndex: 0\n                }\n            }, {\n                obj: {\n                    id: 'x',\n                    collectionIndex: 9\n                }\n            }, {\n                obj: {\n                    id: 'g',\n                    collectionIndex: 6\n                }\n            }, {\n                obj: {\n                    id: 'h',\n                    collectionIndex: 4\n                }\n            }],\n            moves: [3, 4, 4, 3],\n            changedObjects: [{\n                obj: {\n                    id: 'k',\n                    collectionIndex: 5\n                }\n            }]\n        };\n        const arr = [{\n            id: 'a',\n            collectionIndex: 3\n        }, {\n            id: 'c',\n            collectionIndex: 4\n        }, {\n            id: 'd',\n            collectionIndex: 5\n        }];\n\n        return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n            return obj;\n        }, (indecies, finnishFunc) => {\n            expect(indecies[0]).toBe(4);\n            finnishFunc([{\n                collectionIndex: 4,\n                id: 'q'\n            }]);\n        }, 'normal', (step, arr) => {\n            if (step === 'remove') {\n                expect(toNumberedCollectionIndex(arr)).toBe('3c4d');\n            }\n            if (step === 'insert') {\n                expect(toNumberedCollectionIndex(arr)).toBe('4h5c6d7g');\n            }\n            if (step === 'move') {\n                expect(toNumberedCollectionIndex(arr)).toBe('4q5c6d7g');\n            }\n            if (step === 'change') {\n                expect(toNumberedCollectionIndex(arr)).toBe('4q5k6d7g');\n            }\n        }).then((result) => {\n             expect(toNumberedCollectionIndex(result)).toBe('4q5k6d7g');\n        });\n    });\n});\n\nit('should do nothing to input if hasIncrementalChanges is false', () => {\n    const changeDetails = {\n        hasIncrementalChanges: false,\n        insertedObjects: [{\n            obj: {\n                id: 'b',\n                collectionIndex: 1\n            }\n        }]\n    };\n    const arr = [{\n        id: 'a',\n        collectionIndex: 0\n    }, {\n        id: 'c',\n        collectionIndex: 1\n    }, {\n        id: 'd',\n        collectionIndex: 2\n    }];\n\n    return assetArrayObserverHandler(changeDetails, arr, (obj) => {\n        return obj;\n    }).then((result) => {\n        expect(toNumberedCollectionIndex(result)).toBe('0a1c2d');\n    });\n});\n\n//END---------MIXED OPAERTAIONS--------------END\n\n\n//END--------------------EDGE CASES AND OUTSIDE INDEX CHANGES--------------------END"
  },
  {
    "path": "event-emitter.js",
    "content": "import EventEmitter from '../react-native/Libraries/vendor/emitter/EventEmitter';\nexport default EventEmitter;"
  },
  {
    "path": "example/.babelrc",
    "content": "{\n\"presets\": [\"react-native\"]\n}"
  },
  {
    "path": "example/.buckconfig",
    "content": "\n[android]\n  target = Google Inc.:Google APIs:23\n\n[maven_repositories]\n  central = https://repo1.maven.org/maven2\n"
  },
  {
    "path": "example/.flowconfig",
    "content": "[ignore]\n; We fork some components by platform\n.*/*[.]android.js\n\n; Ignore \"BUCK\" generated dirs\n<PROJECT_ROOT>/\\.buckd/\n\n; Ignore unexpected extra \"@providesModule\"\n.*/node_modules/.*/node_modules/fbjs/.*\n\n; Ignore duplicate module providers\n; For RN Apps installed via npm, \"Libraries\" folder is inside\n; \"node_modules/react-native\" but in the source repo it is in the root\n.*/Libraries/react-native/React.js\n.*/Libraries/react-native/ReactNative.js\n\n[include]\n\n[libs]\nnode_modules/react-native/Libraries/react-native/react-native-interface.js\nnode_modules/react-native/flow\nflow/\n\n[options]\nmodule.system=haste\n\nexperimental.strict_type_args=true\n\nmunge_underscores=true\n\nmodule.name_mapper='^[./a-zA-Z0-9$_-]+\\.\\(bmp\\|gif\\|jpg\\|jpeg\\|png\\|psd\\|svg\\|webp\\|m4v\\|mov\\|mp4\\|mpeg\\|mpg\\|webm\\|aac\\|aiff\\|caf\\|m4a\\|mp3\\|wav\\|html\\|pdf\\)$' -> 'RelativeImageStub'\n\nsuppress_type=$FlowIssue\nsuppress_type=$FlowFixMe\nsuppress_type=$FixMe\n\nsuppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowFixMe\\\\($\\\\|[^(]\\\\|(\\\\(>=0\\\\.\\\\(3[0-6]\\\\|[1-2][0-9]\\\\|[0-9]\\\\).[0-9]\\\\)? *\\\\(site=[a-z,_]*react_native[a-z,_]*\\\\)?)\\\\)\nsuppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowIssue\\\\((\\\\(>=0\\\\.\\\\(3[0-6]\\\\|1[0-9]\\\\|[1-2][0-9]\\\\).[0-9]\\\\)? *\\\\(site=[a-z,_]*react_native[a-z,_]*\\\\)?)\\\\)?:? #[0-9]+\nsuppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowFixedInNextDeploy\n\nunsafe.enable_getters_and_setters=true\n\n[version]\n^0.36.0\n"
  },
  {
    "path": "example/.gitattributes",
    "content": "*.pbxproj -text\n"
  },
  {
    "path": "example/.gitignore",
    "content": "# OSX\n#\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\nproject.xcworkspace\n\n# Android/IntelliJ\n#\nbuild/\n.idea\n.gradle\nlocal.properties\n*.iml\n\n# node.js\n#\nnode_modules/\nnpm-debug.log\n\n# BUCK\nbuck-out/\n\\.buckd/\nandroid/app/libs\n*.keystore\n\n# fastlane\n#\n# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the\n# screenshots whenever they are needed.\n# For more information about the recommended setup visit:\n# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md\n\nfastlane/report.xml\nfastlane/Preview.html\nfastlane/screenshots\n"
  },
  {
    "path": "example/.npmignore",
    "content": "Example\ndemo\n"
  },
  {
    "path": "example/.vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Debug Android\",\n            \"program\": \"${workspaceRoot}/.vscode/launchReactNative.js\",\n            \"type\": \"reactnative\",\n            \"request\": \"launch\",\n            \"platform\": \"android\",\n            \"internalDebuggerPort\": 9090,\n            \"sourceMaps\": true,\n            \"outDir\": \"${workspaceRoot}/.vscode/.react\"\n        },\n        {\n            \"name\": \"Debug iOS\",\n            \"program\": \"${workspaceRoot}/.vscode/launchReactNative.js\",\n            \"type\": \"reactnative\",\n            \"request\": \"launch\",\n            \"platform\": \"ios\",\n            \"target\": \"iPhone 6s\",\n            \"internalDebuggerPort\": 9090,\n            \"sourceMaps\": true,\n            \"outDir\": \"${workspaceRoot}/.vscode/.react\"\n        },\n        {\n            \"name\": \"Attach to packager\",\n            \"program\": \"${workspaceRoot}/.vscode/launchReactNative.js\",\n            \"type\": \"reactnative\",\n            \"request\": \"attach\",\n            \"internalDebuggerPort\": 9090,\n            \"sourceMaps\": true,\n            \"outDir\": \"${workspaceRoot}/.vscode/.react\"\n        },\n        {\n            \"name\": \"Debug in Exponent\",\n            \"program\": \"${workspaceRoot}/.vscode/launchReactNative.js\",\n            \"type\": \"reactnative\",\n            \"request\": \"launch\",\n            \"platform\": \"exponent\",\n            \"internalDebuggerPort\": 9090,\n            \"sourceMaps\": true,\n            \"outDir\": \"${workspaceRoot}/.vscode/.react\"\n        }\n    ]\n}"
  },
  {
    "path": "example/.vscode/launchReactNative.js",
    "content": "// This file is automatically generated by vscode-react-native@0.2.1\n// Please do not modify it manually. All changes will be lost.\ntry {\n    var path = require(\"path\");\n    var Launcher = require(\"/Users/olda/.vscode/extensions/vsmobile.vscode-react-native-0.2.1/out/debugger/launcher.js\").Launcher;\n    new Launcher(path.resolve(__dirname, \"..\")).launch();\n} catch (e) {\n    throw new Error(\"Unable to launch application. Try deleting .vscode/launchReactNative.js and restarting vscode.\");\n}"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-create-fragment.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-create-fragment)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    namespace __Addons {\n        export function createFragment(object: { [key: string]: ReactNode }): ReactFragment;\n    }\n}\n\ndeclare module \"react-addons-create-fragment\" {\n    export = __React.__Addons.createFragment;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-css-transition-group.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-css-transition-group)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n/// <reference path=\"react-addons-transition-group.d.ts\" />\n\ndeclare namespace __React {\n    interface CSSTransitionGroupTransitionName {\n        enter: string;\n        enterActive?: string;\n        leave: string;\n        leaveActive?: string;\n        appear?: string;\n        appearActive?: string;\n    }\n\n    interface CSSTransitionGroupProps extends TransitionGroupProps {\n        transitionName: string | CSSTransitionGroupTransitionName;\n        transitionAppear?: boolean;\n        transitionAppearTimeout?: number;\n        transitionEnter?: boolean;\n        transitionEnterTimeout?: number;\n        transitionLeave?: boolean;\n        transitionLeaveTimeout?: number;\n    }\n\n    type CSSTransitionGroup = ComponentClass<CSSTransitionGroupProps>;\n\n    namespace __Addons {\n        export var CSSTransitionGroup: __React.CSSTransitionGroup;\n    }\n}\n\ndeclare module \"react-addons-css-transition-group\" {\n    var CSSTransitionGroup: __React.CSSTransitionGroup;\n    type CSSTransitionGroup = __React.CSSTransitionGroup;\n    export = CSSTransitionGroup;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-linked-state-mixin.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-linked-state-mixin)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface ReactLink<T> {\n        value: T;\n        requestChange(newValue: T): void;\n    }\n\n    interface LinkedStateMixin extends Mixin<any, any> {\n        linkState<T>(key: string): ReactLink<T>;\n    }\n\n    interface HTMLAttributes {\n        checkedLink?: ReactLink<boolean>;\n        valueLink?: ReactLink<boolean | string | number>;\n    }\n\n    namespace __Addons {\n        export var LinkedStateMixin: LinkedStateMixin;\n    }\n}\n\ndeclare module \"react-addons-linked-state-mixin\" {\n    var LinkedStateMixin: __React.LinkedStateMixin;\n    type LinkedStateMixin = __React.LinkedStateMixin;\n    export = LinkedStateMixin;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-perf.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-perf)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface ComponentPerfContext {\n        current: string;\n        owner: string;\n    }\n\n    interface NumericPerfContext {\n        [key: string]: number;\n    }\n\n    interface Measurements {\n        exclusive: NumericPerfContext;\n        inclusive: NumericPerfContext;\n        render: NumericPerfContext;\n        counts: NumericPerfContext;\n        writes: NumericPerfContext;\n        displayNames: {\n            [key: string]: ComponentPerfContext;\n        };\n        totalTime: number;\n    }\n\n    namespace __Addons {\n        namespace Perf {\n            export function start(): void;\n            export function stop(): void;\n            export function printInclusive(measurements: Measurements[]): void;\n            export function printExclusive(measurements: Measurements[]): void;\n            export function printWasted(measurements: Measurements[]): void;\n            export function printDOM(measurements: Measurements[]): void;\n            export function getLastMeasurements(): Measurements[];\n        }\n    }\n}\n\ndeclare module \"react-addons-perf\" {\n    import Perf = __React.__Addons.Perf;\n    export = Perf;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-pure-render-mixin.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-pure-render-mixin)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface PureRenderMixin extends Mixin<any, any> {}\n\n    namespace __Addons {\n        export var PureRenderMixin: PureRenderMixin;\n    }\n}\n\ndeclare module \"react-addons-pure-render-mixin\" {\n    var PureRenderMixin: __React.PureRenderMixin;\n    type PureRenderMixin = __React.PureRenderMixin;\n    export = PureRenderMixin;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-test-utils.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-test-utils)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface SyntheticEventData {\n        altKey?: boolean;\n        button?: number;\n        buttons?: number;\n        clientX?: number;\n        clientY?: number;\n        changedTouches?: TouchList;\n        charCode?: boolean;\n        clipboardData?: DataTransfer;\n        ctrlKey?: boolean;\n        deltaMode?: number;\n        deltaX?: number;\n        deltaY?: number;\n        deltaZ?: number;\n        detail?: number;\n        getModifierState?(key: string): boolean;\n        key?: string;\n        keyCode?: number;\n        locale?: string;\n        location?: number;\n        metaKey?: boolean;\n        pageX?: number;\n        pageY?: number;\n        relatedTarget?: EventTarget;\n        repeat?: boolean;\n        screenX?: number;\n        screenY?: number;\n        shiftKey?: boolean;\n        targetTouches?: TouchList;\n        touches?: TouchList;\n        view?: AbstractView;\n        which?: number;\n    }\n\n    interface EventSimulator {\n        (element: Element, eventData?: SyntheticEventData): void;\n        (component: Component<any, any>, eventData?: SyntheticEventData): void;\n    }\n\n    interface MockedComponentClass {\n        new(): any;\n    }\n\n    class ShallowRenderer {\n        getRenderOutput<E extends ReactElement<any>>(): E;\n        getRenderOutput(): ReactElement<any>;\n        render(element: ReactElement<any>, context?: any): void;\n        unmount(): void;\n    }\n\n    namespace __Addons {\n        namespace TestUtils {\n            namespace Simulate {\n                export var blur: EventSimulator;\n                export var change: EventSimulator;\n                export var click: EventSimulator;\n                export var cut: EventSimulator;\n                export var doubleClick: EventSimulator;\n                export var drag: EventSimulator;\n                export var dragEnd: EventSimulator;\n                export var dragEnter: EventSimulator;\n                export var dragExit: EventSimulator;\n                export var dragLeave: EventSimulator;\n                export var dragOver: EventSimulator;\n                export var dragStart: EventSimulator;\n                export var drop: EventSimulator;\n                export var focus: EventSimulator;\n                export var input: EventSimulator;\n                export var keyDown: EventSimulator;\n                export var keyPress: EventSimulator;\n                export var keyUp: EventSimulator;\n                export var mouseDown: EventSimulator;\n                export var mouseEnter: EventSimulator;\n                export var mouseLeave: EventSimulator;\n                export var mouseMove: EventSimulator;\n                export var mouseOut: EventSimulator;\n                export var mouseOver: EventSimulator;\n                export var mouseUp: EventSimulator;\n                export var paste: EventSimulator;\n                export var scroll: EventSimulator;\n                export var submit: EventSimulator;\n                export var touchCancel: EventSimulator;\n                export var touchEnd: EventSimulator;\n                export var touchMove: EventSimulator;\n                export var touchStart: EventSimulator;\n                export var wheel: EventSimulator;\n            }\n\n            export function renderIntoDocument(\n                element: DOMElement<any>): Element;\n            export function renderIntoDocument<P>(\n                element: ReactElement<P>): Component<P, any>;\n            export function renderIntoDocument<C extends Component<any, any>>(\n                element: ReactElement<any>): C;\n\n            export function mockComponent(\n                mocked: MockedComponentClass, mockTagName?: string): typeof TestUtils;\n\n            export function isElementOfType(\n                element: ReactElement<any>, type: ReactType): boolean;\n            export function isDOMComponent(instance: ReactInstance): boolean;\n            export function isCompositeComponent(instance: ReactInstance): boolean;\n            export function isCompositeComponentWithType(\n                instance: ReactInstance,\n                type: ComponentClass<any>): boolean;\n\n            export function findAllInRenderedTree(\n                root: Component<any, any>,\n                fn: (i: ReactInstance) => boolean): ReactInstance[];\n\n            export function scryRenderedDOMComponentsWithClass(\n                root: Component<any, any>,\n                className: string): Element[];\n            export function findRenderedDOMComponentWithClass(\n                root: Component<any, any>,\n                className: string): Element;\n\n            export function scryRenderedDOMComponentsWithTag(\n                root: Component<any, any>,\n                tagName: string): Element[];\n            export function findRenderedDOMComponentWithTag(\n                root: Component<any, any>,\n                tagName: string): Element;\n\n            export function scryRenderedComponentsWithType<P>(\n                root: Component<any, any>,\n                type: ComponentClass<P>): Component<P, {}>[];\n            export function scryRenderedComponentsWithType<C extends Component<any, any>>(\n                root: Component<any, any>,\n                type: ComponentClass<any>): C[];\n\n            export function findRenderedComponentWithType<P>(\n                root: Component<any, any>,\n                type: ComponentClass<P>): Component<P, {}>;\n            export function findRenderedComponentWithType<C extends Component<any, any>>(\n                root: Component<any, any>,\n                type: ComponentClass<any>): C;\n\n            export function createRenderer(): ShallowRenderer;\n        }\n    }\n}\n\ndeclare module \"react-addons-test-utils\" {\n    import TestUtils = __React.__Addons.TestUtils;\n    export = TestUtils;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-transition-group.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-transition-group)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n\n    interface TransitionGroupProps {\n        component?: ReactType;\n        childFactory?: (child: ReactElement<any>) => ReactElement<any>;\n    }\n\n    type TransitionGroup = ComponentClass<TransitionGroupProps>;\n\n    namespace __Addons {\n        export var TransitionGroup: __React.TransitionGroup;\n    }\n}\n\ndeclare module \"react-addons-transition-group\" {\n    var TransitionGroup: __React.TransitionGroup;\n    type TransitionGroup = __React.TransitionGroup;\n    export = TransitionGroup;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-addons-update.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-update)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface UpdateSpecCommand {\n        $set?: any;\n        $merge?: {};\n        $apply?(value: any): any;\n    }\n\n    interface UpdateSpecPath {\n        [key: string]: UpdateSpec;\n    }\n\n    type UpdateSpec = UpdateSpecCommand | UpdateSpecPath;\n\n    interface UpdateArraySpec extends UpdateSpecCommand {\n        $push?: any[];\n        $unshift?: any[];\n        $splice?: any[][];\n    }\n\n    namespace __Addons {\n        export function update(value: any[], spec: UpdateArraySpec): any[];\n        export function update(value: {}, spec: UpdateSpec): any;\n    }\n}\n\ndeclare module \"react-addons-update\" {\n    export = __React.__Addons.update;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-dom.d.ts",
    "content": "// Type definitions for React v0.14 (react-dom)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    namespace __DOM {\n        function findDOMNode<E extends Element>(instance: ReactInstance): E;\n        function findDOMNode(instance: ReactInstance): Element;\n\n        function render<P>(\n            element: DOMElement<P>,\n            container: Element,\n            callback?: (element: Element) => any): Element;\n        function render<P, S>(\n            element: ClassicElement<P>,\n            container: Element,\n            callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;\n        function render<P, S>(\n            element: ReactElement<P>,\n            container: Element,\n            callback?: (component: Component<P, S>) => any): Component<P, S>;\n\n        function unmountComponentAtNode(container: Element): boolean;\n\n        var version: string;\n\n        function unstable_batchedUpdates<A, B>(callback: (a: A, b: B) => any, a: A, b: B): void;\n        function unstable_batchedUpdates<A>(callback: (a: A) => any, a: A): void;\n        function unstable_batchedUpdates(callback: () => any): void;\n\n        function unstable_renderSubtreeIntoContainer<P>(\n            parentComponent: Component<any, any>,\n            nextElement: DOMElement<P>,\n            container: Element,\n            callback?: (element: Element) => any): Element;\n        function unstable_renderSubtreeIntoContainer<P, S>(\n            parentComponent: Component<any, any>,\n            nextElement: ClassicElement<P>,\n            container: Element,\n            callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;\n        function unstable_renderSubtreeIntoContainer<P, S>(\n            parentComponent: Component<any, any>,\n            nextElement: ReactElement<P>,\n            container: Element,\n            callback?: (component: Component<P, S>) => any): Component<P, S>;\n    }\n\n    namespace __DOMServer {\n        function renderToString(element: ReactElement<any>): string;\n        function renderToStaticMarkup(element: ReactElement<any>): string;\n        var version: string;\n    }\n}\n\ndeclare module \"react-dom\" {\n    import DOM = __React.__DOM;\n    export = DOM;\n}\n\ndeclare module \"react-dom/server\" {\n    import DOMServer = __React.__DOMServer;\n    export = DOMServer;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react-global.d.ts",
    "content": "// Type definitions for React v0.14 (namespace)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n/// <reference path=\"react-dom.d.ts\" />\n/// <reference path=\"react-addons-create-fragment.d.ts\" />\n/// <reference path=\"react-addons-css-transition-group.d.ts\" />\n/// <reference path=\"react-addons-linked-state-mixin.d.ts\" />\n/// <reference path=\"react-addons-perf.d.ts\" />\n/// <reference path=\"react-addons-pure-render-mixin.d.ts\" />\n/// <reference path=\"react-addons-test-utils.d.ts\" />\n/// <reference path=\"react-addons-transition-group.d.ts\" />\n/// <reference path=\"react-addons-update.d.ts\" />\n\nimport React = __React;\nimport ReactDOM = __React.__DOM;\n\ndeclare namespace __React {\n    export import addons = __React.__Addons;\n}\n"
  },
  {
    "path": "example/.vscode/typings/react/react.d.ts",
    "content": "// Type definitions for React v0.14\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\ndeclare namespace __React {\n\n    //\n    // React Elements\n    // ----------------------------------------------------------------------\n\n    type ReactType = string | ComponentClass<any> | StatelessComponent<any>;\n\n    interface ReactElement<P extends Props<any>> {\n        type: string | ComponentClass<P> | StatelessComponent<P>;\n        props: P;\n        key: string | number;\n        ref: string | ((component: Component<P, any> | Element) => any);\n    }\n\n    interface ClassicElement<P> extends ReactElement<P> {\n        type: ClassicComponentClass<P>;\n        ref: string | ((component: ClassicComponent<P, any>) => any);\n    }\n\n    interface DOMElement<P extends Props<Element>> extends ReactElement<P> {\n        type: string;\n        ref: string | ((element: Element) => any);\n    }\n\n    interface ReactHTMLElement extends DOMElement<HTMLProps<HTMLElement>> {\n        ref: string | ((element: HTMLElement) => any);\n    }\n\n    interface ReactSVGElement extends DOMElement<SVGProps> {\n        ref: string | ((element: SVGElement) => any);\n    }\n\n    //\n    // Factories\n    // ----------------------------------------------------------------------\n\n    interface Factory<P> {\n        (props?: P, ...children: ReactNode[]): ReactElement<P>;\n    }\n\n    interface ClassicFactory<P> extends Factory<P> {\n        (props?: P, ...children: ReactNode[]): ClassicElement<P>;\n    }\n\n    interface DOMFactory<P extends Props<Element>> extends Factory<P> {\n        (props?: P, ...children: ReactNode[]): DOMElement<P>;\n    }\n\n    type HTMLFactory = DOMFactory<HTMLProps<HTMLElement>>;\n    type SVGFactory = DOMFactory<SVGProps>;\n\n    //\n    // React Nodes\n    // http://facebook.github.io/react/docs/glossary.html\n    // ----------------------------------------------------------------------\n\n    type ReactText = string | number;\n    type ReactChild = ReactElement<any> | ReactText;\n\n    // Should be Array<ReactNode> but type aliases cannot be recursive\n    type ReactFragment = {} | Array<ReactChild | any[] | boolean>;\n    type ReactNode = ReactChild | ReactFragment | boolean;\n\n    //\n    // Top Level API\n    // ----------------------------------------------------------------------\n\n    function createClass<P, S>(spec: ComponentSpec<P, S>): ClassicComponentClass<P>;\n\n    function createFactory<P>(type: string): DOMFactory<P>;\n    function createFactory<P>(type: ClassicComponentClass<P>): ClassicFactory<P>;\n    function createFactory<P>(type: ComponentClass<P> | StatelessComponent<P>): Factory<P>;\n\n    function createElement<P>(\n        type: string,\n        props?: P,\n        ...children: ReactNode[]): DOMElement<P>;\n    function createElement<P>(\n        type: ClassicComponentClass<P>,\n        props?: P,\n        ...children: ReactNode[]): ClassicElement<P>;\n    function createElement<P>(\n        type: ComponentClass<P> | StatelessComponent<P>,\n        props?: P,\n        ...children: ReactNode[]): ReactElement<P>;\n\n    function cloneElement<P>(\n        element: DOMElement<P>,\n        props?: P,\n        ...children: ReactNode[]): DOMElement<P>;\n    function cloneElement<P>(\n        element: ClassicElement<P>,\n        props?: P,\n        ...children: ReactNode[]): ClassicElement<P>;\n    function cloneElement<P>(\n        element: ReactElement<P>,\n        props?: P,\n        ...children: ReactNode[]): ReactElement<P>;\n\n    function isValidElement(object: {}): boolean;\n\n    var DOM: ReactDOM;\n    var PropTypes: ReactPropTypes;\n    var Children: ReactChildren;\n\n    //\n    // Component API\n    // ----------------------------------------------------------------------\n\n    type ReactInstance = Component<any, any> | Element;\n\n    // Base component for plain JS classes\n    class Component<P, S> implements ComponentLifecycle<P, S> {\n        constructor(props?: P, context?: any);\n        setState(f: (prevState: S, props: P) => S, callback?: () => any): void;\n        setState(state: S, callback?: () => any): void;\n        forceUpdate(callBack?: () => any): void;\n        render(): JSX.Element;\n        props: P;\n        state: S;\n        context: {};\n        refs: {\n            [key: string]: ReactInstance\n        };\n    }\n\n    interface ClassicComponent<P, S> extends Component<P, S> {\n        replaceState(nextState: S, callback?: () => any): void;\n        isMounted(): boolean;\n        getInitialState?(): S;\n    }\n\n    interface ChildContextProvider<CC> {\n        getChildContext(): CC;\n    }\n\n    //\n    // Class Interfaces\n    // ----------------------------------------------------------------------\n\n    interface StatelessComponent<P> {\n        (props?: P, context?: any): ReactElement<any>;\n        propTypes?: ValidationMap<P>;\n        contextTypes?: ValidationMap<any>;\n        defaultProps?: P;\n        displayName?: string;\n    }\n\n    interface ComponentClass<P> {\n        new(props?: P, context?: any): Component<P, any>;\n        propTypes?: ValidationMap<P>;\n        contextTypes?: ValidationMap<any>;\n        childContextTypes?: ValidationMap<any>;\n        defaultProps?: P;\n    }\n\n    interface ClassicComponentClass<P> extends ComponentClass<P> {\n        new(props?: P, context?: any): ClassicComponent<P, any>;\n        getDefaultProps?(): P;\n        displayName?: string;\n    }\n\n    //\n    // Component Specs and Lifecycle\n    // ----------------------------------------------------------------------\n\n    interface ComponentLifecycle<P, S> {\n        componentWillMount?(): void;\n        componentDidMount?(): void;\n        componentWillReceiveProps?(nextProps: P, nextContext: any): void;\n        shouldComponentUpdate?(nextProps: P, nextState: S, nextContext: any): boolean;\n        componentWillUpdate?(nextProps: P, nextState: S, nextContext: any): void;\n        componentDidUpdate?(prevProps: P, prevState: S, prevContext: any): void;\n        componentWillUnmount?(): void;\n    }\n\n    interface Mixin<P, S> extends ComponentLifecycle<P, S> {\n        mixins?: Mixin<P, S>;\n        statics?: {\n            [key: string]: any;\n        };\n\n        displayName?: string;\n        propTypes?: ValidationMap<any>;\n        contextTypes?: ValidationMap<any>;\n        childContextTypes?: ValidationMap<any>;\n\n        getDefaultProps?(): P;\n        getInitialState?(): S;\n    }\n\n    interface ComponentSpec<P, S> extends Mixin<P, S> {\n        render(): ReactElement<any>;\n\n        [propertyName: string]: any;\n    }\n\n    //\n    // Event System\n    // ----------------------------------------------------------------------\n\n    interface SyntheticEvent {\n        bubbles: boolean;\n        cancelable: boolean;\n        currentTarget: EventTarget;\n        defaultPrevented: boolean;\n        eventPhase: number;\n        isTrusted: boolean;\n        nativeEvent: Event;\n        preventDefault(): void;\n        stopPropagation(): void;\n        target: EventTarget;\n        timeStamp: Date;\n        type: string;\n    }\n\n    interface ClipboardEvent extends SyntheticEvent {\n        clipboardData: DataTransfer;\n    }\n\n    interface CompositionEvent extends SyntheticEvent {\n        data: string;\n    }\n\n    interface DragEvent extends SyntheticEvent {\n        dataTransfer: DataTransfer;\n    }\n\n    interface FocusEvent extends SyntheticEvent {\n        relatedTarget: EventTarget;\n    }\n\n    interface FormEvent extends SyntheticEvent {\n    }\n\n    interface KeyboardEvent extends SyntheticEvent {\n        altKey: boolean;\n        charCode: number;\n        ctrlKey: boolean;\n        getModifierState(key: string): boolean;\n        key: string;\n        keyCode: number;\n        locale: string;\n        location: number;\n        metaKey: boolean;\n        repeat: boolean;\n        shiftKey: boolean;\n        which: number;\n    }\n\n    interface MouseEvent extends SyntheticEvent {\n        altKey: boolean;\n        button: number;\n        buttons: number;\n        clientX: number;\n        clientY: number;\n        ctrlKey: boolean;\n        getModifierState(key: string): boolean;\n        metaKey: boolean;\n        pageX: number;\n        pageY: number;\n        relatedTarget: EventTarget;\n        screenX: number;\n        screenY: number;\n        shiftKey: boolean;\n    }\n\n    interface TouchEvent extends SyntheticEvent {\n        altKey: boolean;\n        changedTouches: TouchList;\n        ctrlKey: boolean;\n        getModifierState(key: string): boolean;\n        metaKey: boolean;\n        shiftKey: boolean;\n        targetTouches: TouchList;\n        touches: TouchList;\n    }\n\n    interface UIEvent extends SyntheticEvent {\n        detail: number;\n        view: AbstractView;\n    }\n\n    interface WheelEvent extends SyntheticEvent {\n        deltaMode: number;\n        deltaX: number;\n        deltaY: number;\n        deltaZ: number;\n    }\n\n    //\n    // Event Handler Types\n    // ----------------------------------------------------------------------\n\n    interface EventHandler<E extends SyntheticEvent> {\n        (event: E): void;\n    }\n\n    type ReactEventHandler = EventHandler<SyntheticEvent>;\n\n    type ClipboardEventHandler = EventHandler<ClipboardEvent>;\n    type CompositionEventHandler = EventHandler<CompositionEvent>;\n    type DragEventHandler = EventHandler<DragEvent>;\n    type FocusEventHandler = EventHandler<FocusEvent>;\n    type FormEventHandler = EventHandler<FormEvent>;\n    type KeyboardEventHandler = EventHandler<KeyboardEvent>;\n    type MouseEventHandler = EventHandler<MouseEvent>;\n    type TouchEventHandler = EventHandler<TouchEvent>;\n    type UIEventHandler = EventHandler<UIEvent>;\n    type WheelEventHandler = EventHandler<WheelEvent>;\n\n    //\n    // Props / DOM Attributes\n    // ----------------------------------------------------------------------\n\n    interface Props<T> {\n        children?: ReactNode;\n        key?: string | number;\n        ref?: string | ((component: T) => any);\n    }\n\n    interface HTMLProps<T> extends HTMLAttributes, Props<T> {\n    }\n\n    interface SVGProps extends SVGAttributes, Props<SVGElement> {\n    }\n\n    interface DOMAttributes {\n        dangerouslySetInnerHTML?: {\n            __html: string;\n        };\n\n        // Clipboard Events\n        onCopy?: ClipboardEventHandler;\n        onCut?: ClipboardEventHandler;\n        onPaste?: ClipboardEventHandler;\n\n        // Composition Events\n        onCompositionEnd?: CompositionEventHandler;\n        onCompositionStart?: CompositionEventHandler;\n        onCompositionUpdate?: CompositionEventHandler;\n\n        // Focus Events\n        onFocus?: FocusEventHandler;\n        onBlur?: FocusEventHandler;\n\n        // Form Events\n        onChange?: FormEventHandler;\n        onInput?: FormEventHandler;\n        onSubmit?: FormEventHandler;\n\n        // Image Events\n        onLoad?: ReactEventHandler;\n        onError?: ReactEventHandler; // also a Media Event\n\n        // Keyboard Events\n        onKeyDown?: KeyboardEventHandler;\n        onKeyPress?: KeyboardEventHandler;\n        onKeyUp?: KeyboardEventHandler;\n\n        // Media Events\n        onAbort?: ReactEventHandler;\n        onCanPlay?: ReactEventHandler;\n        onCanPlayThrough?: ReactEventHandler;\n        onDurationChange?: ReactEventHandler;\n        onEmptied?: ReactEventHandler;\n        onEncrypted?: ReactEventHandler;\n        onEnded?: ReactEventHandler;\n        onLoadedData?: ReactEventHandler;\n        onLoadedMetadata?: ReactEventHandler;\n        onLoadStart?: ReactEventHandler;\n        onPause?: ReactEventHandler;\n        onPlay?: ReactEventHandler;\n        onPlaying?: ReactEventHandler;\n        onProgress?: ReactEventHandler;\n        onRateChange?: ReactEventHandler;\n        onSeeked?: ReactEventHandler;\n        onSeeking?: ReactEventHandler;\n        onStalled?: ReactEventHandler;\n        onSuspend?: ReactEventHandler;\n        onTimeUpdate?: ReactEventHandler;\n        onVolumeChange?: ReactEventHandler;\n        onWaiting?: ReactEventHandler;\n\n        // MouseEvents\n        onClick?: MouseEventHandler;\n        onContextMenu?: MouseEventHandler;\n        onDoubleClick?: MouseEventHandler;\n        onDrag?: DragEventHandler;\n        onDragEnd?: DragEventHandler;\n        onDragEnter?: DragEventHandler;\n        onDragExit?: DragEventHandler;\n        onDragLeave?: DragEventHandler;\n        onDragOver?: DragEventHandler;\n        onDragStart?: DragEventHandler;\n        onDrop?: DragEventHandler;\n        onMouseDown?: MouseEventHandler;\n        onMouseEnter?: MouseEventHandler;\n        onMouseLeave?: MouseEventHandler;\n        onMouseMove?: MouseEventHandler;\n        onMouseOut?: MouseEventHandler;\n        onMouseOver?: MouseEventHandler;\n        onMouseUp?: MouseEventHandler;\n\n        // Selection Events\n        onSelect?: ReactEventHandler;\n\n        // Touch Events\n        onTouchCancel?: TouchEventHandler;\n        onTouchEnd?: TouchEventHandler;\n        onTouchMove?: TouchEventHandler;\n        onTouchStart?: TouchEventHandler;\n\n        // UI Events\n        onScroll?: UIEventHandler;\n\n        // Wheel Events\n        onWheel?: WheelEventHandler;\n    }\n\n    // This interface is not complete. Only properties accepting\n    // unitless numbers are listed here (see CSSProperty.js in React)\n    interface CSSProperties {\n        boxFlex?: number;\n        boxFlexGroup?: number;\n        columnCount?: number;\n        flex?: number | string;\n        flexGrow?: number;\n        flexShrink?: number;\n        fontWeight?: number | string;\n        lineClamp?: number;\n        lineHeight?: number | string;\n        opacity?: number;\n        order?: number;\n        orphans?: number;\n        widows?: number;\n        zIndex?: number;\n        zoom?: number;\n\n        fontSize?: number | string;\n\n        // SVG-related properties\n        fillOpacity?: number;\n        strokeOpacity?: number;\n        strokeWidth?: number;\n\n        // Remaining properties auto-extracted from http://docs.webplatform.org.\n        // License: http://docs.webplatform.org/wiki/Template:CC-by-3.0\n        /**\n         * Aligns a flex container's lines within the flex container when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.\n         */\n        alignContent?: any;\n\n        /**\n         * Sets the default alignment in the cross axis for all of the flex container's items, including anonymous flex items, similarly to how justify-content aligns items along the main axis.\n         */\n        alignItems?: any;\n\n        /**\n         * Allows the default alignment to be overridden for individual flex items.\n         */\n        alignSelf?: any;\n\n        /**\n         * This property allows precise alignment of elements, such as graphics, that do not have a baseline-table or lack the desired baseline in their baseline-table. With the alignment-adjust property, the position of the baseline identified by the alignment-baseline can be explicitly determined. It also determines precisely the alignment point for each glyph within a textual element.\n         */\n        alignmentAdjust?: any;\n\n        alignmentBaseline?: any;\n\n        /**\n         * Defines a length of time to elapse before an animation starts, allowing an animation to begin execution some time after it is applied.\n         */\n        animationDelay?: any;\n\n        /**\n         * Defines whether an animation should run in reverse on some or all cycles.\n         */\n        animationDirection?: any;\n\n        /**\n         * Specifies how many times an animation cycle should play.\n         */\n        animationIterationCount?: any;\n\n        /**\n         * Defines the list of animations that apply to the element.\n         */\n        animationName?: any;\n\n        /**\n         * Defines whether an animation is running or paused.\n         */\n        animationPlayState?: any;\n\n        /**\n         * Allows changing the style of any element to platform-based interface elements or vice versa.\n         */\n        appearance?: any;\n\n        /**\n         * Determines whether or not the “back” side of a transformed element is visible when facing the viewer.\n         */\n        backfaceVisibility?: any;\n\n        /**\n         * This property describes how the element's background images should blend with each other and the element's background color.\n         * The value is a list of blend modes that corresponds to each background image. Each element in the list will apply to the corresponding element of background-image. If a property doesn’t have enough comma-separated values to match the number of layers, the UA must calculate its used value by repeating the list of values until there are enough.\n         */\n        backgroundBlendMode?: any;\n\n        backgroundColor?: any;\n        \n        backgroundComposite?: any;\n\n        /**\n         * Applies one or more background images to an element. These can be any valid CSS image, including url() paths to image files or CSS gradients.\n         */\n        backgroundImage?: any;\n\n        /**\n         * Specifies what the background-position property is relative to.\n         */\n        backgroundOrigin?: any;\n\n        /**\n         * Sets the horizontal position of a background image.\n         */\n        backgroundPositionX?: any;\n\n        /**\n         * Background-repeat defines if and how background images will be repeated after they have been sized and positioned\n         */\n        backgroundRepeat?: any;\n\n        /**\n         * Obsolete - spec retired, not implemented.\n         */\n        baselineShift?: any;\n\n        /**\n         * Non standard. Sets or retrieves the location of the Dynamic HTML (DHTML) behavior.\n         */\n        behavior?: any;\n\n        /**\n         * Shorthand property that defines the different properties of all four sides of an element's border in a single declaration. It can be used to set border-width, border-style and border-color, or a subset of these.\n         */\n        border?: any;\n\n        /**\n         * Defines the shape of the border of the bottom-left corner.\n         */\n        borderBottomLeftRadius?: any;\n\n        /**\n         * Defines the shape of the border of the bottom-right corner.\n         */\n        borderBottomRightRadius?: any;\n\n        /**\n         * Sets the width of an element's bottom border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderBottomWidth?: any;\n\n        /**\n         * Border-collapse can be used for collapsing the borders between table cells\n         */\n        borderCollapse?: any;\n\n        /**\n         * The CSS border-color property sets the color of an element's four borders. This property can have from one to four values, made up of the elementary properties:     •       border-top-color\n         *      •       border-right-color\n         *      •       border-bottom-color\n         *      •       border-left-color The default color is the currentColor of each of these values.\n         * If you provide one value, it sets the color for the element. Two values set the horizontal and vertical values, respectively. Providing three values sets the top, vertical, and bottom values, in that order. Four values set all for sides: top, right, bottom, and left, in that order.\n         */\n        borderColor?: any;\n\n        /**\n         * Specifies different corner clipping effects, such as scoop (inner curves), bevel (straight cuts) or notch (cut-off rectangles). Works along with border-radius to specify the size of each corner effect.\n         */\n        borderCornerShape?: any;\n\n        /**\n         * The property border-image-source is used to set the image to be used instead of the border style. If this is set to none the border-style is used instead.\n         */\n        borderImageSource?: any;\n\n        /**\n         * The border-image-width CSS property defines the offset to use for dividing the border image in nine parts, the top-left corner, central top edge, top-right-corner, central right edge, bottom-right corner, central bottom edge, bottom-left corner, and central right edge. They represent inward distance from the top, right, bottom, and left edges.\n         */\n        borderImageWidth?: any;\n\n        /**\n         * Shorthand property that defines the border-width, border-style and border-color of an element's left border in a single declaration. Note that you can use the corresponding longhand properties to set specific individual properties of the left border — border-left-width, border-left-style and border-left-color.\n         */\n        borderLeft?: any;\n\n        /**\n         * The CSS border-left-color property sets the color of an element's left border. This page explains the border-left-color value, but often you will find it more convenient to fix the border's left color as part of a shorthand set, either border-left or border-color.\n         * Colors can be defined several ways. For more information, see Usage.\n         */\n        borderLeftColor?: any;\n\n        /**\n         * Sets the style of an element's left border. To set all four borders, use the shorthand property, border-style. Otherwise, you can set the borders individually with border-top-style, border-right-style, border-bottom-style, border-left-style.\n         */\n        borderLeftStyle?: any;\n\n        /**\n         * Sets the width of an element's left border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderLeftWidth?: any;\n\n        /**\n         * Shorthand property that defines the border-width, border-style and border-color of an element's right border in a single declaration. Note that you can use the corresponding longhand properties to set specific individual properties of the right border — border-right-width, border-right-style and border-right-color.\n         */\n        borderRight?: any;\n\n        /**\n         * Sets the color of an element's right border. This page explains the border-right-color value, but often you will find it more convenient to fix the border's right color as part of a shorthand set, either border-right or border-color.\n         * Colors can be defined several ways. For more information, see Usage.\n         */\n        borderRightColor?: any;\n\n        /**\n         * Sets the style of an element's right border. To set all four borders, use the shorthand property, border-style. Otherwise, you can set the borders individually with border-top-style, border-right-style, border-bottom-style, border-left-style.\n         */\n        borderRightStyle?: any;\n\n        /**\n         * Sets the width of an element's right border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderRightWidth?: any;\n\n        /**\n         * Specifies the distance between the borders of adjacent cells.\n         */\n        borderSpacing?: any;\n\n        /**\n         * Sets the style of an element's four borders. This property can have from one to four values. With only one value, the value will be applied to all four borders; otherwise, this works as a shorthand property for each of border-top-style, border-right-style, border-bottom-style, border-left-style, where each border style may be assigned a separate value.\n         */\n        borderStyle?: any;\n\n        /**\n         * Shorthand property that defines the border-width, border-style and border-color of an element's top border in a single declaration. Note that you can use the corresponding longhand properties to set specific individual properties of the top border — border-top-width, border-top-style and border-top-color.\n         */\n        borderTop?: any;\n\n        /**\n         * Sets the color of an element's top border. This page explains the border-top-color value, but often you will find it more convenient to fix the border's top color as part of a shorthand set, either border-top or border-color.\n         * Colors can be defined several ways. For more information, see Usage.\n         */\n        borderTopColor?: any;\n\n        /**\n         * Sets the rounding of the top-left corner of the element.\n         */\n        borderTopLeftRadius?: any;\n\n        /**\n         * Sets the rounding of the top-right corner of the element.\n         */\n        borderTopRightRadius?: any;\n\n        /**\n         * Sets the style of an element's top border. To set all four borders, use the shorthand property, border-style. Otherwise, you can set the borders individually with border-top-style, border-right-style, border-bottom-style, border-left-style.\n         */\n        borderTopStyle?: any;\n\n        /**\n         * Sets the width of an element's top border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderTopWidth?: any;\n\n        /**\n         * Sets the width of an element's four borders. This property can have from one to four values. This is a shorthand property for setting values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderWidth?: any;\n\n        /**\n         * Obsolete.\n         */\n        boxAlign?: any;\n\n        /**\n         * Breaks a box into fragments creating new borders, padding and repeating backgrounds or lets it stay as a continuous box on a page break, column break, or, for inline elements, at a line break.\n         */\n        boxDecorationBreak?: any;\n\n        /**\n         * Deprecated\n         */\n        boxDirection?: any;\n\n        /**\n         * Do not use. This property has been replaced by the flex-wrap property.\n         * Gets or sets a value that specifies the direction to add successive rows or columns when the value of box-lines is set to multiple.\n         */\n        boxLineProgression?: any;\n\n        /**\n         * Do not use. This property has been replaced by the flex-wrap property.\n         * Gets or sets a value that specifies whether child elements wrap onto multiple lines or columns based on the space available in the object.\n         */\n        boxLines?: any;\n\n        /**\n         * Do not use. This property has been replaced by flex-order.\n         * Specifies the ordinal group that a child element of the object belongs to. This ordinal value identifies the display order (along the axis defined by the box-orient property) for the group.\n         */\n        boxOrdinalGroup?: any;\n\n        /**\n         * The CSS break-after property allows you to force a break on multi-column layouts. More specifically, it allows you to force a break after an element. It allows you to determine if a break should occur, and what type of break it should be. The break-after CSS property describes how the page, column or region break behaves after the generated box. If there is no generated box, the property is ignored.\n         */\n        breakAfter?: any;\n\n        /**\n         * Control page/column/region breaks that fall above a block of content\n         */\n        breakBefore?: any;\n\n        /**\n         * Control page/column/region breaks that fall within a block of content\n         */\n        breakInside?: any;\n\n        /**\n         * The clear CSS property specifies if an element can be positioned next to or must be positioned below the floating elements that precede it in the markup.\n         */\n        clear?: any;\n\n        /**\n         * Deprecated; see clip-path.\n         * Lets you specify the dimensions of an absolutely positioned element that should be visible, and the element is clipped into this shape, and displayed.\n         */\n        clip?: any;\n\n        /**\n         * Clipping crops an graphic, so that only a portion of the graphic is rendered, or filled. This clip-rule property, when used with the clip-path property, defines which clip rule, or algorithm, to use when filling the different parts of a graphics.\n         */\n        clipRule?: any;\n\n        /**\n         * The color property sets the color of an element's foreground content (usually text), accepting any standard CSS color from keywords and hex values to RGB(a) and HSL(a).\n         */\n        color?: any;\n\n        /**\n         * Specifies how to fill columns (balanced or sequential).\n         */\n        columnFill?: any;\n\n        /**\n         * The column-gap property controls the width of the gap between columns in multi-column elements.\n         */\n        columnGap?: any;\n\n        /**\n         * Sets the width, style, and color of the rule between columns.\n         */\n        columnRule?: any;\n\n        /**\n         * Specifies the color of the rule between columns.\n         */\n        columnRuleColor?: any;\n\n        /**\n         * Specifies the width of the rule between columns.\n         */\n        columnRuleWidth?: any;\n\n        /**\n         * The column-span CSS property makes it possible for an element to span across all columns when its value is set to all. An element that spans more than one column is called a spanning element.\n         */\n        columnSpan?: any;\n\n        /**\n         * Specifies the width of columns in multi-column elements.\n         */\n        columnWidth?: any;\n\n        /**\n         * This property is a shorthand property for setting column-width and/or column-count.\n         */\n        columns?: any;\n\n        /**\n         * The counter-increment property accepts one or more names of counters (identifiers), each one optionally followed by an integer which specifies the value by which the counter should be incremented (e.g. if the value is 2, the counter increases by 2 each time it is invoked).\n         */\n        counterIncrement?: any;\n\n        /**\n         * The counter-reset property contains a list of one or more names of counters, each one optionally followed by an integer (otherwise, the integer defaults to 0.) Each time the given element is invoked, the counters specified by the property are set to the given integer.\n         */\n        counterReset?: any;\n\n        /**\n         * The cue property specifies sound files (known as an \"auditory icon\") to be played by speech media agents before and after presenting an element's content; if only one file is specified, it is played both before and after. The volume at which the file(s) should be played, relative to the volume of the main element, may also be specified. The icon files may also be set separately with the cue-before and cue-after properties.\n         */\n        cue?: any;\n\n        /**\n         * The cue-after property specifies a sound file (known as an \"auditory icon\") to be played by speech media agents after presenting an element's content; the volume at which the file should be played may also be specified. The shorthand property cue sets cue sounds for both before and after the element is presented.\n         */\n        cueAfter?: any;\n\n        /**\n         * The direction CSS property specifies the text direction/writing direction. The rtl is used for Hebrew or Arabic text, the ltr is for other languages.\n         */\n        direction?: any;\n\n        /**\n         * This property specifies the type of rendering box used for an element. It is a shorthand property for many other display properties.\n         */\n        display?: any;\n\n        /**\n         * The ‘fill’ property paints the interior of the given graphical element. The area to be painted consists of any areas inside the outline of the shape. To determine the inside of the shape, all subpaths are considered, and the interior is determined according to the rules associated with the current value of the ‘fill-rule’ property. The zero-width geometric outline of a shape is included in the area to be painted.\n         */\n        fill?: any;\n\n        /**\n         * The ‘fill-rule’ property indicates the algorithm which is to be used to determine what parts of the canvas are included inside the shape. For a simple, non-intersecting path, it is intuitively clear what region lies \"inside\"; however, for a more complex path, such as a path that intersects itself or where one subpath encloses another, the interpretation of \"inside\" is not so obvious.\n         * The ‘fill-rule’ property provides two options for how the inside of a shape is determined:\n         */\n        fillRule?: any;\n\n        /**\n         * Applies various image processing effects. This property is largely unsupported. See Compatibility section for more information.\n         */\n        filter?: any;\n\n        /**\n         * Obsolete, do not use. This property has been renamed to align-items.\n         * Specifies the alignment (perpendicular to the layout axis defined by the flex-direction property) of child elements of the object.\n         */\n        flexAlign?: any;\n\n        /**\n         * The flex-basis CSS property describes the initial main size of the flex item before any free space is distributed according to the flex factors described in the flex property (flex-grow and flex-shrink).\n         */\n        flexBasis?: any;\n\n        /**\n         * The flex-direction CSS property describes how flex items are placed in the flex container, by setting the direction of the flex container's main axis.\n         */\n        flexDirection?: any;\n\n        /**\n         * The flex-flow CSS property defines the flex container's main and cross axis. It is a shorthand property for the flex-direction and flex-wrap properties.\n         */\n        flexFlow?: any;\n\n        /**\n         * Do not use. This property has been renamed to align-self\n         * Specifies the alignment (perpendicular to the layout axis defined by flex-direction) of child elements of the object.\n         */\n        flexItemAlign?: any;\n\n        /**\n         * Do not use. This property has been renamed to align-content.\n         * Specifies how a flexbox's lines align within the flexbox when there is extra space along the axis that is perpendicular to the axis defined by the flex-direction property.\n         */\n        flexLinePack?: any;\n\n        /**\n         * Gets or sets a value that specifies the ordinal group that a flexbox element belongs to. This ordinal value identifies the display order for the group.\n         */\n        flexOrder?: any;\n\n        /**\n         * Elements which have the style float are floated horizontally. These elements can move as far to the left or right of the containing element. All elements after the floating element will flow around it, but elements before the floating element are not impacted. If several floating elements are placed after each other, they will float next to each other as long as there is room.\n         */\n        float?: any;\n\n        /**\n         * Flows content from a named flow (specified by a corresponding flow-into) through selected elements to form a dynamic chain of layout regions.\n         */\n        flowFrom?: any;\n\n        /**\n         * The font property is shorthand that allows you to do one of two things: you can either set up six of the most mature font properties in one line, or you can set one of a choice of keywords to adopt a system font setting.\n         */\n        font?: any;\n\n        /**\n         * The font-family property allows one or more font family names and/or generic family names to be specified for usage on the selected element(s)' text. The browser then goes through the list; for each character in the selection it applies the first font family that has an available glyph for that character.\n         */\n        fontFamily?: any;\n\n        /**\n         * The font-kerning property allows contextual adjustment of inter-glyph spacing, i.e. the spaces between the characters in text. This property controls <bold>metric kerning</bold> - that utilizes adjustment data contained in the font. Optical Kerning is not supported as yet.\n         */\n        fontKerning?: any;\n\n        /**\n         * The font-size-adjust property adjusts the font-size of the fallback fonts defined with font-family, so that the x-height is the same no matter what font is used. This preserves the readability of the text when fallback happens.\n         */\n        fontSizeAdjust?: any;\n\n        /**\n         * Allows you to expand or condense the widths for a normal, condensed, or expanded font face.\n         */\n        fontStretch?: any;\n\n        /**\n         * The font-style property allows normal, italic, or oblique faces to be selected. Italic forms are generally cursive in nature while oblique faces are typically sloped versions of the regular face. Oblique faces can be simulated by artificially sloping the glyphs of the regular face.\n         */\n        fontStyle?: any;\n\n        /**\n         * This value specifies whether the user agent is allowed to synthesize bold or oblique font faces when a font family lacks bold or italic faces.\n         */\n        fontSynthesis?: any;\n\n        /**\n         * The font-variant property enables you to select the small-caps font within a font family.\n         */\n        fontVariant?: any;\n\n        /**\n         * Fonts can provide alternate glyphs in addition to default glyph for a character. This property provides control over the selection of these alternate glyphs.\n         */\n        fontVariantAlternates?: any;\n\n        /**\n         * Lays out one or more grid items bound by 4 grid lines. Shorthand for setting grid-column-start, grid-column-end, grid-row-start, and grid-row-end in a single declaration.\n         */\n        gridArea?: any;\n\n        /**\n         * Controls a grid item's placement in a grid area, particularly grid position and a grid span. Shorthand for setting grid-column-start and grid-column-end in a single declaration.\n         */\n        gridColumn?: any;\n\n        /**\n         * Controls a grid item's placement in a grid area as well as grid position and a grid span. The grid-column-end property (with grid-row-start, grid-row-end, and grid-column-start) determines a grid item's placement by specifying the grid lines of a grid item's grid area.\n         */\n        gridColumnEnd?: any;\n\n        /**\n         * Determines a grid item's placement by specifying the starting grid lines of a grid item's grid area . A grid item's placement in a grid area consists of a grid position and a grid span. See also ( grid-row-start, grid-row-end, and grid-column-end)\n         */\n        gridColumnStart?: any;\n\n        /**\n         * Gets or sets a value that indicates which row an element within a Grid should appear in. Shorthand for setting grid-row-start and grid-row-end in a single declaration.\n         */\n        gridRow?: any;\n\n        /**\n         * Determines a grid item’s placement by specifying the block-end. A grid item's placement in a grid area consists of a grid position and a grid span. The grid-row-end property (with grid-row-start, grid-column-start, and grid-column-end) determines a grid item's placement by specifying the grid lines of a grid item's grid area.\n         */\n        gridRowEnd?: any;\n\n        /**\n         * Specifies a row position based upon an integer location, string value, or desired row size.\n         * css/properties/grid-row is used as short-hand for grid-row-position and grid-row-position\n         */\n        gridRowPosition?: any;\n\n        gridRowSpan?: any;\n\n        /**\n         * Specifies named grid areas which are not associated with any particular grid item, but can be referenced from the grid-placement properties. The syntax of the grid-template-areas property also provides a visualization of the structure of the grid, making the overall layout of the grid container easier to understand.\n         */\n        gridTemplateAreas?: any;\n\n        /**\n         * Specifies (with grid-template-rows) the line names and track sizing functions of the grid. Each sizing function can be specified as a length, a percentage of the grid container’s size, a measurement of the contents occupying the column or row, or a fraction of the free space in the grid.\n         */\n        gridTemplateColumns?: any;\n\n        /**\n         * Specifies (with grid-template-columns) the line names and track sizing functions of the grid. Each sizing function can be specified as a length, a percentage of the grid container’s size, a measurement of the contents occupying the column or row, or a fraction of the free space in the grid.\n         */\n        gridTemplateRows?: any;\n\n        /**\n         * Sets the height of an element. The content area of the element height does not include the padding, border, and margin of the element.\n         */\n        height?: any;\n\n        /**\n         * Specifies the minimum number of characters in a hyphenated word\n         */\n        hyphenateLimitChars?: any;\n\n        /**\n         * Indicates the maximum number of successive hyphenated lines in an element. The ‘no-limit’ value means that there is no limit.\n         */\n        hyphenateLimitLines?: any;\n\n        /**\n         * Specifies the maximum amount of trailing whitespace (before justification) that may be left in a line before hyphenation is triggered to pull part of a word from the next line back up into the current one.\n         */\n        hyphenateLimitZone?: any;\n\n        /**\n         * Specifies whether or not words in a sentence can be split by the use of a manual or automatic hyphenation mechanism.\n         */\n        hyphens?: any;\n\n        imeMode?: any;\n\n        layoutGrid?: any;\n\n        layoutGridChar?: any;\n\n        layoutGridLine?: any;\n\n        layoutGridMode?: any;\n\n        layoutGridType?: any;\n\n        /**\n         * Sets the left edge of an element\n         */\n        left?: any;\n\n        /**\n         * The letter-spacing CSS property specifies the spacing behavior between text characters.\n         */\n        letterSpacing?: any;\n\n        /**\n         * Deprecated. Gets or sets line-breaking rules for text in selected languages such as Japanese, Chinese, and Korean.\n         */\n        lineBreak?: any;\n\n        /**\n         * Shorthand property that sets the list-style-type, list-style-position and list-style-image properties in one declaration.\n         */\n        listStyle?: any;\n\n        /**\n         * This property sets the image that will be used as the list item marker. When the image is available, it will replace the marker set with the 'list-style-type' marker. That also means that if the image is not available, it will show the style specified by list-style-property\n         */\n        listStyleImage?: any;\n\n        /**\n         * Specifies if the list-item markers should appear inside or outside the content flow.\n         */\n        listStylePosition?: any;\n\n        /**\n         * Specifies the type of list-item marker in a list.\n         */\n        listStyleType?: any;\n\n        /**\n         * The margin property is shorthand to allow you to set all four margins of an element at once. Its equivalent longhand properties are margin-top, margin-right, margin-bottom and margin-left. Negative values are also allowed.\n         */\n        margin?: any;\n\n        /**\n         * margin-bottom sets the bottom margin of an element.\n         */\n        marginBottom?: any;\n\n        /**\n         * margin-left sets the left margin of an element.\n         */\n        marginLeft?: any;\n\n        /**\n         * margin-right sets the right margin of an element.\n         */\n        marginRight?: any;\n\n        /**\n         * margin-top sets the top margin of an element.\n         */\n        marginTop?: any;\n\n        /**\n         * The marquee-direction determines the initial direction in which the marquee content moves.\n         */\n        marqueeDirection?: any;\n\n        /**\n         * The 'marquee-style' property determines a marquee's scrolling behavior.\n         */\n        marqueeStyle?: any;\n\n        /**\n         * This property is shorthand for setting mask-image, mask-mode, mask-repeat, mask-position, mask-clip, mask-origin, mask-composite and mask-size. Omitted values are set to their original properties' initial values.\n         */\n        mask?: any;\n\n        /**\n         * This property is shorthand for setting mask-border-source, mask-border-slice, mask-border-width, mask-border-outset, and mask-border-repeat. Omitted values are set to their original properties' initial values.\n         */\n        maskBorder?: any;\n\n        /**\n         * This property specifies how the images for the sides and the middle part of the mask image are scaled and tiled. The first keyword applies to the horizontal sides, the second one applies to the vertical ones. If the second keyword is absent, it is assumed to be the same as the first, similar to the CSS border-image-repeat property.\n         */\n        maskBorderRepeat?: any;\n\n        /**\n         * This property specifies inward offsets from the top, right, bottom, and left edges of the mask image, dividing it into nine regions: four corners, four edges, and a middle. The middle image part is discarded and treated as fully transparent black unless the fill keyword is present. The four values set the top, right, bottom and left offsets in that order, similar to the CSS border-image-slice property.\n         */\n        maskBorderSlice?: any;\n\n        /**\n         * Specifies an image to be used as a mask. An image that is empty, fails to download, is non-existent, or cannot be displayed is ignored and does not mask the element.\n         */\n        maskBorderSource?: any;\n\n        /**\n         * This property sets the width of the mask box image, similar to the CSS border-image-width property.\n         */\n        maskBorderWidth?: any;\n\n        /**\n         * Determines the mask painting area, which defines the area that is affected by the mask. The painted content of an element may be restricted to this area.\n         */\n        maskClip?: any;\n\n        /**\n         * For elements rendered as a single box, specifies the mask positioning area. For elements rendered as multiple boxes (e.g., inline boxes on several lines, boxes on several pages) specifies which boxes box-decoration-break operates on to determine the mask positioning area(s).\n         */\n        maskOrigin?: any;\n\n        /**\n         * This property must not be used. It is no longer included in any standard or standard track specification, nor is it implemented in any browser. It is only used when the text-align-last property is set to size. It controls allowed adjustments of font-size to fit line content.\n         */\n        maxFontSize?: any;\n\n        /**\n         * Sets the maximum height for an element. It prevents the height of the element to exceed the specified value. If min-height is specified and is greater than max-height, max-height is overridden.\n         */\n        maxHeight?: any;\n\n        /**\n         * Sets the maximum width for an element. It limits the width property to be larger than the value specified in max-width.\n         */\n        maxWidth?: any;\n\n        /**\n         * Sets the minimum height for an element. It prevents the height of the element to be smaller than the specified value. The value of min-height overrides both max-height and height.\n         */\n        minHeight?: any;\n\n        /**\n         * Sets the minimum width of an element. It limits the width property to be not smaller than the value specified in min-width.\n         */\n        minWidth?: any;\n\n        /**\n         * The CSS outline property is a shorthand property for setting one or more of the individual outline properties outline-style, outline-width and outline-color in a single rule. In most cases the use of this shortcut is preferable and more convenient.\n         * Outlines differ from borders in the following ways:  •       Outlines do not take up space, they are drawn above the content.\n         *      •       Outlines may be non-rectangular. They are rectangular in Gecko/Firefox. Internet Explorer attempts to place the smallest contiguous outline around all elements or shapes that are indicated to have an outline. Opera draws a non-rectangular shape around a construct.\n         */\n        outline?: any;\n\n        /**\n         * The outline-color property sets the color of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\n         */\n        outlineColor?: any;\n\n        /**\n         * The outline-offset property offsets the outline and draw it beyond the border edge.\n         */\n        outlineOffset?: any;\n\n        /**\n         * The overflow property controls how extra content exceeding the bounding box of an element is rendered. It can be used in conjunction with an element that has a fixed width and height, to eliminate text-induced page distortion.\n         */\n        overflow?: any;\n\n        /**\n         * Specifies the preferred scrolling methods for elements that overflow.\n         */\n        overflowStyle?: any;\n\n        /**\n         * The overflow-x property is a specific case of the generic overflow property. It controls how extra content exceeding the x-axis of the bounding box of an element is rendered.\n         */\n        overflowX?: any;\n\n        /**\n         * The padding optional CSS property sets the required padding space on one to four sides of an element. The padding area is the space between an element and its border. Negative values are not allowed but decimal values are permitted. The element size is treated as fixed, and the content of the element shifts toward the center as padding is increased.\n         * The padding property is a shorthand to avoid setting each side separately (padding-top, padding-right, padding-bottom, padding-left).\n         */\n        padding?: any;\n\n        /**\n         * The padding-bottom CSS property of an element sets the padding space required on the bottom of an element. The padding area is the space between the content of the element and its border. Contrary to margin-bottom values, negative values of padding-bottom are invalid.\n         */\n        paddingBottom?: any;\n\n        /**\n         * The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and its border. Contrary to margin-left values, negative values of padding-left are invalid.\n         */\n        paddingLeft?: any;\n\n        /**\n         * The padding-right CSS property of an element sets the padding space required on the right side of an element. The padding area is the space between the content of the element and its border. Contrary to margin-right values, negative values of padding-right are invalid.\n         */\n        paddingRight?: any;\n\n        /**\n         * The padding-top CSS property of an element sets the padding space required on the top of an element. The padding area is the space between the content of the element and its border. Contrary to margin-top values, negative values of padding-top are invalid.\n         */\n        paddingTop?: any;\n\n        /**\n         * The page-break-after property is supported in all major browsers. With CSS3, page-break-* properties are only aliases of the break-* properties. The CSS3 Fragmentation spec defines breaks for all CSS box fragmentation.\n         */\n        pageBreakAfter?: any;\n\n        /**\n         * The page-break-before property sets the page-breaking behavior before an element. With CSS3, page-break-* properties are only aliases of the break-* properties. The CSS3 Fragmentation spec defines breaks for all CSS box fragmentation.\n         */\n        pageBreakBefore?: any;\n\n        /**\n         * Sets the page-breaking behavior inside an element. With CSS3, page-break-* properties are only aliases of the break-* properties. The CSS3 Fragmentation spec defines breaks for all CSS box fragmentation.\n         */\n        pageBreakInside?: any;\n\n        /**\n         * The pause property determines how long a speech media agent should pause before and after presenting an element. It is a shorthand for the pause-before and pause-after properties.\n         */\n        pause?: any;\n\n        /**\n         * The pause-after property determines how long a speech media agent should pause after presenting an element. It may be replaced by the shorthand property pause, which sets pause time before and after.\n         */\n        pauseAfter?: any;\n\n        /**\n         * The pause-before property determines how long a speech media agent should pause before presenting an element. It may be replaced by the shorthand property pause, which sets pause time before and after.\n         */\n        pauseBefore?: any;\n\n        /**\n         * The perspective property defines how far an element is placed from the view on the z-axis, from the screen to the viewer.\n         * Perspective defines how an object is viewed. In graphic arts, perspective is the representation on a flat surface of what the viewer's eye would see in a 3D space. (See Wikipedia for more information about graphical perspective and for related illustrations.)\n         * The illusion of perspective on a flat surface, such as a computer screen, is created by projecting points on the flat surface as they would appear if the flat surface were a window through which the viewer was looking at the object. In discussion of virtual environments, this flat surface is called a projection plane.\n         */\n        perspective?: any;\n\n        /**\n         * The perspective-origin property establishes the origin for the perspective property. It effectively sets the X and Y position at which the viewer appears to be looking at the children of the element.\n         * When used with perspective, perspective-origin changes the appearance of an object, as if a viewer were looking at it from a different origin. An object appears differently if a viewer is looking directly at it versus looking at it from below, above, or from the side. Thus, the perspective-origin is like a vanishing point.\n         * The default value of perspective-origin is 50% 50%. This displays an object as if the viewer's eye were positioned directly at the center of the screen, both top-to-bottom and left-to-right. A value of 0% 0% changes the object as if the viewer was looking toward the top left angle. A value of 100% 100% changes the appearance as if viewed toward the bottom right angle.\n         */\n        perspectiveOrigin?: any;\n\n        /**\n         * The pointer-events property allows you to control whether an element can be the target for the pointing device (e.g, mouse, pen) events.\n         */\n        pointerEvents?: any;\n\n        /**\n         * The position property controls the type of positioning used by an element within its parent elements. The effect of the position property depends on a lot of factors, for example the position property of parent elements.\n         */\n        position?: any;\n\n        /**\n         * Obsolete: unsupported.\n         * This property determines whether or not a full-width punctuation mark character should be trimmed if it appears at the beginning of a line, so that its \"ink\" lines up with the first glyph in the line above and below.\n         */\n        punctuationTrim?: any;\n\n        /**\n         * Sets the type of quotation marks for embedded quotations.\n         */\n        quotes?: any;\n\n        /**\n         * Controls whether the last region in a chain displays additional 'overset' content according its default overflow property, or if it displays a fragment of content as if it were flowing into a subsequent region.\n         */\n        regionFragment?: any;\n\n        /**\n         * The rest-after property determines how long a speech media agent should pause after presenting an element's main content, before presenting that element's exit cue sound. It may be replaced by the shorthand property rest, which sets rest time before and after.\n         */\n        restAfter?: any;\n\n        /**\n         * The rest-before property determines how long a speech media agent should pause after presenting an intro cue sound for an element, before presenting that element's main content. It may be replaced by the shorthand property rest, which sets rest time before and after.\n         */\n        restBefore?: any;\n\n        /**\n         * Specifies the position an element in relation to the right side of the containing element.\n         */\n        right?: any;\n\n        rubyAlign?: any;\n\n        rubyPosition?: any;\n\n        /**\n         * Defines the alpha channel threshold used to extract a shape from an image. Can be thought of as a \"minimum opacity\" threshold; that is, a value of 0.5 means that the shape will enclose all the pixels that are more than 50% opaque.\n         */\n        shapeImageThreshold?: any;\n\n        /**\n         * A future level of CSS Shapes will define a shape-inside property, which will define a shape to wrap content within the element. See Editor's Draft <http://dev.w3.org/csswg/css-shapes/> and CSSWG wiki page on next-level plans <http://wiki.csswg.org/spec/css-shapes>\n         */\n        shapeInside?: any;\n\n        /**\n         * Adds a margin to a shape-outside. In effect, defines a new shape that is the smallest contour around all the points that are the shape-margin distance outward perpendicular to each point on the underlying shape. For points where a perpendicular direction is not defined (e.g., a triangle corner), takes all points on a circle centered at the point and with a radius of the shape-margin distance. This property accepts only non-negative values.\n         */\n        shapeMargin?: any;\n\n        /**\n         * Declares a shape around which text should be wrapped, with possible modifications from the shape-margin property. The shape defined by shape-outside and shape-margin changes the geometry of a float element's float area.\n         */\n        shapeOutside?: any;\n\n        /**\n         * The speak property determines whether or not a speech synthesizer will read aloud the contents of an element.\n         */\n        speak?: any;\n\n        /**\n         * The speak-as property determines how the speech synthesizer interprets the content: words as whole words or as a sequence of letters, numbers as a numerical value or a sequence of digits, punctuation as pauses in speech or named punctuation characters.\n         */\n        speakAs?: any;\n\n        /**\n         * The tab-size CSS property is used to customise the width of a tab (U+0009) character.\n         */\n        tabSize?: any;\n\n        /**\n         * The 'table-layout' property controls the algorithm used to lay out the table cells, rows, and columns.\n         */\n        tableLayout?: any;\n\n        /**\n         * The text-align CSS property describes how inline content like text is aligned in its parent block element. text-align does not control the alignment of block elements itself, only their inline content.\n         */\n        textAlign?: any;\n\n        /**\n         * The text-align-last CSS property describes how the last line of a block element or a line before line break is aligned in its parent block element.\n         */\n        textAlignLast?: any;\n\n        /**\n         * The text-decoration CSS property is used to set the text formatting to underline, overline, line-through or blink. \n         * underline and overline decorations are positioned under the text, line-through over it.\n         */\n        textDecoration?: any;\n\n        /**\n         * Sets the color of any text decoration, such as underlines, overlines, and strike throughs.\n         */\n        textDecorationColor?: any;\n\n        /**\n         * Sets what kind of line decorations are added to an element, such as underlines, overlines, etc.\n         */\n        textDecorationLine?: any;\n\n        textDecorationLineThrough?: any;\n\n        textDecorationNone?: any;\n\n        textDecorationOverline?: any;\n\n        /**\n         * Specifies what parts of an element’s content are skipped over when applying any text decoration.\n         */\n        textDecorationSkip?: any;\n\n        /**\n         * This property specifies the style of the text decoration line drawn on the specified element. The intended meaning for the values are the same as those of the border-style-properties.\n         */\n        textDecorationStyle?: any;\n\n        textDecorationUnderline?: any;\n\n        /**\n         * The text-emphasis property will apply special emphasis marks to the elements text. Slightly similar to the text-decoration property only that this property can have affect on the line-height. It also is noted that this is shorthand for text-emphasis-style and for text-emphasis-color.\n         */\n        textEmphasis?: any;\n\n        /**\n         * The text-emphasis-color property specifies the foreground color of the emphasis marks.\n         */\n        textEmphasisColor?: any;\n\n        /**\n         * The text-emphasis-style property applies special emphasis marks to an element's text.\n         */\n        textEmphasisStyle?: any;\n\n        /**\n         * This property helps determine an inline box's block-progression dimension, derived from the text-height and font-size properties for non-replaced elements, the height or the width for replaced elements, and the stacked block-progression dimension for inline-block elements. The block-progression dimension determines the position of the padding, border and margin for the element.\n         */\n        textHeight?: any;\n\n        /**\n         * Specifies the amount of space horizontally that should be left on the first line of the text of an element. This horizontal spacing is at the beginning of the first line and is in respect to the left edge of the containing block box.\n         */\n        textIndent?: any;\n\n        textJustifyTrim?: any;\n\n        textKashidaSpace?: any;\n\n        /**\n         * The text-line-through property is a shorthand property for text-line-through-style, text-line-through-color and text-line-through-mode. (Considered obsolete; use text-decoration instead.)\n         */\n        textLineThrough?: any;\n\n        /**\n         * Specifies the line colors for the line-through text decoration.\n         * (Considered obsolete; use text-decoration-color instead.)\n         */\n        textLineThroughColor?: any;\n\n        /**\n         * Sets the mode for the line-through text decoration, determining whether the text decoration affects the space characters or not.\n         * (Considered obsolete; use text-decoration-skip instead.)\n         */\n        textLineThroughMode?: any;\n\n        /**\n         * Specifies the line style for line-through text decoration.\n         * (Considered obsolete; use text-decoration-style instead.)\n         */\n        textLineThroughStyle?: any;\n\n        /**\n         * Specifies the line width for the line-through text decoration.\n         */\n        textLineThroughWidth?: any;\n\n        /**\n         * The text-overflow shorthand CSS property determines how overflowed content that is not displayed is signaled to the users. It can be clipped, display an ellipsis ('…', U+2026 HORIZONTAL ELLIPSIS) or a Web author-defined string. It covers the two long-hand properties text-overflow-mode and text-overflow-ellipsis\n         */\n        textOverflow?: any;\n\n        /**\n         * The text-overline property is the shorthand for the text-overline-style, text-overline-width, text-overline-color, and text-overline-mode properties.\n         */\n        textOverline?: any;\n\n        /**\n         * Specifies the line color for the overline text decoration.\n         */\n        textOverlineColor?: any;\n\n        /**\n         * Sets the mode for the overline text decoration, determining whether the text decoration affects the space characters or not.\n         */\n        textOverlineMode?: any;\n\n        /**\n         * Specifies the line style for overline text decoration.\n         */\n        textOverlineStyle?: any;\n\n        /**\n         * Specifies the line width for the overline text decoration.\n         */\n        textOverlineWidth?: any;\n\n        /**\n         * The text-rendering CSS property provides information to the browser about how to optimize when rendering text. Options are: legibility, speed or geometric precision.\n         */\n        textRendering?: any;\n\n        /**\n         * Obsolete: unsupported.\n         */\n        textScript?: any;\n\n        /**\n         * The CSS text-shadow property applies one or more drop shadows to the text and <text-decorations> of an element. Each shadow is specified as an offset from the text, along with optional color and blur radius values.\n         */\n        textShadow?: any;\n\n        /**\n         * This property transforms text for styling purposes. (It has no effect on the underlying content.)\n         */\n        textTransform?: any;\n\n        /**\n         * Unsupported.\n         * This property will add a underline position value to the element that has an underline defined.\n         */\n        textUnderlinePosition?: any;\n\n        /**\n         * After review this should be replaced by text-decoration should it not?\n         * This property will set the underline style for text with a line value for underline, overline, and line-through.\n         */\n        textUnderlineStyle?: any;\n\n        /**\n         * This property specifies how far an absolutely positioned box's top margin edge is offset below the top edge of the box's containing block. For relatively positioned boxes, the offset is with respect to the top edges of the box itself (i.e., the box is given a position in the normal flow, then offset from that position according to these properties).\n         */\n        top?: any;\n\n        /**\n         * Determines whether touch input may trigger default behavior supplied by the user agent, such as panning or zooming.\n         */\n        touchAction?: any;\n\n        /**\n         * CSS transforms allow elements styled with CSS to be transformed in two-dimensional or three-dimensional space. Using this property, elements can be translated, rotated, scaled, and skewed. The value list may consist of 2D and/or 3D transform values.\n         */\n        transform?: any;\n\n        /**\n         * This property defines the origin of the transformation axes relative to the element to which the transformation is applied.\n         */\n        transformOrigin?: any;\n\n        /**\n         * This property allows you to define the relative position of the origin of the transformation grid along the z-axis.\n         */\n        transformOriginZ?: any;\n\n        /**\n         * This property specifies how nested elements are rendered in 3D space relative to their parent.\n         */\n        transformStyle?: any;\n\n        /**\n         * The transition CSS property is a shorthand property for transition-property, transition-duration, transition-timing-function, and transition-delay. It allows to define the transition between two states of an element.\n         */\n        transition?: any;\n\n        /**\n         * Defines when the transition will start. A value of ‘0s’ means the transition will execute as soon as the property is changed. Otherwise, the value specifies an offset from the moment the property is changed, and the transition will delay execution by that offset.\n         */\n        transitionDelay?: any;\n\n        /**\n         * The 'transition-duration' property specifies the length of time a transition animation takes to complete.\n         */\n        transitionDuration?: any;\n\n        /**\n         * The 'transition-property' property specifies the name of the CSS property to which the transition is applied.\n         */\n        transitionProperty?: any;\n\n        /**\n         * Sets the pace of action within a transition\n         */\n        transitionTimingFunction?: any;\n\n        /**\n         * The unicode-bidi CSS property specifies the level of embedding with respect to the bidirectional algorithm.\n         */\n        unicodeBidi?: any;\n\n        /**\n         * unicode-range allows you to set a specific range of characters to be downloaded from a font (embedded using @font-face) and made available for use on the current page.\n         */\n        unicodeRange?: any;\n\n        /**\n         * This is for all the high level UX stuff.\n         */\n        userFocus?: any;\n\n        /**\n         * For inputing user content\n         */\n        userInput?: any;\n\n        /**\n         * The vertical-align property controls how inline elements or text are vertically aligned compared to the baseline. If this property is used on table-cells it controls the vertical alignment of content of the table cell.\n         */\n        verticalAlign?: any;\n\n        /**\n         * The visibility property specifies whether the boxes generated by an element are rendered.\n         */\n        visibility?: any;\n\n        /**\n         * The voice-balance property sets the apparent position (in stereo sound) of the synthesized voice for spoken media.\n         */\n        voiceBalance?: any;\n\n        /**\n         * The voice-duration property allows the author to explicitly set the amount of time it should take a speech synthesizer to read an element's content, for example to allow the speech to be synchronized with other media. With a value of auto (the default) the length of time it takes to read the content is determined by the content itself and the voice-rate property.\n         */\n        voiceDuration?: any;\n\n        /**\n         * The voice-family property sets the speaker's voice used by a speech media agent to read an element. The speaker may be specified as a named character (to match a voice option in the speech reading software) or as a generic description of the age and gender of the voice. Similar to the font-family property for visual media, a comma-separated list of fallback options may be given in case the speech reader does not recognize the character name or cannot synthesize the requested combination of generic properties.\n         */\n        voiceFamily?: any;\n\n        /**\n         * The voice-pitch property sets pitch or tone (high or low) for the synthesized speech when reading an element; the pitch may be specified absolutely or relative to the normal pitch for the voice-family used to read the text.\n         */\n        voicePitch?: any;\n\n        /**\n         * The voice-range property determines how much variation in pitch or tone will be created by the speech synthesize when reading an element. Emphasized text, grammatical structures and punctuation may all be rendered as changes in pitch, this property determines how strong or obvious those changes are; large ranges are associated with enthusiastic or emotional speech, while small ranges are associated with flat or mechanical speech.\n         */\n        voiceRange?: any;\n\n        /**\n         * The voice-rate property sets the speed at which the voice synthesized by a speech media agent will read content.\n         */\n        voiceRate?: any;\n\n        /**\n         * The voice-stress property sets the level of vocal emphasis to be used for synthesized speech reading the element.\n         */\n        voiceStress?: any;\n\n        /**\n         * The voice-volume property sets the volume for spoken content in speech media. It replaces the deprecated volume property.\n         */\n        voiceVolume?: any;\n\n        /**\n         * The white-space property controls whether and how white space inside the element is collapsed, and whether lines may wrap at unforced \"soft wrap\" opportunities.\n         */\n        whiteSpace?: any;\n\n        /**\n         * Obsolete: unsupported.\n         */\n        whiteSpaceTreatment?: any;\n\n        /**\n         * Specifies the width of the content area of an element. The content area of the element width does not include the padding, border, and margin of the element.\n         */\n        width?: any;\n\n        /**\n         * The word-break property is often used when there is long generated content that is strung together without and spaces or hyphens to beak apart. A common case of this is when there is a long URL that does not have any hyphens. This case could potentially cause the breaking of the layout as it could extend past the parent element.\n         */\n        wordBreak?: any;\n\n        /**\n         * The word-spacing CSS property specifies the spacing behavior between \"words\".\n         */\n        wordSpacing?: any;\n\n        /**\n         * An alias of css/properties/overflow-wrap, word-wrap defines whether to break words when the content exceeds the boundaries of its container.\n         */\n        wordWrap?: any;\n\n        /**\n         * Specifies how exclusions affect inline content within block-level elements. Elements lay out their inline content in their content area but wrap around exclusion areas.\n         */\n        wrapFlow?: any;\n\n        /**\n         * Set the value that is used to offset the inner wrap shape from other shapes. Inline content that intersects a shape with this property will be pushed by this shape's margin.\n         */\n        wrapMargin?: any;\n\n        /**\n         * Obsolete and unsupported. Do not use.\n         * This CSS property controls the text when it reaches the end of the block in which it is enclosed.\n         */\n        wrapOption?: any;\n\n        /**\n         * writing-mode specifies if lines of text are laid out horizontally or vertically, and the direction which lines of text and blocks progress.\n         */\n        writingMode?: any;\n\n\n        [propertyName: string]: any;\n    }\n\n    interface HTMLAttributes extends DOMAttributes {\n        // React-specific Attributes\n        defaultChecked?: boolean;\n        defaultValue?: string | string[];\n\n        // Standard HTML Attributes\n        accept?: string;\n        acceptCharset?: string;\n        accessKey?: string;\n        action?: string;\n        allowFullScreen?: boolean;\n        allowTransparency?: boolean;\n        alt?: string;\n        async?: boolean;\n        autoComplete?: string;\n        autoFocus?: boolean;\n        autoPlay?: boolean;\n        capture?: boolean;\n        cellPadding?: number | string;\n        cellSpacing?: number | string;\n        charSet?: string;\n        challenge?: string;\n        checked?: boolean;\n        classID?: string;\n        className?: string;\n        cols?: number;\n        colSpan?: number;\n        content?: string;\n        contentEditable?: boolean;\n        contextMenu?: string;\n        controls?: boolean;\n        coords?: string;\n        crossOrigin?: string;\n        data?: string;\n        dateTime?: string;\n        default?: boolean;\n        defer?: boolean;\n        dir?: string;\n        disabled?: boolean;\n        download?: any;\n        draggable?: boolean;\n        encType?: string;\n        form?: string;\n        formAction?: string;\n        formEncType?: string;\n        formMethod?: string;\n        formNoValidate?: boolean;\n        formTarget?: string;\n        frameBorder?: number | string;\n        headers?: string;\n        height?: number | string;\n        hidden?: boolean;\n        high?: number;\n        href?: string;\n        hrefLang?: string;\n        htmlFor?: string;\n        httpEquiv?: string;\n        icon?: string;\n        id?: string;\n        inputMode?: string;\n        integrity?: string;\n        is?: string;\n        keyParams?: string;\n        keyType?: string;\n        kind?: string;\n        label?: string;\n        lang?: string;\n        list?: string;\n        loop?: boolean;\n        low?: number;\n        manifest?: string;\n        marginHeight?: number;\n        marginWidth?: number;\n        max?: number | string;\n        maxLength?: number;\n        media?: string;\n        mediaGroup?: string;\n        method?: string;\n        min?: number | string;\n        minLength?: number;\n        multiple?: boolean;\n        muted?: boolean;\n        name?: string;\n        noValidate?: boolean;\n        open?: boolean;\n        optimum?: number;\n        pattern?: string;\n        placeholder?: string;\n        poster?: string;\n        preload?: string;\n        radioGroup?: string;\n        readOnly?: boolean;\n        rel?: string;\n        required?: boolean;\n        role?: string;\n        rows?: number;\n        rowSpan?: number;\n        sandbox?: string;\n        scope?: string;\n        scoped?: boolean;\n        scrolling?: string;\n        seamless?: boolean;\n        selected?: boolean;\n        shape?: string;\n        size?: number;\n        sizes?: string;\n        span?: number;\n        spellCheck?: boolean;\n        src?: string;\n        srcDoc?: string;\n        srcLang?: string;\n        srcSet?: string;\n        start?: number;\n        step?: number | string;\n        style?: CSSProperties;\n        summary?: string;\n        tabIndex?: number;\n        target?: string;\n        title?: string;\n        type?: string;\n        useMap?: string;\n        value?: string | string[];\n        width?: number | string;\n        wmode?: string;\n        wrap?: string;\n\n        // RDFa Attributes\n        about?: string;\n        datatype?: string;\n        inlist?: any;\n        prefix?: string;\n        property?: string;\n        resource?: string;\n        typeof?: string;\n        vocab?: string;\n\n        // Non-standard Attributes\n        autoCapitalize?: string;\n        autoCorrect?: string;\n        autoSave?: string;\n        color?: string;\n        itemProp?: string;\n        itemScope?: boolean;\n        itemType?: string;\n        itemID?: string;\n        itemRef?: string;\n        results?: number;\n        security?: string;\n        unselectable?: boolean;\n    }\n\n    interface SVGAttributes extends HTMLAttributes {\n        clipPath?: string;\n        cx?: number | string;\n        cy?: number | string;\n        d?: string;\n        dx?: number | string;\n        dy?: number | string;\n        fill?: string;\n        fillOpacity?: number | string;\n        fontFamily?: string;\n        fontSize?: number | string;\n        fx?: number | string;\n        fy?: number | string;\n        gradientTransform?: string;\n        gradientUnits?: string;\n        markerEnd?: string;\n        markerMid?: string;\n        markerStart?: string;\n        offset?: number | string;\n        opacity?: number | string;\n        patternContentUnits?: string;\n        patternUnits?: string;\n        points?: string;\n        preserveAspectRatio?: string;\n        r?: number | string;\n        rx?: number | string;\n        ry?: number | string;\n        spreadMethod?: string;\n        stopColor?: string;\n        stopOpacity?: number | string;\n        stroke?: string;\n        strokeDasharray?: string;\n        strokeLinecap?: string;\n        strokeMiterlimit?: string;\n        strokeOpacity?: number | string;\n        strokeWidth?: number | string;\n        textAnchor?: string;\n        transform?: string;\n        version?: string;\n        viewBox?: string;\n        x1?: number | string;\n        x2?: number | string;\n        x?: number | string;\n        xlinkActuate?: string;\n        xlinkArcrole?: string;\n        xlinkHref?: string;\n        xlinkRole?: string;\n        xlinkShow?: string;\n        xlinkTitle?: string;\n        xlinkType?: string;\n        xmlBase?: string;\n        xmlLang?: string;\n        xmlSpace?: string;\n        y1?: number | string;\n        y2?: number | string;\n        y?: number | string;\n    }\n\n    //\n    // React.DOM\n    // ----------------------------------------------------------------------\n\n    interface ReactDOM {\n        // HTML\n        a: HTMLFactory;\n        abbr: HTMLFactory;\n        address: HTMLFactory;\n        area: HTMLFactory;\n        article: HTMLFactory;\n        aside: HTMLFactory;\n        audio: HTMLFactory;\n        b: HTMLFactory;\n        base: HTMLFactory;\n        bdi: HTMLFactory;\n        bdo: HTMLFactory;\n        big: HTMLFactory;\n        blockquote: HTMLFactory;\n        body: HTMLFactory;\n        br: HTMLFactory;\n        button: HTMLFactory;\n        canvas: HTMLFactory;\n        caption: HTMLFactory;\n        cite: HTMLFactory;\n        code: HTMLFactory;\n        col: HTMLFactory;\n        colgroup: HTMLFactory;\n        data: HTMLFactory;\n        datalist: HTMLFactory;\n        dd: HTMLFactory;\n        del: HTMLFactory;\n        details: HTMLFactory;\n        dfn: HTMLFactory;\n        dialog: HTMLFactory;\n        div: HTMLFactory;\n        dl: HTMLFactory;\n        dt: HTMLFactory;\n        em: HTMLFactory;\n        embed: HTMLFactory;\n        fieldset: HTMLFactory;\n        figcaption: HTMLFactory;\n        figure: HTMLFactory;\n        footer: HTMLFactory;\n        form: HTMLFactory;\n        h1: HTMLFactory;\n        h2: HTMLFactory;\n        h3: HTMLFactory;\n        h4: HTMLFactory;\n        h5: HTMLFactory;\n        h6: HTMLFactory;\n        head: HTMLFactory;\n        header: HTMLFactory;\n        hr: HTMLFactory;\n        html: HTMLFactory;\n        i: HTMLFactory;\n        iframe: HTMLFactory;\n        img: HTMLFactory;\n        input: HTMLFactory;\n        ins: HTMLFactory;\n        kbd: HTMLFactory;\n        keygen: HTMLFactory;\n        label: HTMLFactory;\n        legend: HTMLFactory;\n        li: HTMLFactory;\n        link: HTMLFactory;\n        main: HTMLFactory;\n        map: HTMLFactory;\n        mark: HTMLFactory;\n        menu: HTMLFactory;\n        menuitem: HTMLFactory;\n        meta: HTMLFactory;\n        meter: HTMLFactory;\n        nav: HTMLFactory;\n        noscript: HTMLFactory;\n        object: HTMLFactory;\n        ol: HTMLFactory;\n        optgroup: HTMLFactory;\n        option: HTMLFactory;\n        output: HTMLFactory;\n        p: HTMLFactory;\n        param: HTMLFactory;\n        picture: HTMLFactory;\n        pre: HTMLFactory;\n        progress: HTMLFactory;\n        q: HTMLFactory;\n        rp: HTMLFactory;\n        rt: HTMLFactory;\n        ruby: HTMLFactory;\n        s: HTMLFactory;\n        samp: HTMLFactory;\n        script: HTMLFactory;\n        section: HTMLFactory;\n        select: HTMLFactory;\n        small: HTMLFactory;\n        source: HTMLFactory;\n        span: HTMLFactory;\n        strong: HTMLFactory;\n        style: HTMLFactory;\n        sub: HTMLFactory;\n        summary: HTMLFactory;\n        sup: HTMLFactory;\n        table: HTMLFactory;\n        tbody: HTMLFactory;\n        td: HTMLFactory;\n        textarea: HTMLFactory;\n        tfoot: HTMLFactory;\n        th: HTMLFactory;\n        thead: HTMLFactory;\n        time: HTMLFactory;\n        title: HTMLFactory;\n        tr: HTMLFactory;\n        track: HTMLFactory;\n        u: HTMLFactory;\n        ul: HTMLFactory;\n        \"var\": HTMLFactory;\n        video: HTMLFactory;\n        wbr: HTMLFactory;\n\n        // SVG\n        svg: SVGFactory;\n        circle: SVGFactory;\n        defs: SVGFactory;\n        ellipse: SVGFactory;\n        g: SVGFactory;\n        image: SVGFactory;\n        line: SVGFactory;\n        linearGradient: SVGFactory;\n        mask: SVGFactory;\n        path: SVGFactory;\n        pattern: SVGFactory;\n        polygon: SVGFactory;\n        polyline: SVGFactory;\n        radialGradient: SVGFactory;\n        rect: SVGFactory;\n        stop: SVGFactory;\n        text: SVGFactory;\n        tspan: SVGFactory;\n    }\n\n    //\n    // React.PropTypes\n    // ----------------------------------------------------------------------\n\n    interface Validator<T> {\n        (object: T, key: string, componentName: string): Error;\n    }\n\n    interface Requireable<T> extends Validator<T> {\n        isRequired: Validator<T>;\n    }\n\n    interface ValidationMap<T> {\n        [key: string]: Validator<T>;\n    }\n\n    interface ReactPropTypes {\n        any: Requireable<any>;\n        array: Requireable<any>;\n        bool: Requireable<any>;\n        func: Requireable<any>;\n        number: Requireable<any>;\n        object: Requireable<any>;\n        string: Requireable<any>;\n        node: Requireable<any>;\n        element: Requireable<any>;\n        instanceOf(expectedClass: {}): Requireable<any>;\n        oneOf(types: any[]): Requireable<any>;\n        oneOfType(types: Validator<any>[]): Requireable<any>;\n        arrayOf(type: Validator<any>): Requireable<any>;\n        objectOf(type: Validator<any>): Requireable<any>;\n        shape(type: ValidationMap<any>): Requireable<any>;\n    }\n\n    //\n    // React.Children\n    // ----------------------------------------------------------------------\n\n    interface ReactChildren {\n        map<T>(children: ReactNode, fn: (child: ReactChild, index: number) => T): T[];\n        forEach(children: ReactNode, fn: (child: ReactChild, index: number) => any): void;\n        count(children: ReactNode): number;\n        only(children: ReactNode): ReactElement<any>;\n        toArray(children: ReactNode): ReactChild[];\n    }\n\n    //\n    // Browser Interfaces\n    // https://github.com/nikeee/2048-typescript/blob/master/2048/js/touch.d.ts\n    // ----------------------------------------------------------------------\n\n    interface AbstractView {\n        styleMedia: StyleMedia;\n        document: Document;\n    }\n\n    interface Touch {\n        identifier: number;\n        target: EventTarget;\n        screenX: number;\n        screenY: number;\n        clientX: number;\n        clientY: number;\n        pageX: number;\n        pageY: number;\n    }\n\n    interface TouchList {\n        [index: number]: Touch;\n        length: number;\n        item(index: number): Touch;\n        identifiedTouch(identifier: number): Touch;\n    }\n}\n\ndeclare module \"react\" {\n    export = __React;\n}\n\ndeclare namespace JSX {\n    import React = __React;\n\n    interface Element extends React.ReactElement<any> { }\n    interface ElementClass extends React.Component<any, any> {\n        render(): JSX.Element;\n    }\n    interface ElementAttributesProperty { props: {}; }\n\n    interface IntrinsicAttributes {\n        key?: string | number;\n    }\n\n    interface IntrinsicClassAttributes<T> {\n        ref?: string | ((classInstance: T) => void);\n    }\n\n    interface IntrinsicElements {\n        // HTML\n        a: React.HTMLProps<HTMLAnchorElement>;\n        abbr: React.HTMLProps<HTMLElement>;\n        address: React.HTMLProps<HTMLElement>;\n        area: React.HTMLProps<HTMLAreaElement>;\n        article: React.HTMLProps<HTMLElement>;\n        aside: React.HTMLProps<HTMLElement>;\n        audio: React.HTMLProps<HTMLAudioElement>;\n        b: React.HTMLProps<HTMLElement>;\n        base: React.HTMLProps<HTMLBaseElement>;\n        bdi: React.HTMLProps<HTMLElement>;\n        bdo: React.HTMLProps<HTMLElement>;\n        big: React.HTMLProps<HTMLElement>;\n        blockquote: React.HTMLProps<HTMLElement>;\n        body: React.HTMLProps<HTMLBodyElement>;\n        br: React.HTMLProps<HTMLBRElement>;\n        button: React.HTMLProps<HTMLButtonElement>;\n        canvas: React.HTMLProps<HTMLCanvasElement>;\n        caption: React.HTMLProps<HTMLElement>;\n        cite: React.HTMLProps<HTMLElement>;\n        code: React.HTMLProps<HTMLElement>;\n        col: React.HTMLProps<HTMLTableColElement>;\n        colgroup: React.HTMLProps<HTMLTableColElement>;\n        data: React.HTMLProps<HTMLElement>;\n        datalist: React.HTMLProps<HTMLDataListElement>;\n        dd: React.HTMLProps<HTMLElement>;\n        del: React.HTMLProps<HTMLElement>;\n        details: React.HTMLProps<HTMLElement>;\n        dfn: React.HTMLProps<HTMLElement>;\n        dialog: React.HTMLProps<HTMLElement>;\n        div: React.HTMLProps<HTMLDivElement>;\n        dl: React.HTMLProps<HTMLDListElement>;\n        dt: React.HTMLProps<HTMLElement>;\n        em: React.HTMLProps<HTMLElement>;\n        embed: React.HTMLProps<HTMLEmbedElement>;\n        fieldset: React.HTMLProps<HTMLFieldSetElement>;\n        figcaption: React.HTMLProps<HTMLElement>;\n        figure: React.HTMLProps<HTMLElement>;\n        footer: React.HTMLProps<HTMLElement>;\n        form: React.HTMLProps<HTMLFormElement>;\n        h1: React.HTMLProps<HTMLHeadingElement>;\n        h2: React.HTMLProps<HTMLHeadingElement>;\n        h3: React.HTMLProps<HTMLHeadingElement>;\n        h4: React.HTMLProps<HTMLHeadingElement>;\n        h5: React.HTMLProps<HTMLHeadingElement>;\n        h6: React.HTMLProps<HTMLHeadingElement>;\n        head: React.HTMLProps<HTMLHeadElement>;\n        header: React.HTMLProps<HTMLElement>;\n        hr: React.HTMLProps<HTMLHRElement>;\n        html: React.HTMLProps<HTMLHtmlElement>;\n        i: React.HTMLProps<HTMLElement>;\n        iframe: React.HTMLProps<HTMLIFrameElement>;\n        img: React.HTMLProps<HTMLImageElement>;\n        input: React.HTMLProps<HTMLInputElement>;\n        ins: React.HTMLProps<HTMLModElement>;\n        kbd: React.HTMLProps<HTMLElement>;\n        keygen: React.HTMLProps<HTMLElement>;\n        label: React.HTMLProps<HTMLLabelElement>;\n        legend: React.HTMLProps<HTMLLegendElement>;\n        li: React.HTMLProps<HTMLLIElement>;\n        link: React.HTMLProps<HTMLLinkElement>;\n        main: React.HTMLProps<HTMLElement>;\n        map: React.HTMLProps<HTMLMapElement>;\n        mark: React.HTMLProps<HTMLElement>;\n        menu: React.HTMLProps<HTMLElement>;\n        menuitem: React.HTMLProps<HTMLElement>;\n        meta: React.HTMLProps<HTMLMetaElement>;\n        meter: React.HTMLProps<HTMLElement>;\n        nav: React.HTMLProps<HTMLElement>;\n        noscript: React.HTMLProps<HTMLElement>;\n        object: React.HTMLProps<HTMLObjectElement>;\n        ol: React.HTMLProps<HTMLOListElement>;\n        optgroup: React.HTMLProps<HTMLOptGroupElement>;\n        option: React.HTMLProps<HTMLOptionElement>;\n        output: React.HTMLProps<HTMLElement>;\n        p: React.HTMLProps<HTMLParagraphElement>;\n        param: React.HTMLProps<HTMLParamElement>;\n        picture: React.HTMLProps<HTMLElement>;\n        pre: React.HTMLProps<HTMLPreElement>;\n        progress: React.HTMLProps<HTMLProgressElement>;\n        q: React.HTMLProps<HTMLQuoteElement>;\n        rp: React.HTMLProps<HTMLElement>;\n        rt: React.HTMLProps<HTMLElement>;\n        ruby: React.HTMLProps<HTMLElement>;\n        s: React.HTMLProps<HTMLElement>;\n        samp: React.HTMLProps<HTMLElement>;\n        script: React.HTMLProps<HTMLElement>;\n        section: React.HTMLProps<HTMLElement>;\n        select: React.HTMLProps<HTMLSelectElement>;\n        small: React.HTMLProps<HTMLElement>;\n        source: React.HTMLProps<HTMLSourceElement>;\n        span: React.HTMLProps<HTMLSpanElement>;\n        strong: React.HTMLProps<HTMLElement>;\n        style: React.HTMLProps<HTMLStyleElement>;\n        sub: React.HTMLProps<HTMLElement>;\n        summary: React.HTMLProps<HTMLElement>;\n        sup: React.HTMLProps<HTMLElement>;\n        table: React.HTMLProps<HTMLTableElement>;\n        tbody: React.HTMLProps<HTMLTableSectionElement>;\n        td: React.HTMLProps<HTMLTableDataCellElement>;\n        textarea: React.HTMLProps<HTMLTextAreaElement>;\n        tfoot: React.HTMLProps<HTMLTableSectionElement>;\n        th: React.HTMLProps<HTMLTableHeaderCellElement>;\n        thead: React.HTMLProps<HTMLTableSectionElement>;\n        time: React.HTMLProps<HTMLElement>;\n        title: React.HTMLProps<HTMLTitleElement>;\n        tr: React.HTMLProps<HTMLTableRowElement>;\n        track: React.HTMLProps<HTMLTrackElement>;\n        u: React.HTMLProps<HTMLElement>;\n        ul: React.HTMLProps<HTMLUListElement>;\n        \"var\": React.HTMLProps<HTMLElement>;\n        video: React.HTMLProps<HTMLVideoElement>;\n        wbr: React.HTMLProps<HTMLElement>;\n\n        // SVG\n        svg: React.SVGProps;\n\n        circle: React.SVGProps;\n        clipPath: React.SVGProps;\n        defs: React.SVGProps;\n        ellipse: React.SVGProps;\n        g: React.SVGProps;\n        image: React.SVGProps;\n        line: React.SVGProps;\n        linearGradient: React.SVGProps;\n        mask: React.SVGProps;\n        path: React.SVGProps;\n        pattern: React.SVGProps;\n        polygon: React.SVGProps;\n        polyline: React.SVGProps;\n        radialGradient: React.SVGProps;\n        rect: React.SVGProps;\n        stop: React.SVGProps;\n        text: React.SVGProps;\n        tspan: React.SVGProps;\n    }\n}\n"
  },
  {
    "path": "example/.vscode/typings/react-native/react-native.d.ts",
    "content": "// Type definitions for react-native 0.14\n// Project: https://github.com/facebook/react-native\n// Definitions by: Bruno Grieder <https://github.com/bgrieder>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n//\n// USING: these definitions are meant to be used with the TSC compiler target set to ES6\n//\n// USAGE EXAMPLES: check the RNTSExplorer project at https://github.com/bgrieder/RNTSExplorer\n//\n// CONTRIBUTING: please open pull requests and make sure that the changes do not break RNTSExplorer (they should not)\n// Do not hesitate to open a pull request against RNTSExplorer to provide an example for a case not covered by the current App\n//\n// CREDITS: This work is based on an original work made by Bernd Paradies: https://github.com/bparadie\n//\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/// <reference path=\"../react/react.d.ts\" />\n\n//so we know what is \"original\" React\nimport React = __React;\n\n//react-native \"extends\" react\ndeclare namespace  __React {\n\n\n    /**\n     * Represents the completion of an asynchronous operation\n     * @see lib.es6.d.ts\n     */\n    export interface Promise<T> {\n        /**\n         * Attaches callbacks for the resolution and/or rejection of the Promise.\n         * @param onfulfilled The callback to execute when the Promise is resolved.\n         * @param onrejected The callback to execute when the Promise is rejected.\n         * @returns A Promise for the completion of which ever callback is executed.\n         */\n        then<TResult>( onfulfilled?: ( value: T ) => TResult | Promise<TResult>, onrejected?: ( reason: any ) => TResult | Promise<TResult> ): Promise<TResult>;\n\n        /**\n         * Attaches a callback for only the rejection of the Promise.\n         * @param onrejected The callback to execute when the Promise is rejected.\n         * @returns A Promise for the completion of the callback.\n         */\n        catch( onrejected?: ( reason: any ) => T | Promise<T> ): Promise<T>;\n\n\n        // not in lib.es6.d.ts but called by react-native\n        done( callback?: ( value: T ) => void ): void;\n    }\n\n    export interface PromiseConstructor {\n        /**\n         * A reference to the prototype.\n         */\n        prototype: Promise<any>;\n\n        /**\n         * Creates a new Promise.\n         * @param init A callback used to initialize the promise. This callback is passed two arguments:\n         * a resolve callback used resolve the promise with a value or the result of another promise,\n         * and a reject callback used to reject the promise with a provided reason or error.\n         */\n        new <T>( init: ( resolve: ( value?: T | Promise<T> ) => void, reject: ( reason?: any ) => void ) => void ): Promise<T>;\n\n        <T>( init: ( resolve: ( value?: T | Promise<T> ) => void, reject: ( reason?: any ) => void ) => void ): Promise<T>;\n\n        /**\n         * Creates a Promise that is resolved with an array of results when all of the provided Promises\n         * resolve, or rejected when any Promise is rejected.\n         * @param values An array of Promises.\n         * @returns A new Promise.\n         */\n        all<T>( values: (T | Promise<T>)[] ): Promise<T[]>;\n\n        /**\n         * Creates a Promise that is resolved with an array of results when all of the provided Promises\n         * resolve, or rejected when any Promise is rejected.\n         * @param values An array of values.\n         * @returns A new Promise.\n         */\n        all( values: Promise<void>[] ): Promise<void>;\n\n        /**\n         * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\n         * or rejected.\n         * @param values An array of Promises.\n         * @returns A new Promise.\n         */\n        race<T>( values: (T | Promise<T>)[] ): Promise<T>;\n\n        /**\n         * Creates a new rejected promise for the provided reason.\n         * @param reason The reason the promise was rejected.\n         * @returns A new rejected Promise.\n         */\n        reject( reason: any ): Promise<void>;\n\n        /**\n         * Creates a new rejected promise for the provided reason.\n         * @param reason The reason the promise was rejected.\n         * @returns A new rejected Promise.\n         */\n        reject<T>( reason: any ): Promise<T>;\n\n        /**\n         * Creates a new resolved promise for the provided value.\n         * @param value A promise.\n         * @returns A promise whose internal state matches the provided promise.\n         */\n        resolve<T>( value: T | Promise<T> ): Promise<T>;\n\n        /**\n         * Creates a new resolved promise .\n         * @returns A resolved promise.\n         */\n        resolve(): Promise<void>;\n    }\n\n    // @see lib.es6.d.ts\n    export var Promise: PromiseConstructor;\n\n    //TODO: BGR: Replace with ComponentClass ?\n    // node_modules/react-tools/src/classic/class/ReactClass.js\n    export interface ReactClass<D, P, S> {\n        // TODO:\n    }\n\n    // see react-jsx.d.ts\n    export function createElement<P>( type: React.ReactType,\n                                      props?: P,\n                                      ...children: React.ReactNode[] ): React.ReactElement<P>;\n\n\n    export type Runnable = ( appParameters: any ) => void;\n\n\n    // Similar to React.SyntheticEvent except for nativeEvent\n    interface NativeSyntheticEvent<T> {\n        bubbles: boolean\n        cancelable: boolean\n        currentTarget: EventTarget\n        defaultPrevented: boolean\n        eventPhase: number\n        isTrusted: boolean\n        nativeEvent: T\n        preventDefault(): void\n        stopPropagation(): void\n        target: EventTarget\n        timeStamp: Date\n        type: string\n    }\n\n    export interface NativeTouchEvent {\n        /**\n         * Array of all touch events that have changed since the last event\n         */\n        changedTouches: NativeTouchEvent[]\n\n        /**\n         * The ID of the touch\n         */\n        identifier: string\n\n        /**\n         * The X position of the touch, relative to the element\n         */\n        locationX: number\n\n        /**\n         * The Y position of the touch, relative to the element\n         */\n        locationY: number\n\n        /**\n         * The X position of the touch, relative to the screen\n         */\n        pageX: number\n\n        /**\n         * The Y position of the touch, relative to the screen\n         */\n        pageY: number\n\n        /**\n         * The node id of the element receiving the touch event\n         */\n        target: string\n\n        /**\n         * A time identifier for the touch, useful for velocity calculation\n         */\n        timestamp: number\n\n        /**\n         * Array of all current touches on the screen\n         */\n        touches : NativeTouchEvent[]\n    }\n\n    export interface GestureResponderEvent extends NativeSyntheticEvent<NativeTouchEvent> {\n    }\n\n\n    export interface  PointProperties {\n        x: number\n        y: number\n    }\n\n    export interface Insets {\n        top?: number\n        left?: number\n        bottom?: number\n        right?: number\n    }\n\n    /**\n     * //FIXME: need to find documentation on which compoenent is a native (i.e. non composite component)\n     */\n    export interface NativeComponent {\n        setNativeProps: ( props: Object ) => void\n    }\n\n    /**\n     * //FIXME: need to find documentation on which component is a TTouchable and can implement that interface\n     * @see React.DOMAtributes\n     */\n    export interface Touchable {\n        onTouchStart?: ( event: GestureResponderEvent ) => void\n        onTouchMove?: ( event: GestureResponderEvent ) => void\n        onTouchEnd?: ( event: GestureResponderEvent ) => void\n        onTouchCancel?: ( event: GestureResponderEvent ) => void\n        onTouchEndCapture?: ( event: GestureResponderEvent ) => void\n    }\n\n    export type AppConfig = {\n        appKey: string;\n        component: ReactClass<any, any, any>;\n        run?: Runnable;\n    }\n\n    // https://github.com/facebook/react-native/blob/master/Libraries/AppRegistry/AppRegistry.js\n    export class AppRegistry {\n        static registerConfig( config: AppConfig[] ): void;\n\n        static registerComponent( appKey: string, getComponentFunc: () => React.ComponentClass<any> ): string;\n\n        static registerRunnable( appKey: string, func: Runnable ): string;\n\n        static runApplication( appKey: string, appParameters: any ): void;\n    }\n\n    export interface LayoutAnimationTypes {\n        spring: string\n        linear: string\n        easeInEaseOut: string\n        easeIn: string\n        easeOut: string\n    }\n\n    export interface LayoutAnimationProperties {\n        opacity: string\n        scaleXY: string\n    }\n\n    export interface LayoutAnimationAnim {\n        duration?: number\n        delay?: number\n        springDamping?: number\n        initialVelocity?: number\n        type?: string //LayoutAnimationTypes\n        property?: string //LayoutAnimationProperties\n    }\n\n    export interface LayoutAnimationConfig {\n        duration: number\n        create?: LayoutAnimationAnim\n        update?: LayoutAnimationAnim\n        delete?: LayoutAnimationAnim\n    }\n\n    export interface LayoutAnimationStatic {\n\n        configureNext: ( config: LayoutAnimationConfig, onAnimationDidEnd?: () => void, onError?: ( error?: any ) => void ) => void\n        create: ( duration: number, type?: string, creationProp?: string ) => LayoutAnimationConfig\n        Types: LayoutAnimationTypes\n        Properties: LayoutAnimationProperties\n        configChecker: ( conf: {config: LayoutAnimationConfig}, name: string, next: string ) => void\n        Presets : {\n            easeInEaseOut: LayoutAnimationConfig\n            linear:LayoutAnimationConfig\n            spring: LayoutAnimationConfig\n        }\n    }\n\n\n    /**\n     * Flex Prop Types\n     * @see https://facebook.github.io/react-native/docs/flexbox.html#proptypes\n     * @see LayoutPropTypes.js\n     */\n    export interface FlexStyle {\n\n        alignItems?: string;  //enum('flex-start', 'flex-end', 'center', 'stretch')\n        alignSelf?: string// enum('auto', 'flex-start', 'flex-end', 'center', 'stretch')\n        borderBottomWidth?: number\n        borderLeftWidth?: number\n        borderRightWidth?: number\n        borderTopWidth?: number\n        borderWidth?: number\n        bottom?: number\n        flex?: number\n        flexDirection?: string // enum('row', 'column')\n        flexWrap?: string // enum('wrap', 'nowrap')\n        height?: number\n        justifyContent?: string // enum('flex-start', 'flex-end', 'center', 'space-between', 'space-around')\n        left?: number\n        margin?: number\n        marginBottom?: number\n        marginHorizontal?: number\n        marginLeft?: number\n        marginRight?: number\n        marginTop?: number\n        marginVertical?: number\n        padding?: number\n        paddingBottom?: number\n        paddingHorizontal?: number\n        paddingLeft?: number\n        paddingRight?: number\n        paddingTop?: number\n        paddingVertical?: number\n        position?: string // enum('absolute', 'relative')\n        right?: number\n        top?: number\n        width?: number\n    }\n\n\n    export interface TransformsStyle {\n\n        transform?: [{perspective: number}, {rotate: string}, {rotateX: string}, {rotateY: string}, {rotateZ: string}, {scale: number}, {scaleX: number}, {scaleY: number}, {translateX: number}, {translateY: number}, {skewX: string}, {skewY: string}]\n        transformMatrix?: Array<number>\n        rotation?: number\n        scaleX?: number\n        scaleY?: number\n        translateX?: number\n        translateY?: number\n    }\n\n\n    export interface StyleSheetProperties {\n        // TODO:\n    }\n\n    export interface LayoutRectangle {\n        x: number;\n        y: number;\n        width: number;\n        height: number;\n    }\n\n    // @see TextProperties.onLayout\n    export interface LayoutChangeEvent {\n        nativeEvent: {\n            layout: LayoutRectangle\n        }\n    }\n\n    // @see https://facebook.github.io/react-native/docs/text.html#style\n    export interface TextStyle extends ViewStyle {\n        color?: string\n        fontFamily?: string\n        fontSize?: number\n        fontStyle?: string // 'normal' | 'italic';\n        fontWeight?: string // enum(\"normal\", 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900')\n        letterSpacing?: number\n        lineHeight?: number\n        textAlign?: string // enum(\"auto\", 'left', 'right', 'center')\n        textDecorationLine?: string // enum(\"none\", 'underline', 'line-through', 'underline line-through')\n        textDecorationStyle?: string // enum(\"solid\", 'double', 'dotted', 'dashed')\n        textDecorationColor?: string\n        writingDirection?: string; //enum(\"auto\", 'ltr', 'rtl')\n        //containerBackgroundColor?: string\n    }\n\n    export interface TextPropertiesIOS {\n\n        /**\n         * When true, no visual change is made when text is pressed down.\n         * By default, a gray oval highlights the text on press down.\n         */\n        suppressHighlighting?: boolean\n    }\n\n    // https://facebook.github.io/react-native/docs/text.html#props\n    export interface TextProperties extends React.Props<TextProperties> {\n\n        /**\n         * Specifies should fonts scale to respect Text Size accessibility setting on iOS.\n         */\n        allowFontScaling?: boolean\n\n        /**\n         * Used to truncate the text with an elipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number.\n         */\n        numberOfLines?: number\n\n        /**\n         * Invoked on mount and layout changes with\n         *\n         * {nativeEvent: { layout: {x, y, width, height}}}.\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void\n\n        /**\n         * This function is called on press.\n         * Text intrinsically supports press handling with a default highlight state (which can be disabled with suppressHighlighting).\n         */\n        onPress?: () => void\n\n        /**\n         * @see https://facebook.github.io/react-native/docs/text.html#style\n         */\n        style?: TextStyle\n\n        /**\n         * Used to locate this view in end-to-end tests.\n         */\n        testID?: string\n    }\n\n    /**\n     * A React component for displaying text which supports nesting, styling, and touch handling.\n     */\n    export interface TextStatic extends React.ComponentClass<TextProperties> {\n\n    }\n\n\n    /**\n     * IOS Specific properties for TextInput\n     * @see https://facebook.github.io/react-native/docs/textinput.html#props\n     */\n    export interface TextInputIOSProperties {\n\n        /**\n         * If true, the text field will blur when submitted.\n         * The default value is true.\n         */\n        blurOnSubmit?: boolean\n\n        /**\n         * enum('never', 'while-editing', 'unless-editing', 'always')\n         * When the clear button should appear on the right side of the text view\n         */\n        clearButtonMode?: string\n\n        /**\n         * If true, clears the text field automatically when editing begins\n         */\n        clearTextOnFocus?: boolean\n\n        /**\n         * If true, the keyboard disables the return key when there is no text and automatically enables it when there is text.\n         * The default value is false.\n         */\n        enablesReturnKeyAutomatically?: boolean\n\n        /**\n         * Callback that is called when a key is pressed.\n         * Pressed key value is passed as an argument to the callback handler.\n         * Fires before onChange callbacks.\n         */\n        onKeyPress?: () => void\n\n        /**\n         * enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call')\n         * Determines how the return key should look.\n         */\n        returnKeyType?: string\n\n        /**\n         * If true, all text will automatically be selected on focus\n         */\n        selectTextOnFocus?: boolean\n\n        /**\n         * //FIXME: requires typing\n         * See DocumentSelectionState.js, some state that is responsible for maintaining selection information for a document\n         */\n        selectionState?: any\n\n\n    }\n\n    /**\n     * Android Specific properties for TextInput\n     * @see https://facebook.github.io/react-native/docs/textinput.html#props\n     */\n    export interface TextInputAndroidProperties {\n\n        /**\n         * Sets the number of lines for a TextInput.\n         * Use it with multiline set to true to be able to fill the lines.\n         */\n        numberOfLines?: number\n\n        /**\n         * enum('start', 'center', 'end')\n         * Set the position of the cursor from where editing will begin.\n         */\n        textAlign?: string\n\n        /**\n         * enum('top', 'center', 'bottom')\n         * Aligns text vertically within the TextInput.\n         */\n        textAlignVertical?: string\n\n        /**\n         * The color of the textInput underline.\n         */\n        underlineColorAndroid?: string\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/textinput.html#props\n     */\n    export interface TextInputProperties extends TextInputIOSProperties, TextInputAndroidProperties, React.Props<TextInputStatic> {\n\n        /**\n         * Can tell TextInput to automatically capitalize certain characters.\n         *      characters: all characters,\n         *      words: first letter of each word\n         *      sentences: first letter of each sentence (default)\n         *      none: don't auto capitalize anything\n         *\n         * https://facebook.github.io/react-native/docs/textinput.html#autocapitalize\n         */\n        autoCapitalize?: string\n\n        /**\n         * If false, disables auto-correct.\n         * The default value is true.\n         */\n        autoCorrect?: boolean\n\n        /**\n         * If true, focuses the input on componentDidMount.\n         * The default value is false.\n         */\n        autoFocus?: boolean\n\n        /**\n         * Provides an initial value that will change when the user starts typing.\n         * Useful for simple use-cases where you don't want to deal with listening to events\n         * and updating the value prop to keep the controlled state in sync.\n         */\n        defaultValue?: string\n\n        /**\n         * If false, text is not editable. The default value is true.\n         */\n        editable?: boolean\n\n        /**\n         * enum(\"default\", 'numeric', 'email-address', \"ascii-capable\", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search')\n         * Determines which keyboard to open, e.g.numeric.\n         * The following values work across platforms: - default - numeric - email-address\n         */\n        keyboardType?: string\n\n        /**\n         * Limits the maximum number of characters that can be entered.\n         * Use this instead of implementing the logic in JS to avoid flicker.\n         */\n        maxLength?: number\n\n        /**\n         * If true, the text input can be multiple lines. The default value is false.\n         */\n        multiline?: boolean\n\n        /**\n         * Callback that is called when the text input is blurred\n         */\n        onBlur?: () => void\n\n        /**\n         * Callback that is called when the text input's text changes.\n         */\n        onChange?: ( event: {nativeEvent: {text: string}} ) => void\n\n        /**\n         * Callback that is called when the text input's text changes.\n         * Changed text is passed as an argument to the callback handler.\n         */\n        onChangeText?: ( text: string ) => void\n\n        /**\n         * Callback that is called when text input ends.\n         */\n        onEndEditing?: ( event: {nativeEvent: {text: string}} ) => void\n\n        /**\n         * Callback that is called when the text input is focused\n         */\n        onFocus?: () => void\n\n        /**\n         * Invoked on mount and layout changes with {x, y, width, height}.\n         */\n        onLayout?: ( event: {nativeEvent: {x: number, y: number, width: number, height: number}} ) => void\n\n        /**\n         * Callback that is called when the text input's submit button is pressed.\n         */\n        onSubmitEditing?: ( event: {nativeEvent: {text: string}} ) => void\n\n        /**\n         * //FIXME: Not part of the doc but found in examples\n         */\n        password?: boolean\n\n        /**\n         * The string that will be rendered before text input has been entered\n         */\n        placeholder?: string\n\n        /**\n         * The text color of the placeholder string\n         */\n        placeholderTextColor?: string\n\n        /**\n         * If true, the text input obscures the text entered so that sensitive text like passwords stay secure.\n         * The default value is false.\n         */\n        secureTextEntry?: boolean\n\n        /**\n         * Styles\n         */\n        style?: TextStyle\n\n        /**\n         * Used to locate this view in end-to-end tests\n         */\n        testID?: string\n\n        /**\n         * The value to show for the text input. TextInput is a controlled component,\n         * which means the native value will be forced to match this value prop if provided.\n         * For most uses this works great, but in some cases this may cause flickering - one common cause is preventing edits by keeping value the same.\n         * In addition to simply setting the same value, either set editable={false},\n         * or set/update maxLength to prevent unwanted edits without flicker.\n         */\n        value?: string\n    }\n\n    export interface TextInputStatic extends NativeComponent, React.ComponentClass<TextInputProperties> {\n        blur: () => void\n        focus: () => void\n    }\n\n\n    /**\n     * Gesture recognition on mobile devices is much more complicated than web.\n     * A touch can go through several phases as the app determines what the user's intention is.\n     * For example, the app needs to determine if the touch is scrolling, sliding on a widget, or tapping.\n     * This can even change during the duration of a touch. There can also be multiple simultaneous touches.\n     *\n     * The touch responder system is needed to allow components to negotiate these touch interactions\n     * without any additional knowledge about their parent or child components.\n     * This system is implemented in ResponderEventPlugin.js, which contains further details and documentation.\n     *\n     * Best Practices\n     * Users can feel huge differences in the usability of web apps vs. native, and this is one of the big causes.\n     * Every action should have the following attributes:\n     *      Feedback/highlighting- show the user what is handling their touch, and what will happen when they release the gesture\n     *      Cancel-ability- when making an action, the user should be able to abort it mid-touch by dragging their finger away\n     *\n     * These features make users more comfortable while using an app,\n     * because it allows people to experiment and interact without fear of making mistakes.\n     *\n     * TouchableHighlight and Touchable*\n     * The responder system can be complicated to use.\n     * So we have provided an abstract Touchable implementation for things that should be \"tappable\".\n     * This uses the responder system and allows you to easily configure tap interactions declaratively.\n     * Use TouchableHighlight anywhere where you would use a button or link on web.\n     */\n    export interface GestureResponderHandlers {\n\n        /**\n         * A view can become the touch responder by implementing the correct negotiation methods.\n         * There are two methods to ask the view if it wants to become responder:\n         */\n\n        /**\n         * Does this view want to become responder on the start of a touch?\n         */\n        onStartShouldSetResponder?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * Called for every touch move on the View when it is not the responder: does this view want to \"claim\" touch responsiveness?\n         */\n        onMoveShouldSetResponder?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * If the View returns true and attempts to become the responder, one of the following will happen:\n         */\n\n        /**\n         * The View is now responding for touch events.\n         * This is the time to highlight and show the user what is happening\n         */\n        onResponderGrant?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * Something else is the responder right now and will not release it\n         */\n        onResponderReject?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * If the view is responding, the following handlers can be called:\n         */\n\n        /**\n         * The user is moving their finger\n         */\n        onResponderMove?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * Fired at the end of the touch, ie \"touchUp\"\n         */\n        onResponderRelease?: ( event: GestureResponderEvent ) => void\n\n        /**\n         *  Something else wants to become responder.\n         *  Should this view release the responder? Returning true allows release\n         */\n        onResponderTerminationRequest?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * The responder has been taken from the View.\n         * Might be taken by other views after a call to onResponderTerminationRequest,\n         * or might be taken by the OS without asking (happens with control center/ notification center on iOS)\n         */\n        onResponderTerminate?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern,\n         * where the deepest node is called first.\n         * That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers.\n         * This is desirable in most cases, because it makes sure all controls and buttons are usable.\n         *\n         * However, sometimes a parent will want to make sure that it becomes responder.\n         * This can be handled by using the capture phase.\n         * Before the responder system bubbles up from the deepest component,\n         * it will do a capture phase, firing on*ShouldSetResponderCapture.\n         * So if a parent View wants to prevent the child from becoming responder on a touch start,\n         * it should have a onStartShouldSetResponderCapture handler which returns true.\n         */\n        onStartShouldSetResponderCapture?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern,\n         * where the deepest node is called first.\n         * That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers.\n         * This is desirable in most cases, because it makes sure all controls and buttons are usable.\n         *\n         * However, sometimes a parent will want to make sure that it becomes responder.\n         * This can be handled by using the capture phase.\n         * Before the responder system bubbles up from the deepest component,\n         * it will do a capture phase, firing on*ShouldSetResponderCapture.\n         * So if a parent View wants to prevent the child from becoming responder on a touch start,\n         * it should have a onStartShouldSetResponderCapture handler which returns true.\n         */\n        onMoveShouldSetResponderCapture?: () => void;\n\n    }\n\n    // @see https://facebook.github.io/react-native/docs/view.html#style\n    export interface ViewStyle extends FlexStyle, TransformsStyle {\n        backgroundColor?: string;\n        borderBottomColor?: string;\n        borderBottomLeftRadius?: number;\n        borderBottomRightRadius?: number;\n        borderColor?: string;\n        borderLeftColor?: string;\n        borderRadius?: number;\n        borderRightColor?: string;\n        borderTopColor?: string;\n        borderTopLeftRadius?: number;\n        borderTopRightRadius?: number;\n        opacity?: number;\n        overflow?: string; // enum('visible', 'hidden')\n        shadowColor?: string;\n        shadowOffset?: {width: number, height: number};\n        shadowOpacity?: number;\n        shadowRadius?: number;\n    }\n\n\n    export interface ViewPropertiesIOS {\n\n        /**\n         * Provides additional traits to screen reader.\n         * By default no traits are provided unless specified otherwise in element\n         *\n         * @enum('none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text','summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn')\n         */\n        accessibilityTraits?: string | string[];\n\n        /**\n         * Whether this view should be rendered as a bitmap before compositing.\n         *\n         * On iOS, this is useful for animations and interactions that do not modify this component's dimensions nor its children;\n         * for example, when translating the position of a static view, rasterization allows the renderer to reuse a cached bitmap of a static view\n         * and quickly composite it during each frame.\n         *\n         * Rasterization incurs an off-screen drawing pass and the bitmap consumes memory.\n         * Test and measure when using this property.\n         */\n        shouldRasterizeIOS?: boolean\n    }\n\n    export interface ViewPropertiesAndroid {\n\n        /**\n         * Indicates to accessibility services to treat UI component like a native one.\n         * Works for Android only.\n         *\n         * @enum('none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' )\n         */\n        accessibilityComponentType?: string\n\n\n        /**\n         * Indicates to accessibility services whether the user should be notified when this view changes.\n         * Works for Android API >= 19 only.\n         * See http://developer.android.com/reference/android/view/View.html#attr_android:accessibilityLiveRegion for references.\n         */\n        accessibilityLiveRegion?: string\n\n        /**\n         * Views that are only used to layout their children or otherwise don't draw anything\n         * may be automatically removed from the native hierarchy as an optimization.\n         * Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy.\n         */\n        collapsable?: boolean\n\n\n        /**\n         * Controls how view is important for accessibility which is if it fires accessibility events\n         * and if it is reported to accessibility services that query the screen.\n         * Works for Android only. See http://developer.android.com/reference/android/R.attr.html#importantForAccessibility for references.\n         *\n         * Possible values:\n         *      'auto' - The system determines whether the view is important for accessibility - default (recommended).\n         *      'yes' - The view is important for accessibility.\n         *      'no' - The view is not important for accessibility.\n         *      'no-hide-descendants' - The view is not important for accessibility, nor are any of its descendant views.\n         */\n        importantForAccessibility?: string\n\n\n        /**\n         * Whether this view needs to rendered offscreen and composited with an alpha in order to preserve 100% correct colors and blending behavior.\n         * The default (false) falls back to drawing the component and its children\n         * with an alpha applied to the paint used to draw each element instead of rendering the full component offscreen and compositing it back with an alpha value.\n         * This default may be noticeable and undesired in the case where the View you are setting an opacity on\n         * has multiple overlapping elements (e.g. multiple overlapping Views, or text and a background).\n         *\n         * Rendering offscreen to preserve correct alpha behavior is extremely expensive\n         * and hard to debug for non-native developers, which is why it is not turned on by default.\n         * If you do need to enable this property for an animation,\n         * consider combining it with renderToHardwareTextureAndroid if the view contents are static (i.e. it doesn't need to be redrawn each frame).\n         * If that property is enabled, this View will be rendered off-screen once,\n         * saved in a hardware texture, and then composited onto the screen with an alpha each frame without having to switch rendering targets on the GPU.\n         */\n        needsOffscreenAlphaCompositing?: boolean\n\n\n        /**\n         * Whether this view should render itself (and all of its children) into a single hardware texture on the GPU.\n         *\n         * On Android, this is useful for animations and interactions that only modify opacity, rotation, translation, and/or scale:\n         * in those cases, the view doesn't have to be redrawn and display lists don't need to be re-executed. The texture can just be\n         * re-used and re-composited with different parameters. The downside is that this can use up limited video memory, so this prop should be set back to false at the end of the interaction/animation.\n         */\n        renderToHardwareTextureAndroid?: boolean;\n\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/view.html#props\n     */\n    export interface ViewProperties extends ViewPropertiesAndroid, ViewPropertiesIOS, GestureResponderHandlers, Touchable, React.Props<ViewStatic> {\n\n        /**\n         * Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space.\n         */\n        accessibilityLabel?: string;\n\n        /**\n         * When true, indicates that the view is an accessibility element.\n         * By default, all the touchable elements are accessible.\n         */\n        accessible?: boolean;\n\n        /**\n         * When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture.\n         */\n        onAcccessibilityTap?: () => void;\n\n        /**\n         * Invoked on mount and layout changes with\n         *\n         * {nativeEvent: { layout: {x, y, width, height}}}.\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void;\n\n        /**\n         * When accessible is true, the system will invoke this function when the user performs the magic tap gesture.\n         */\n        onMagicTap?: () => void;\n\n        /**\n         *\n         * In the absence of auto property, none is much like CSS's none value. box-none is as if you had applied the CSS class:\n         *\n         * .box-none {\n         *   pointer-events: none;\n         * }\n         * .box-none * {\n         *   pointer-events: all;\n         * }\n         *\n         * box-only is the equivalent of\n         *\n         * .box-only {\n         *   pointer-events: all;\n         * }\n         * .box-only * {\n         *   pointer-events: none;\n         * }\n         *\n         * But since pointerEvents does not affect layout/appearance, and we are already deviating from the spec by adding additional modes,\n         * we opt to not include pointerEvents on style. On some platforms, we would need to implement it as a className anyways. Using style or not is an implementation detail of the platform.\n         */\n        pointerEvents?: string;\n\n        /**\n         *\n         * This is a special performance property exposed by RCTView and is useful for scrolling content when there are many subviews,\n         * most of which are offscreen. For this property to be effective, it must be applied to a view that contains many subviews that extend outside its bound.\n         * The subviews must also have overflow: hidden, as should the containing view (or one of its superviews).\n         */\n        removeClippedSubviews?: boolean\n\n        style?: ViewStyle;\n\n        /**\n         * Used to locate this view in end-to-end tests.\n         */\n        testID?: string;\n    }\n\n    /**\n     * The most fundamental component for building UI, View is a container that supports layout with flexbox, style, some touch handling,\n     * and accessibility controls, and is designed to be nested inside other views and to have 0 to many children of any type.\n     * View maps directly to the native view equivalent on whatever platform React is running on,\n     * whether that is a UIView, <div>, android.view, etc.\n     */\n    export interface ViewStatic extends NativeComponent, React.ComponentClass<ViewProperties> {\n\n    }\n\n    /**\n     * //FIXME: No documentation extracted from code comment on WebView.ios.js\n     */\n    export interface NavState {\n\n        url?: string\n        title?: string\n        loading?: boolean\n        canGoBack?: boolean\n        canGoForward?: boolean;\n\n        [key: string]: any\n    }\n\n    export interface WebViewPropertiesAndroid {\n\n        /**\n         * Used for android only, JS is enabled by default for WebView on iOS\n         */\n        javaScriptEnabledAndroid?: boolean\n    }\n\n    export interface WebViewPropertiesIOS {\n\n        /**\n         * Used for iOS only, sets whether the webpage scales to fit the view and the user can change the scale\n         */\n        scalesPageToFit?: boolean\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/webview.html#props\n     */\n    export interface WebViewProperties extends WebViewPropertiesAndroid, WebViewPropertiesIOS, React.Props<WebViewStatic> {\n\n        automaticallyAdjustContentInsets?: boolean\n\n        bounces?: boolean\n\n        contentInset?: Insets\n\n        html?: string\n\n        /**\n         * Sets the JS to be injected when the webpage loads.\n         */\n        injectedJavaScript?: string\n\n        onNavigationStateChange?: ( event: NavState ) => void\n\n        /**\n         * Allows custom handling of any webview requests by a JS handler.\n         * Return true or false from this method to continue loading the request.\n         */\n        onShouldStartLoadWithRequest?: () => boolean\n\n        /**\n         * view to show if there's an error\n         */\n        renderError?: () => ViewStatic\n\n        /**\n         * loading indicator to show\n         */\n        renderLoading?: () => ViewStatic\n\n        scrollEnabled?: boolean\n\n        startInLoadingState?: boolean\n\n        style?: ViewStyle\n\n        url: string\n    }\n\n\n    export interface WebViewStatic extends React.ComponentClass<WebViewProperties> {\n\n        goBack: () => void\n        goForward: () => void\n        reload: () => void\n    }\n\n\n    /**\n     * @see\n     */\n    export interface SegmentedControlIOSProperties {\n        /// TODO\n    }\n\n\n    export interface NavigatorIOSProperties extends React.Props<NavigatorIOSStatic> {\n\n        /**\n         * NavigatorIOS uses \"route\" objects to identify child views, their props, and navigation bar configuration.\n         * \"push\" and all the other navigation operations expect routes to be like this\n         */\n        initialRoute?: Route\n\n        /**\n         * The default wrapper style for components in the navigator.\n         * A common use case is to set the backgroundColor for every page\n         */\n        itemWrapperStyle?: ViewStyle\n\n        /**\n         * A Boolean value that indicates whether the navigation bar is hidden\n         */\n        navigationBarHidden?: boolean\n\n        /**\n         * A Boolean value that indicates whether to hide the 1px hairline shadow\n         */\n        shadowHidden?: boolean\n\n        /**\n         * The color used for buttons in the navigation bar\n         */\n        tintColor?: string\n\n        /**\n         * The text color of the navigation bar title\n         */\n        titleTextColor?: string\n\n        /**\n         * A Boolean value that indicates whether the navigation bar is translucent\n         */\n        translucent?: boolean\n\n        /**\n         * NOT IN THE DOC BUT IN THE EXAMPLES\n         */\n        style?: ViewStyle\n    }\n\n    /**\n     * A navigator is an object of navigation functions that a view can call.\n     * It is passed as a prop to any component rendered by NavigatorIOS.\n     *\n     * Navigator functions are also available on the NavigatorIOS component:\n     *\n     * @see https://facebook.github.io/react-native/docs/navigatorios.html#navigator\n     */\n    export interface NavigationIOS {\n        /**\n         * Navigate forward to a new route\n         */\n        push: ( route: Route ) => void\n\n        /**\n         * Go back one page\n         */\n        pop: () => void\n\n        /**\n         * Go back N pages at once. When N=1, behavior matches pop()\n         */\n        popN: ( n: number ) => void\n\n        /**\n         * Replace the route for the current page and immediately load the view for the new route\n         */\n        replace: ( route: Route ) => void\n\n        /**\n         * Replace the route/view for the previous page\n         */\n        replacePrevious: ( route: Route ) => void\n\n        /**\n         * Replaces the previous route/view and transitions back to it\n         */\n        replacePreviousAndPop: ( route: Route ) => void\n\n        /**\n         * Replaces the top item and popToTop\n         */\n        resetTo: ( route: Route ) => void\n\n        /**\n         * Go back to the item for a particular route object\n         */\n        popToRoute( route: Route ): void\n\n        /**\n         * Go back to the top item\n         */\n        popToTop(): void\n    }\n\n    export interface NavigatorIOSStatic extends NavigationIOS, React.ComponentClass<NavigatorIOSProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/activityindicatorios.html#props\n     */\n    export interface ActivityIndicatorIOSProperties extends React.Props<ActivityIndicatorIOSStatic> {\n\n        /**\n         * Whether to show the indicator (true, the default) or hide it (false).\n         */\n        animating?: boolean\n\n        /**\n         * The foreground color of the spinner (default is gray).\n         */\n        color?: string\n\n        /**\n         * Whether the indicator should hide when not animating (true by default).\n         */\n        hidesWhenStopped?: boolean\n\n        /**\n         * Invoked on mount and layout changes with\n         */\n        onLayout?: ( event: {nativeEvent: { layout: {x: number, y: number , width: number, height: number}}} ) => void\n\n        /**\n         * Size of the indicator.\n         * Small has a height of 20, large has a height of 36.\n         *\n         * enum('small', 'large')\n         */\n        size?: string\n\n        style?: ViewStyle\n    }\n\n    export interface ActivityIndicatorIOSStatic extends React.ComponentClass<ActivityIndicatorIOSProperties> {\n    }\n\n\n    export interface DatePickerIOSProperties extends React.Props<DatePickerIOSStatic> {\n\n        /**\n         * The currently selected date.\n         */\n        date?: Date\n\n\n        /**\n         * Maximum date.\n         * Restricts the range of possible date/time values.\n         */\n        maximumDate?: Date\n\n        /**\n         * Maximum date.\n         * Restricts the range of possible date/time values.\n         */\n        minimumDate?: Date\n\n        /**\n         *  enum(1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30)\n         *  The interval at which minutes can be selected.\n         */\n        minuteInterval?: number\n\n        /**\n         *  enum('date', 'time', 'datetime')\n         *  The date picker mode.\n         */\n        mode?: string\n\n        /**\n         * Date change handler.\n         * This is called when the user changes the date or time in the UI.\n         * The first and only argument is a Date object representing the new date and time.\n         */\n        onDateChange?: ( newDate: Date ) => void\n\n        /**\n         * Timezone offset in minutes.\n         * By default, the date picker will use the device's timezone. With this parameter, it is possible to force a certain timezone offset.\n         * For instance, to show times in Pacific Standard Time, pass -7 * 60.\n         */\n        timeZoneOffsetInMinutes?: number\n\n    }\n\n    export interface DatePickerIOSStatic extends React.ComponentClass<DatePickerIOSProperties> {\n    }\n\n\n    /**\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSItemProperties extends React.Props<PickerIOSItemStatic> {\n        value?: string | number\n        label?: string\n    }\n\n    /**\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSItemStatic extends React.ComponentClass<PickerIOSItemProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/pickerios.html\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSProperties extends React.Props<PickerIOSStatic> {\n\n        onValueChange?: ( value: string | number ) => void\n\n        selectedValue?: string | number\n\n        style?: ViewStyle\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/pickerios.html\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSStatic extends React.ComponentClass<PickerIOSProperties> {\n\n        Item: PickerIOSItemStatic\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/sliderios.html\n     */\n    export interface SliderIOSProperties extends React.Props<SliderIOSStatic> {\n\n        /**\n         * If true the user won't be able to move the slider. Default value is false.\n         */\n        disabled?: boolean\n\n        /**\n         * Initial maximum value of the slider. Default value is 1.\n         */\n        maximumValue?: number\n\n        /**\n         * The color used for the track to the right of the button. Overrides the default blue gradient image.\n         */\n        maximumTrackTintColor?: string\n\n        /**\n         * Initial minimum value of the slider. Default value is 0.\n         */\n        minimumValue?: number\n\n        /**\n         * The color used for the track to the left of the button. Overrides the default blue gradient image.\n         */\n        minimumTrackTintColor?: string\n\n        /**\n         * Callback called when the user finishes changing the value (e.g. when the slider is released).\n         */\n        onSlidingComplete?: () => void\n\n        /**\n         * Callback continuously called while the user is dragging the slider.\n         */\n        onValueChange?: ( value: number ) => void\n\n        /**\n         * Step value of the slider.\n         * The value should be between 0 and (maximumValue - minimumValue).\n         * Default value is 0.\n         */\n        step?: number\n\n        /**\n         * Used to style and layout the Slider.\n         * @see StyleSheet.js and ViewStylePropTypes.js for more info.\n         */\n        style?: ViewStyle\n\n        /**\n         * Initial value of the slider.\n         * The value should be between minimumValue and maximumValue, which default to 0 and 1 respectively.\n         * Default value is 0.\n         *\n         * This is not a controlled component, e.g. if you don't update the value, the component won't be reset to its inital value.\n         */\n        value?: number\n    }\n\n    export interface SliderIOSStatic extends React.ComponentClass<SliderIOSProperties> {\n\n    }\n\n    /**\n     * //FIXME: no dcumentation, inferred\n     * @see SwitchIOS.ios.js\n     */\n    export interface SwitchIOSStyle extends ViewStyle {\n        height?: number\n        width?: number\n    }\n\n\n    /**\n     * https://facebook.github.io/react-native/docs/switchios.html#props\n     */\n    export interface SwitchIOSProperties extends React.Props<SwitchIOSStatic> {\n\n        /**\n         * If true the user won't be able to toggle the switch. Default value is false.\n         */\n        disabled?: boolean\n\n        /**\n         * Background color when the switch is turned on.\n         */\n        onTintColor?: string\n\n        /**\n         * Callback that is called when the user toggles the switch.\n         */\n        onValueChange?: ( value: boolean ) => void\n\n        /**\n         * Background color for the switch round button.\n         */\n        thumbTintColor?: string\n\n        /**\n         * Background color when the switch is turned off.\n         */\n        tintColor?: string\n\n        /**\n         * The value of the switch, if true the switch will be turned on. Default value is false.\n         */\n        value?: boolean\n\n        style?: SwitchIOSStyle\n    }\n\n    /**\n     *\n     * Use SwitchIOS to render a boolean input on iOS.\n     *\n     * This is a controlled component, so you must hook in to the onValueChange callback and update the value prop in order for the component to update,\n     * otherwise the user's change will be reverted immediately to reflect props.value as the source of truth.\n     *\n     * @see https://facebook.github.io/react-native/docs/switchios.html\n     */\n    export interface SwitchIOSStatic extends React.ComponentClass<SwitchIOSProperties> {\n\n    }\n\n\n    /**\n     * @see ImageResizeMode.js\n     */\n    export interface ImageResizeModeStatic {\n        /**\n         * contain - The image will be resized such that it will be completely\n         * visible, contained within the frame of the View.\n         */\n        contain: string\n        /**\n         * cover - The image will be resized such that the entire area of the view\n         * is covered by the image, potentially clipping parts of the image.\n         */\n        cover: string\n        /**\n         * stretch - The image will be stretched to fill the entire frame of the\n         * view without clipping.  This may change the aspect ratio of the image,\n         * distoring it.  Only supported on iOS.\n         */\n        stretch: string\n    }\n\n    /**\n     * Image style\n     * @see https://facebook.github.io/react-native/docs/image.html#style\n     */\n    export interface ImageStyle extends FlexStyle, TransformsStyle {\n        resizeMode?: string //Object.keys(ImageResizeMode)\n        backgroundColor?: string\n        borderColor?: string\n        borderWidth?: number\n        borderRadius?: number\n        overflow?: string // enum('visible', 'hidden')\n        tintColor?: string\n        opacity?: number\n    }\n\n    export interface ImagePropertiesIOS {\n        /**\n         * The text that's read by the screen reader when the user interacts with the image.\n         */\n        accessibilityLabel?: string;\n\n        /**\n         * When true, indicates the image is an accessibility element.\n         */\n        accessible?: boolean;\n\n        /**\n         * When the image is resized, the corners of the size specified by capInsets will stay a fixed size,\n         * but the center content and borders of the image will be stretched.\n         * This is useful for creating resizable rounded buttons, shadows, and other resizable assets.\n         * More info on Apple documentation\n         */\n        capInsets?: Insets\n\n        /**\n         * A static image to display while downloading the final image off the network.\n         */\n        defaultSource?: {uri: string}\n\n        /**\n         * Invoked on load error with {nativeEvent: {error}}\n         */\n        onError?: ( error: {nativeEvent: any} ) => void\n\n        /**\n         * Invoked when load completes successfully\n         */\n        onLoad?: () => void\n\n        /**\n         * Invoked when load either succeeds or fails\n         */\n        onLoadEnd?: () => void\n\n        /**\n         * Invoked on load start\n         */\n        onLoadStart?: () => void\n\n        /**\n         * Invoked on download progress with {nativeEvent: {loaded, total}}\n         */\n        onProgress?: ()=> void\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/image.html\n     */\n    export interface ImageProperties extends ImagePropertiesIOS, React.Props<Image> {\n        /**\n         * onLayout function\n         *\n         * Invoked on mount and layout changes with\n         *\n         * {nativeEvent: { layout: {x, y, width, height}}}.\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void;\n\n\n        /**\n         * Determines how to resize the image when the frame doesn't match the raw image dimensions.\n         *\n         * enum('cover', 'contain', 'stretch')\n         */\n        resizeMode?: string;\n\n        /**\n         * uri is a string representing the resource identifier for the image,\n         * which could be an http address, a local file path,\n         * or the name of a static image resource (which should be wrapped in the require('image!name') function).\n         */\n        source: {uri: string} | string;\n\n        /**\n         *\n         * Style\n         */\n        style?:  ImageStyle;\n\n        /**\n         * A unique identifier for this element to be used in UI Automation testing scripts.\n         */\n        testID?: string;\n\n    }\n\n    export interface ImageStatic extends React.ComponentClass<ImageProperties> {\n        uri: string;\n        resizeMode: ImageResizeModeStatic\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/listview.html#props\n     */\n    export interface ListViewProperties extends ScrollViewProperties, React.Props<ListViewStatic> {\n\n        dataSource?: ListViewDataSource\n\n        /**\n         * How many rows to render on initial component mount.  Use this to make\n         * it so that the first screen worth of data apears at one time instead of\n         * over the course of multiple frames.\n         */\n        initialListSize?: number\n\n        /**\n         * (visibleRows, changedRows) => void\n         *\n         * Called when the set of visible rows changes.  `visibleRows` maps\n         * { sectionID: { rowID: true }} for all the visible rows, and\n         * `changedRows` maps { sectionID: { rowID: true | false }} for the rows\n         * that have changed their visibility, with true indicating visible, and\n         * false indicating the view has moved out of view.\n         */\n        onChangeVisibleRows?: ( visibleRows: Array<{[sectionId: string]: {[rowID: string]: boolean}}>, changedRows: Array<{[sectionId: string]: {[rowID: string]: boolean}}> ) => void\n\n        /**\n         * Called when all rows have been rendered and the list has been scrolled\n         * to within onEndReachedThreshold of the bottom.  The native scroll\n         * event is provided.\n         */\n        onEndReached?: () => void\n\n        /**\n         * Threshold in pixels for onEndReached.\n         */\n        onEndReachedThreshold?: number\n\n        /**\n         * Number of rows to render per event loop.\n         */\n        pageSize?: number\n\n        /**\n         * An experimental performance optimization for improving scroll perf of\n         * large lists, used in conjunction with overflow: 'hidden' on the row\n         * containers.  Use at your own risk.\n         */\n        removeClippedSubviews?: boolean\n\n        /**\n         * () => renderable\n         *\n         * The header and footer are always rendered (if these props are provided)\n         * on every render pass.  If they are expensive to re-render, wrap them\n         * in StaticContainer or other mechanism as appropriate.  Footer is always\n         * at the bottom of the list, and header at the top, on every render pass.\n         */\n        renderFooter?: () => React.ReactElement<any>\n\n        /**\n         * () => renderable\n         *\n         * The header and footer are always rendered (if these props are provided)\n         * on every render pass.  If they are expensive to re-render, wrap them\n         * in StaticContainer or other mechanism as appropriate.  Footer is always\n         * at the bottom of the list, and header at the top, on every render pass.\n         */\n        renderHeader?: () => React.ReactElement<any>\n\n        /**\n         * (rowData, sectionID, rowID) => renderable\n         * Takes a data entry from the data source and its ids and should return\n         * a renderable component to be rendered as the row.  By default the data\n         * is exactly what was put into the data source, but it's also possible to\n         * provide custom extractors.\n         */\n        renderRow?: ( rowData: any, sectionID: string | number, rowID: string | number, highlightRow?: boolean ) => React.ReactElement<any>\n\n\n        /**\n         * A function that returns the scrollable component in which the list rows are rendered.\n         * Defaults to returning a ScrollView with the given props.\n         */\n        renderScrollComponent?: ( props: ScrollViewProperties ) => React.ReactElement<ScrollViewProperties>\n\n        /**\n         * (sectionData, sectionID) => renderable\n         *\n         * If provided, a sticky header is rendered for this section.  The sticky\n         * behavior means that it will scroll with the content at the top of the\n         * section until it reaches the top of the screen, at which point it will\n         * stick to the top until it is pushed off the screen by the next section\n         * header.\n         */\n        renderSectionHeader?: ( sectionData: any, sectionId: string | number ) => React.ReactElement<any>\n\n\n        /**\n         * (sectionID, rowID, adjacentRowHighlighted) => renderable\n         * If provided, a renderable component to be rendered as the separator below each row\n         * but not the last row if there is a section header below.\n         * Take a sectionID and rowID of the row above and whether its adjacent row is highlighted.\n         */\n        renderSeparator?: ( sectionID: string | number, rowID: string | number, adjacentRowHighlighted?: boolean ) => React.ReactElement<any>\n\n        /**\n         * How early to start rendering rows before they come on screen, in\n         * pixels.\n         */\n        scrollRenderAheadDistance?: number\n    }\n\n    export interface ListViewStatic extends React.ComponentClass<ListViewProperties> {\n        DataSource: ListViewDataSource;\n    }\n\n\n    export interface MapViewAnnotation {\n        latitude?: number\n        longitude?: number\n        animateDrop?: boolean\n        title?: string\n        subtitle?: string\n        hasLeftCallout?: boolean\n        hasRightCallout?: boolean\n        onLeftCalloutPress?: () => void\n        onRightCalloutPress?: () => void\n        id?: string\n    }\n\n    export interface MapViewRegion {\n        latitude: number\n        longitude: number\n        latitudeDelta: number\n        longitudeDelta: number\n    }\n\n    export interface MapViewPropertiesIOS {\n\n        /**\n         * If false points of interest won't be displayed on the map.\n         * Default value is true.\n         */\n        showsPointsOfInterest?: boolean\n    }\n\n    export interface MapViewProperties extends MapViewPropertiesIOS, Touchable, React.Props<MapViewStatic> {\n\n        /**\n         * Map annotations with title/subtitle.\n         */\n        annotations?: MapViewAnnotation[]\n\n        /**\n         * Insets for the map's legal label, originally at bottom left of the map. See EdgeInsetsPropType.js for more information.\n         */\n        legalLabelInsets?: Insets\n\n        /**\n         * The map type to be displayed.\n         *     standard: standard road map (default)\n         *     satellite: satellite view\n         *     hybrid: satellite view with roads and points of interest overlayed\n         *\n         * enum('standard', 'satellite', 'hybrid')\n         */\n        mapType?: string\n\n        /**\n         * Maximum size of area that can be displayed.\n         */\n        maxDelta?: number\n\n        /**\n         * Minimum size of area that can be displayed.\n         */\n        minDelta?: number\n\n        /**\n         * Callback that is called once, when the user taps an annotation.\n         */\n        onAnnotationPress?: () => void\n\n        /**\n         * Callback that is called continuously when the user is dragging the map.\n         */\n        onRegionChange?: ( region: MapViewRegion ) => void\n\n        /**\n         * Callback that is called once, when the user is done moving the map.\n         */\n        onRegionChangeComplete?: ( region: MapViewRegion ) => void\n\n        /**\n         * When this property is set to true and a valid camera is associated with the map,\n         * the camera’s pitch angle is used to tilt the plane of the map.\n         *\n         * When this property is set to false, the camera’s pitch angle is ignored and\n         * the map is always displayed as if the user is looking straight down onto it.\n         */\n        pitchEnabled?: boolean\n\n        /**\n         * The region to be displayed by the map.\n         * The region is defined by the center coordinates and the span of coordinates to display.\n         */\n        region?: MapViewRegion\n\n        /**\n         * When this property is set to true and a valid camera is associated with the map,\n         * the camera’s heading angle is used to rotate the plane of the map around its center point.\n         *\n         * When this property is set to false, the camera’s heading angle is ignored and the map is always oriented\n         * so that true north is situated at the top of the map view\n         */\n        rotateEnabled?: boolean\n\n        /**\n         * If false the user won't be able to change the map region being displayed.\n         * Default value is true.\n         */\n        scrollEnabled?: boolean\n\n        /**\n         * If true the app will ask for the user's location and focus on it.\n         * Default value is false.\n         *\n         * NOTE: You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation,\n         * otherwise it is going to fail silently!\n         */\n        showsUserLocation?: boolean\n\n        /**\n         * Used to style and layout the MapView.\n         * See StyleSheet.js and ViewStylePropTypes.js for more info.\n         */\n        style?: ViewStyle\n\n        /**\n         * If false the user won't be able to pinch/zoom the map.\n         * Default value is true.\n         */\n        zoomEnabled?: boolean\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/mapview.html#content\n     */\n    export interface MapViewStatic extends React.ComponentClass<MapViewProperties> {\n    }\n\n\n    export interface TouchableWithoutFeedbackAndroidProperties {\n\n        /**\n         * Indicates to accessibility services to treat UI component like a native one.\n         * Works for Android only.\n         *\n         * @enum('none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' )\n         */\n        accessibilityComponentType?: string\n    }\n\n    export interface TouchableWithoutFeedbackIOSProperties {\n\n        /**\n         * Provides additional traits to screen reader.\n         * By default no traits are provided unless specified otherwise in element\n         *\n         * @enum('none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text','summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn')\n         */\n        accessibilityTraits?: string | string[];\n\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#props\n     */\n    export interface TouchableWithoutFeedbackProperties extends TouchableWithoutFeedbackAndroidProperties, TouchableWithoutFeedbackIOSProperties {\n\n\n        /**\n         * Called when the touch is released, but not if cancelled (e.g. by a scroll that steals the responder lock).\n         */\n        accessible?: boolean\n\n        /**\n         * Delay in ms, from onPressIn, before onLongPress is called.\n         */\n        delayLongPress?: number;\n\n        /**\n         * Delay in ms, from the start of the touch, before onPressIn is called.\n         */\n        delayPressIn?: number;\n\n        /**\n         * Delay in ms, from the release of the touch, before onPressOut is called.\n         */\n        delayPressOut?: number;\n\n        /**\n         * Invoked on mount and layout changes with\n         * {nativeEvent: {layout: {x, y, width, height}}}\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void\n\n        onLongPress?: () => void;\n\n        /**\n         * Called when the touch is released,\n         * but not if cancelled (e.g. by a scroll that steals the responder lock).\n         */\n        onPress?: () => void;\n\n        onPressIn?: () => void;\n\n        onPressOut?: () => void;\n\n        /**\n         * //FIXME: not in doc but available in exmaples\n         */\n        style?: ViewStyle\n    }\n\n\n    export interface TouchableWithoutFeedbackProps extends TouchableWithoutFeedbackProperties, React.Props<TouchableWithoutFeedbackStatic> {\n\n    }\n\n    /**\n     * Do not use unless you have a very good reason.\n     * All the elements that respond to press should have a visual feedback when touched.\n     * This is one of the primary reason a \"web\" app doesn't feel \"native\".\n     *\n     * @see https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html\n     */\n    export interface TouchableWithoutFeedbackStatic extends React.ComponentClass<TouchableWithoutFeedbackProps> {\n\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchablehighlight.html#props\n     */\n    export interface TouchableHighlightProperties extends TouchableWithoutFeedbackProperties, React.Props<TouchableHighlightStatic> {\n\n        /**\n         * Determines what the opacity of the wrapped view should be when touch is active.\n         */\n        activeOpacity?: number\n\n        /**\n         *\n         * Called immediately after the underlay is hidden\n         */\n        onHideUnderlay?: () => void\n\n        /**\n         * Called immediately after the underlay is shown\n         */\n        onShowUnderlay?: () => void\n\n        /**\n         * @see https://facebook.github.io/react-native/docs/view.html#style\n         */\n        style?: ViewStyle\n\n\n        /**\n         * The color of the underlay that will show through when the touch is active.\n         */\n        underlayColor?: string\n    }\n\n    /**\n     * A wrapper for making views respond properly to touches.\n     * On press down, the opacity of the wrapped view is decreased,\n     * which allows the underlay color to show through, darkening or tinting the view.\n     * The underlay comes from adding a view to the view hierarchy,\n     * which can sometimes cause unwanted visual artifacts if not used correctly,\n     * for example if the backgroundColor of the wrapped view isn't explicitly set to an opaque color.\n     *\n     * NOTE: TouchableHighlight supports only one child\n     * If you wish to have several child components, wrap them in a View.\n     *\n     * @see https://facebook.github.io/react-native/docs/touchablehighlight.html\n     */\n    export interface TouchableHighlightStatic extends React.ComponentClass<TouchableHighlightProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchableopacity.html#props\n     */\n    export interface TouchableOpacityProperties extends TouchableWithoutFeedbackProperties, React.Props<TouchableOpacityStatic> {\n        /**\n         * Determines what the opacity of the wrapped view should be when touch is active.\n         * Defaults to 0.2\n         */\n        activeOpacity?: number\n    }\n\n    /**\n     * A wrapper for making views respond properly to touches.\n     * On press down, the opacity of the wrapped view is decreased, dimming it.\n     * This is done without actually changing the view hierarchy,\n     * and in general is easy to add to an app without weird side-effects.\n     *\n     * @see https://facebook.github.io/react-native/docs/touchableopacity.html\n     */\n    export interface TouchableOpacityStatic extends React.ComponentClass<TouchableOpacityProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchableopacity.html#props\n     */\n    export interface TouchableNativeFeedbackProperties extends TouchableWithoutFeedbackProperties, React.Props<TouchableNativeFeedbackStatic> {\n        /**\n         * Determines the type of background drawable that's going to be used to display feedback.\n         * It takes an object with type property and extra data depending on the type.\n         * It's recommended to use one of the following static methods to generate that dictionary:\n         *      1) TouchableNativeFeedback.SelectableBackground() - will create object that represents android theme's default background for selectable elements (?android:attr/selectableItemBackground)\n         *      2) TouchableNativeFeedback.SelectableBackgroundBorderless() - will create object that represent android theme's default background for borderless selectable elements (?android:attr/selectableItemBackgroundBorderless). Available on android API level 21+\n         *      3) TouchableNativeFeedback.Ripple(color, borderless) - will create object that represents ripple drawable with specified color (as a string). If property borderless evaluates to true the ripple will render outside of the view bounds (see native actionbar buttons as an example of that behavior). This background type is available on Android API level 21+\n         */\n        background?: any\n    }\n\n    /**\n     * A wrapper for making views respond properly to touches (Android only).\n     * On Android this component uses native state drawable to display touch feedback.\n     * At the moment it only supports having a single View instance as a child node,\n     * as it's implemented by replacing that View with another instance of RCTView node with some additional properties set.\n     *\n     * Background drawable of native feedback touchable can be customized with background property.\n     *\n     * @see https://facebook.github.io/react-native/docs/touchablenativefeedback.html#content\n     */\n    export interface TouchableNativeFeedbackStatic extends React.ComponentClass<TouchableNativeFeedbackProperties> {\n        SelectableBackground: () => TouchableNativeFeedbackStatic\n        SelectableBackgroundBorderless: () => TouchableNativeFeedbackStatic\n        Ripple: ( color: string, borderless?: boolean ) => TouchableNativeFeedbackStatic\n    }\n\n\n    export interface LeftToRightGesture {\n        //TODO:\n    }\n\n    export interface AnimationInterpolator {\n        //TODO:\n    }\n\n    // see /NavigatorSceneConfigs.js\n    export interface SceneConfig {\n        // A list of all gestures that are enabled on this scene\n        gestures: {\n            pop: LeftToRightGesture,\n        },\n\n        // Rebound spring parameters when transitioning FROM this scene\n        springFriction: number;\n        springTension: number;\n\n        // Velocity to start at when transitioning without gesture\n        defaultTransitionVelocity: number;\n\n        // Animation interpolators for horizontal transitioning:\n        animationInterpolators: {\n            into: AnimationInterpolator,\n            out: AnimationInterpolator\n        };\n\n    }\n\n    // see /NavigatorSceneConfigs.js\n    export interface SceneConfigs {\n        FloatFromBottom: SceneConfig;\n        FloatFromRight: SceneConfig;\n        PushFromRight: SceneConfig;\n        FloatFromLeft: SceneConfig;\n        HorizontalSwipeJump: SceneConfig;\n    }\n\n    export interface Route {\n        component?: ComponentClass<ViewProperties>\n        id?: string\n        title?: string\n        passProps?: Object;\n\n        //anything else\n        [key: string]: any\n\n        //Commonly found properties\n        backButtonTitle?: string\n        content?: string\n        message?: string;\n        index?: number\n        onRightButtonPress?: () => void\n        rightButtonTitle?: string\n        sceneConfig?: SceneConfig\n        wrapperStyle?: any\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/navigator.html#content\n     */\n    export interface NavigatorProperties extends React.Props<Navigator> {\n        /**\n         * Optional function that allows configuration about scene animations and gestures.\n         * Will be invoked with the route and should return a scene configuration object\n         * @param route\n         */\n        configureScene?: ( route: Route ) => SceneConfig\n        /**\n         * Specify a route to start on.\n         * A route is an object that the navigator will use to identify each scene to render.\n         * initialRoute must be a route in the initialRouteStack if both props are provided.\n         * The initialRoute will default to the last item in the initialRouteStack.\n         */\n        initialRoute?: Route\n        /**\n         * Provide a set of routes to initially mount.\n         * Required if no initialRoute is provided.\n         * Otherwise, it will default to an array containing only the initialRoute\n         */\n        initialRouteStack?: Route[]\n\n        /**\n         * Optionally provide a navigation bar that persists across scene transitions\n         */\n        navigationBar?: React.ReactElement<NavigatorStatic.NavigationBarProperties>\n\n        /**\n         * Optionally provide the navigator object from a parent Navigator\n         */\n        navigator?: Navigator\n\n        /**\n         * @deprecated Use navigationContext.addListener('willfocus', callback) instead.\n         */\n        onDidFocus?: Function\n\n        /**\n         * @deprecated Use navigationContext.addListener('willfocus', callback) instead.\n         */\n        onWillFocus?: Function\n\n        /**\n         * Required function which renders the scene for a given route.\n         * Will be invoked with the route and the navigator object\n         * @param route\n         * @param navigator\n         */\n        renderScene?: ( route: Route, navigator: Navigator ) => React.ReactElement<ViewProperties>\n\n        /**\n         * Styles to apply to the container of each scene\n         */\n        sceneStyle?: ViewStyle\n\n        /**\n         * //FIXME: not found in doc but found in examples\n         */\n        debugOverlay?: boolean\n\n    }\n\n    /**\n     * Use Navigator to transition between different scenes in your app.\n     * To accomplish this, provide route objects to the navigator to identify each scene,\n     * and also a renderScene function that the navigator can use to render the scene for a given route.\n     *\n     * To change the animation or gesture properties of the scene, provide a configureScene prop to get the config object for a given route.\n     * See Navigator.SceneConfigs for default animations and more info on scene config options.\n     * @see https://facebook.github.io/react-native/docs/navigator.html\n     */\n    export interface NavigatorStatic extends React.ComponentClass<NavigatorProperties> {\n        SceneConfigs: SceneConfigs;\n        NavigationBar: NavigatorStatic.NavigationBarStatic;\n        BreadcrumbNavigationBar: NavigatorStatic.BreadcrumbNavigationBarStatic\n\n        getContext( self: any ): NavigatorStatic;\n\n        /**\n         * returns the current list of routes\n         */\n        getCurrentRoutes(): Route[];\n\n        /**\n         * Jump backward without unmounting the current scen\n         */\n        jumpBack(): void;\n\n        /**\n         * Jump forward to the next scene in the route stack\n         */\n        jumpForward(): void;\n\n        /**\n         * Transition to an existing scene without unmounting\n         */\n        jumpTo( route: Route ): void;\n\n        /**\n         * Navigate forward to a new scene, squashing any scenes that you could jumpForward to\n         */\n        push( route: Route ): void;\n\n        /**\n         * Transition back and unmount the current scene\n         */\n        pop(): void;\n\n        /**\n         * Replace the current scene with a new route\n         */\n        replace( route: Route ): void;\n\n        /**\n         * Replace a scene as specified by an index\n         */\n        replaceAtIndex( route: Route, index: number ): void;\n\n        /**\n         *  Replace the previous scene\n         */\n        replacePrevious( route: Route ): void;\n\n        /**\n         * Reset every scene with an array of routes\n         */\n        immediatelyResetRouteStack( routes: Route[] ): void;\n\n        /**\n         * Pop to a particular scene, as specified by its route. All scenes after it will be unmounted\n         */\n        popToRoute( route: Route ): void;\n\n        /**\n         * Pop to the first scene in the stack, unmounting every other scene\n         */\n        popToTop(): void;\n\n    }\n\n    namespace NavigatorStatic {\n\n\n        export interface NavState {\n            routeStack: Route[]\n            idStack: number[]\n            presentedIndex: number\n        }\n\n        export interface NavigationBarStyle {\n            //TODO @see NavigationBarStyle.ios.js\n        }\n\n\n        export interface NavigationBarRouteMapper {\n            Title: ( route: Route, nav: Navigator, index: number, navState: NavState ) => React.ReactElement<any>;\n            LeftButton: ( route: Route, nav: Navigator, index: number, navState: NavState )=> React.ReactElement<any>;\n            RightButton: ( route: Route, nav: Navigator, index: number, navState: NavState )=> React.ReactElement<any>;\n        }\n\n        /**\n         * @see NavigatorNavigationBar.js\n         */\n        export interface NavigationBarProperties extends React.Props<NavigationBarStatic> {\n            navigator?: Navigator\n            routeMapper?: NavigationBarRouteMapper\n            navState?: NavState\n            style?: ViewStyle\n        }\n\n        export interface NavigationBarStatic extends React.ComponentClass<NavigationBarProperties> {\n            Styles: NavigationBarStyle\n\n        }\n\n        export type NavigationBar = NavigationBarStatic\n        export var NavigationBar: NavigationBarStatic\n\n\n        export interface BreadcrumbNavigationBarStyle {\n            //TODO &see NavigatorBreadcrumbNavigationBar.js\n        }\n\n        export interface BreadcrumbNavigationBarRouteMapper {\n            rightContentForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n            titleContentForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n            iconForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n            //in samples...\n            separatorForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n        }\n\n        /**\n         * @see NavigatorNavigationBar.js\n         */\n        export interface BreadcrumbNavigationBarProperties extends React.Props<BreadcrumbNavigationBarStatic> {\n            navigator?: Navigator\n            routeMapper?: BreadcrumbNavigationBarRouteMapper\n            navState?: NavState\n            style?: ViewStyle\n        }\n\n        export interface BreadcrumbNavigationBarStatic extends React.ComponentClass<BreadcrumbNavigationBarProperties> {\n            Styles: BreadcrumbNavigationBarStyle\n        }\n\n        export type BreadcrumbNavigationBar = BreadcrumbNavigationBarStatic\n        var BreadcrumbNavigationBar: BreadcrumbNavigationBarStatic\n\n    }\n\n\n    export interface StyleSheetStatic extends React.ComponentClass<StyleSheetProperties> {\n        create<T>( styles: T ): T;\n    }\n\n    /**\n     * //FIXME: Could not find docs. Inferred from examples and jscode : ListViewDataSource.js\n     */\n    export interface DataSourceAssetCallback {\n        rowHasChanged?: ( r1: any, r2: any ) => boolean\n        sectionHeaderHasChanged?: ( h1: any, h2: any ) => boolean\n        getRowData?: <T>( dataBlob: any, sectionID: number | string, rowID: number | string ) => T\n        getSectionHeaderData?: <T>( dataBlob: any, sectionID: number | string ) => T\n    }\n\n    /**\n     * //FIXME: Could not find docs. Inferred from examples and js code: ListViewDataSource.js\n     */\n    export interface ListViewDataSource {\n        new( onAsset: DataSourceAssetCallback ): ListViewDataSource;\n        /**\n         * Clones this `ListViewDataSource` with the specified `dataBlob` and\n         * `rowIdentities`. The `dataBlob` is just an aribitrary blob of data. At\n         * construction an extractor to get the interesting informatoin was defined\n         * (or the default was used).\n         *\n         * The `rowIdentities` is is a 2D array of identifiers for rows.\n         * ie. [['a1', 'a2'], ['b1', 'b2', 'b3'], ...].  If not provided, it's\n         * assumed that the keys of the section data are the row identities.\n         *\n         * Note: This function does NOT clone the data in this data source. It simply\n         * passes the functions defined at construction to a new data source with\n         * the data specified. If you wish to maintain the existing data you must\n         * handle merging of old and new data separately and then pass that into\n         * this function as the `dataBlob`.\n         */\n        cloneWithRows<T>( dataBlob: Array<any> | {[key: string ]: any}, rowIdentities?: Array<string | number> ): ListViewDataSource\n\n        /**\n         * This performs the same function as the `cloneWithRows` function but here\n         * you also specify what your `sectionIdentities` are. If you don't care\n         * about sections you should safely be able to use `cloneWithRows`.\n         *\n         * `sectionIdentities` is an array of identifiers for  sections.\n         * ie. ['s1', 's2', ...].  If not provided, it's assumed that the\n         * keys of dataBlob are the section identities.\n         *\n         * Note: this returns a new object!\n         */\n        cloneWithRowsAndSections( dataBlob: Array<any> | {[key: string]: any}, sectionIdentities?: Array<string | number>, rowIdentities?: Array<Array<string | number>> ): ListViewDataSource\n\n        getRowCount(): number\n\n        /**\n         * Gets the data required to render the row.\n         */\n        getRowData( sectionIndex: number, rowIndex: number ): any\n\n        /**\n         * Gets the rowID at index provided if the dataSource arrays were flattened,\n         * or null of out of range indexes.\n         */\n        getRowIDForFlatIndex( index: number ): string\n\n        /**\n         * Gets the sectionID at index provided if the dataSource arrays were flattened,\n         * or null for out of range indexes.\n         */\n        getSectionIDForFlatIndex( index: number ): string\n\n        /**\n         * Returns an array containing the number of rows in each section\n         */\n        getSectionLengths(): Array<number>\n\n        /**\n         * Returns if the section header is dirtied and needs to be rerendered\n         */\n        sectionHeaderShouldUpdate( sectionIndex: number ): boolean\n\n        /**\n         * Gets the data required to render the section header\n         */\n        getSectionHeaderData( sectionIndex: number ): any\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/tabbarios-item.html#props\n     */\n    export interface TabBarItemProperties extends React.Props<TabBarItemStatic> {\n\n        /**\n         * Little red bubble that sits at the top right of the icon.\n         */\n        badge?:  string | number\n\n        /**\n         * A custom icon for the tab. It is ignored when a system icon is defined.\n         */\n        icon?: {uri: string} | string\n\n        /**\n         * Callback when this tab is being selected,\n         * you should change the state of your component to set selected={true}.\n         */\n        onPress?: () => void\n\n        /**\n         * It specifies whether the children are visible or not. If you see a blank content, you probably forgot to add a selected one.\n         */\n        selected?: boolean\n\n        /**\n         * A custom icon when the tab is selected.\n         * It is ignored when a system icon is defined. If left empty, the icon will be tinted in blue.\n         */\n        selectedIcon?: {uri: string} | string;\n\n        /**\n         * React style object.\n         */\n        style?: ViewStyle\n\n        /**\n         * Items comes with a few predefined system icons.\n         * Note that if you are using them, the title and selectedIcon will be overridden with the system ones.\n         *\n         *  enum('bookmarks', 'contacts', 'downloads', 'favorites', 'featured', 'history', 'more', 'most-recent', 'most-viewed', 'recents', 'search', 'top-rated')\n         */\n        systemIcon: string\n\n        /**\n         * Text that appears under the icon. It is ignored when a system icon is defined.\n         */\n        title?: string\n\n    }\n\n    export interface TabBarItemStatic extends React.ComponentClass<TabBarItemProperties> {\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/tabbarios.html#props\n     */\n    export interface TabBarIOSProperties extends React.Props<TabBarIOSStatic> {\n\n        /**\n         * Background color of the tab bar\n         */\n        barTintColor?: string\n\n        style?: ViewStyle\n\n        /**\n         * Color of the currently selected tab icon\n         */\n        tintColor?: string\n\n        /**\n         * A Boolean value that indicates whether the tab bar is translucent\n         */\n        translucent?: boolean\n    }\n\n    export interface TabBarIOSStatic extends React.ComponentClass<TabBarIOSProperties> {\n        Item: TabBarItemStatic;\n    }\n\n\n    export interface PixelRatioStatic {\n        get(): number;\n    }\n\n    export interface DeviceEventSubscriptionStatic {\n        remove(): void;\n    }\n\n    export interface DeviceEventEmitterStatic {\n        addListener<T>( type: string, onReceived: ( data: T ) => void ): DeviceEventSubscription;\n    }\n\n    // Used by Dimensions below\n    export interface ScaledSize {\n        width: number;\n        height: number;\n        scale: number;\n    }\n\n\n    export interface InteractionManagerStatic {\n        runAfterInteractions( fn: () => void ): void;\n    }\n\n\n    export interface ScrollViewStyle extends FlexStyle, TransformsStyle {\n\n        backfaceVisibility?:string //enum('visible', 'hidden')\n        backgroundColor?: string\n        borderColor?: string\n        borderTopColor?: string\n        borderRightColor?: string\n        borderBottomColor?: string\n        borderLeftColor?: string\n        borderRadius?: number\n        borderTopLeftRadius?: number\n        borderTopRightRadius?: number\n        borderBottomLeftRadius?: number\n        borderBottomRightRadius?: number\n        borderStyle?: string //enum('solid', 'dotted', 'dashed')\n        borderWidth?: number\n        borderTopWidth?: number\n        borderRightWidth?: number\n        borderBottomWidth?: number\n        borderLeftWidth?: number\n        opacity?: number\n        overflow?: string //enum('visible', 'hidden')\n        shadowColor?: string\n        shadowOffset?: {width: number; height: number}\n        shadowOpacity?: number\n        shadowRadius?: number\n    }\n\n\n    export interface ScrollViewIOSProperties {\n\n        /**\n         * When true the scroll view bounces horizontally when it reaches the end\n         * even if the content is smaller than the scroll view itself. The default\n         * value is true when `horizontal={true}` and false otherwise.\n         */\n        alwaysBounceHorizontal?: boolean\n        /**\n         * When true the scroll view bounces vertically when it reaches the end\n         * even if the content is smaller than the scroll view itself. The default\n         * value is false when `horizontal={true}` and true otherwise.\n         */\n        alwaysBounceVertical?: boolean\n\n        /**\n         * Controls whether iOS should automatically adjust the content inset for scroll views that are placed behind a navigation bar or tab bar/ toolbar.\n         * The default value is true.\n         */\n        automaticallyAdjustContentInsets?: boolean // true\n\n        /**\n         * When true the scroll view bounces when it reaches the end of the\n         * content if the content is larger then the scroll view along the axis of\n         * the scroll direction. When false it disables all bouncing even if\n         * the `alwaysBounce*` props are true. The default value is true.\n         */\n        bounces?: boolean\n        /**\n         * When true gestures can drive zoom past min/max and the zoom will animate\n         * to the min/max value at gesture end otherwise the zoom will not exceed\n         * the limits.\n         */\n        bouncesZoom?: boolean\n\n        /**\n         * When false once tracking starts won't try to drag if the touch moves.\n         * The default value is true.\n         */\n        canCancelContentTouches?: boolean\n\n        /**\n         * When true the scroll view automatically centers the content when the\n         * content is smaller than the scroll view bounds; when the content is\n         * larger than the scroll view this property has no effect. The default\n         * value is false.\n         */\n        centerContent?: boolean\n\n\n        /**\n         * The amount by which the scroll view content is inset from the edges of the scroll view.\n         * Defaults to {0, 0, 0, 0}.\n         */\n        contentInset?: Insets // zeros\n\n        /**\n         * Used to manually set the starting scroll offset.\n         * The default value is {x: 0, y: 0}\n         */\n        contentOffset?: PointProperties // zeros\n\n        /**\n         * A floating-point number that determines how quickly the scroll view\n         * decelerates after the user lifts their finger. Reasonable choices include\n         *   - Normal: 0.998 (the default)\n         *   - Fast: 0.9\n         */\n        decelerationRate?: number\n\n        /**\n         * When true the ScrollView will try to lock to only vertical or horizontal\n         * scrolling while dragging.  The default value is false.\n         */\n        directionalLockEnabled?: boolean\n\n        /**\n         * The maximum allowed zoom scale. The default value is 1.0.\n         */\n        maximumZoomScale?: number\n\n        /**\n         * The minimum allowed zoom scale. The default value is 1.0.\n         */\n        minimumZoomScale?: number\n\n        /**\n         * Called when a scrolling animation ends.\n         */\n        onScrollAnimationEnd?: () => void\n\n        /**\n         * When true the scroll view stops on multiples of the scroll view's size\n         * when scrolling. This can be used for horizontal pagination. The default\n         * value is false.\n         */\n        pagingEnabled?: boolean\n\n        /**\n         * When false, the content does not scroll. The default value is true\n         */\n        scrollEnabled?: boolean // true\n\n        /**\n         * This controls how often the scroll event will be fired while scrolling (in events per seconds).\n         * A higher number yields better accuracy for code that is tracking the scroll position,\n         * but can lead to scroll performance problems due to the volume of information being send over the bridge.\n         * The default value is zero, which means the scroll event will be sent only once each time the view is scrolled.\n         */\n        scrollEventThrottle?: number // null\n\n        /**\n         * The amount by which the scroll view indicators are inset from the edges of the scroll view.\n         * This should normally be set to the same value as the contentInset.\n         * Defaults to {0, 0, 0, 0}.\n         */\n        scrollIndicatorInsets?: Insets //zeroes\n\n        /**\n         * When true the scroll view scrolls to top when the status bar is tapped.\n         * The default value is true.\n         */\n        scrollsToTop?: boolean\n\n        /**\n         * When snapToInterval is set, snapToAlignment will define the relationship of the the snapping to the scroll view.\n         *      - start (the default) will align the snap at the left (horizontal) or top (vertical)\n         *      - center will align the snap in the center\n         *      - end will align the snap at the right (horizontal) or bottom (vertical)\n         */\n        snapToAlignment?: string\n\n        /**\n         * When set, causes the scroll view to stop at multiples of the value of snapToInterval.\n         * This can be used for paginating through children that have lengths smaller than the scroll view.\n         * Used in combination with snapToAlignment.\n         */\n        snapToInterval?: number\n\n        /**\n         * An array of child indices determining which children get docked to the\n         * top of the screen when scrolling. For example passing\n         * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the\n         * top of the scroll view. This property is not supported in conjunction\n         * with `horizontal={true}`.\n         */\n        stickyHeaderIndices?: number[]\n\n        /**\n         * The current scale of the scroll view content. The default value is 1.0.\n         */\n        zoomScale?: number\n    }\n\n    export interface ScrollViewProperties extends ScrollViewIOSProperties, Touchable {\n\n        /**\n         * These styles will be applied to the scroll view content container which\n         * wraps all of the child views. Example:\n         *\n         *   return (\n         *     <ScrollView contentContainerStyle={styles.contentContainer}>\n         *     </ScrollView>\n         *   );\n         *   ...\n         *   var styles = StyleSheet.create({\n         *     contentContainer: {\n         *       paddingVertical: 20\n         *     }\n         *   });\n         */\n        contentContainerStyle?: ViewStyle\n\n        /**\n         * When true the scroll view's children are arranged horizontally in a row\n         * instead of vertically in a column. The default value is false.\n         */\n        horizontal?: boolean\n\n        /**\n         * Determines whether the keyboard gets dismissed in response to a drag.\n         *   - 'none' (the default) drags do not dismiss the keyboard.\n         *   - 'onDrag' the keyboard is dismissed when a drag begins.\n         *   - 'interactive' the keyboard is dismissed interactively with the drag\n         *     and moves in synchrony with the touch; dragging upwards cancels the\n         *     dismissal.\n         */\n        keyboardDismissMode?: string\n\n        /**\n         * When false tapping outside of the focused text input when the keyboard\n         * is up dismisses the keyboard. When true the scroll view will not catch\n         * taps and the keyboard will not dismiss automatically. The default value\n         * is false.\n         */\n        keyboardShouldPersistTaps?: boolean\n\n        /**\n         * Fires at most once per frame during scrolling.\n         * The frequency of the events can be contolled using the scrollEventThrottle prop.\n         */\n        onScroll?: (event?: { nativeEvent: NativeScrollEvent }) => void\n\n        /**\n         * Experimental: When true offscreen child views (whose `overflow` value is\n         * `hidden`) are removed from their native backing superview when offscreen.\n         * This canimprove scrolling performance on long lists. The default value is\n         * false.\n         */\n        removeClippedSubviews?: boolean\n\n        /**\n         * When true, shows a horizontal scroll indicator.\n         */\n        showsHorizontalScrollIndicator?: boolean\n\n        /**\n         * When true, shows a vertical scroll indicator.\n         */\n        showsVerticalScrollIndicator?: boolean\n\n        /**\n         * Style\n         */\n        style?: ScrollViewStyle\n    }\n\n    export interface ScrollViewProps extends ScrollViewProperties, React.Props<ScrollViewStatic> {\n\n    }\n\n    interface ScrollViewStatic extends React.ComponentClass<ScrollViewProps> {\n\n    }\n\n\n    export interface NativeScrollRectangle {\n        left: number;\n        top: number;\n        bottom: number;\n        right: number;\n    }\n\n    export interface NativeScrollPoint {\n        x: number;\n        y: number;\n    }\n\n    export interface NativeScrollSize {\n        height: number;\n        width: number;\n    }\n\n    export interface NativeScrollEvent {\n        contentInset: NativeScrollRectangle;\n        contentOffset: NativeScrollPoint;\n        contentSize: NativeScrollSize;\n        layoutMeasurement: NativeScrollSize;\n        zoomScale: number;\n    }\n\n\n    //////////////////////////////////////////////////////////////////////////\n    //\n    // A P I s\n    //\n    //////////////////////////////////////////////////////////////////////////\n\n    /**\n     * //FIXME: no documentation - inferred from RCTACtionSheetManager.m\n     */\n    export interface ActionSheetIOSOptions {\n        title?: string\n        options?: string[]\n        cancelButtonIndex?: number\n        destructiveButtonIndex?: number\n    }\n\n    /**\n     * //FIXME: no documentation - inferred from RCTACtionSheetManager.m\n     */\n    export interface ShareActionSheetIOSOptions {\n        message?: string\n        url?: string\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/actionsheetios.html#content\n     * //FIXME: no documentation - inferred from RCTACtionSheetManager.m\n     */\n    export interface ActionSheetIOSStatic {\n        showActionSheetWithOptions: ( options: ActionSheetIOSOptions, callback: ( buttonIndex: number ) => void ) => void\n        showShareActionSheetWithOptions: ( options: ShareActionSheetIOSOptions, failureCallback: ( error: Error ) => void, successCallback: ( success: boolean, method: string ) => void ) => void\n    }\n\n\n    /**\n     * //FIXME: No documentation - inferred from RCTAdSupport.m\n     */\n    export interface AdSupportIOSStatic {\n        getAdvertisingId: ( onSuccess: ( deviceId: string ) => void, onFailure: ( err: Error ) => void ) => void\n        getAdvertisingTrackingEnabled: ( onSuccess: ( hasTracking: boolean ) => void, onFailure: ( err: Error ) => void ) => void\n    }\n\n    interface AlertIOSButton {\n        text: string\n        onPress?: () => void\n    }\n\n    /**\n     * Launches an alert dialog with the specified title and message.\n     *\n     * Optionally provide a list of buttons.\n     * Tapping any button will fire the respective onPress callback and dismiss the alert.\n     * By default, the only button will be an 'OK' button\n     *\n     * The last button in the list will be considered the 'Primary' button and it will appear bold.\n     *\n     * @see https://facebook.github.io/react-native/docs/alertios.html#content\n     */\n    export interface AlertIOSStatic {\n        alert: ( title: string, message?: string, buttons?: Array<AlertIOSButton>, type?: string ) => void\n        prompt: ( title: string, value?: string, buttons?: Array<AlertIOSButton>, callback?: ( value?: string ) => void ) => void\n    }\n\n\n    /**\n     * AppStateIOS can tell you if the app is in the foreground or background,\n     * and notify you when the state changes.\n     *\n     * AppStateIOS is frequently used to determine the intent and proper behavior\n     * when handling push notifications.\n     *\n     * iOS App States\n     *      active - The app is running in the foreground\n     *      background - The app is running in the background. The user is either in another app or on the home screen\n     *      inactive - This is a transition state that currently never happens for typical React Native apps.\n     *\n     * For more information, see Apple's documentation: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html\n     *\n     * @see https://facebook.github.io/react-native/docs/appstateios.html#content\n     */\n    export interface AppStateIOSStatic {\n        currentState: string\n        addEventListener( type: string, listener: ( state: string ) => void ): void\n        removeEventListener( type: string, listener: ( state: string ) => void ): void\n    }\n\n    /**\n     * AsyncStorage is a simple, asynchronous, persistent, key-value storage system that is global to the app.\n     * It should be used instead of LocalStorage.\n     *\n     * It is recommended that you use an abstraction on top of AsyncStorage\n     * instead of AsyncStorage directly for anything more than light usage since it operates globally.\n     *\n     * @see https://facebook.github.io/react-native/docs/asyncstorage.html#content\n     */\n    export interface AsyncStorageStatic {\n\n        /**\n         * Fetches key and passes the result to callback, along with an Error if there is any.\n         */\n        getItem( key: string, callback?: ( error?: Error, result?: string ) => void ): Promise<string>\n\n        /**\n         * Sets value for key and calls callback on completion, along with an Error if there is any\n         */\n        setItem( key: string, value: string, callback?: ( error?: Error ) => void ): Promise<string>\n\n        removeItem( key: string, callback?: ( error?: Error ) => void ): Promise<string>\n\n        /**\n         * Merges existing value with input value, assuming they are stringified json. Returns a Promise object.\n         * Not supported by all native implementation\n         */\n        mergeItem( key: string, value: string, callback?: ( error?: Error ) => void ): Promise<string>\n\n        /**\n         * Erases all AsyncStorage for all clients, libraries, etc. You probably don't want to call this.\n         * Use removeItem or multiRemove to clear only your own keys instead.\n         */\n        clear( callback?: ( error?: Error ) => void ): Promise<string>\n\n        /**\n         * Gets all keys known to the app, for all callers, libraries, etc\n         */\n        getAllKeys( callback?: ( error?: Error, keys?: string[] ) => void ): Promise<string>\n\n        /**\n         * multiGet invokes callback with an array of key-value pair arrays that matches the input format of multiSet\n         */\n        multiGet( keys: string[], callback?: ( errors?: Error[], result?: string[][] ) => void ): Promise<string>\n\n        /**\n         * multiSet and multiMerge take arrays of key-value array pairs that match the output of multiGet,\n         *\n         * multiSet([['k1', 'val1'], ['k2', 'val2']], cb);\n         */\n        multiSet( keyValuePairs: string[][], callback?: ( errors?: Error[] ) => void ): Promise<string>\n\n        /**\n         * Delete all the keys in the keys array.\n         */\n        multiRemove( keys: string[], callback?: ( errors?: Error[] ) => void ): Promise<string>\n\n        /**\n         * Merges existing values with input values, assuming they are stringified json.\n         * Returns a Promise object.\n         *\n         * Not supported by all native implementations.\n         */\n        multiMerge( keyValuePairs: string[][], callback?: ( errors?: Error[] ) => void ): Promise<string>\n    }\n\n\n    export interface CameraRollFetchParams {\n        first: number;\n        after?: string;\n        groupTypes: string; //  'Album','All','Event','Faces','Library','PhotoStream','SavedPhotos'\n        groupName?: string\n        assetType?: string\n    }\n\n    export interface CameraRollNodeInfo {\n        image: Image;\n        group_name: string;\n        timestamp: number;\n        location: any;\n    }\n\n    export interface CameraRollEdgeInfo {\n        node: CameraRollNodeInfo;\n    }\n\n    export interface CameraRollAssetInfo {\n        edges: CameraRollEdgeInfo[];\n        page_info: {\n            has_next_page: boolean;\n            end_cursor: string;\n        };\n    }\n\n    /**\n     * CameraRoll provides access to the local camera roll / gallery.\n     */\n    export interface CameraRollStatic {\n\n        GroupTypesOptions: string[] //'Album','All','Event','Faces','Library','PhotoStream','SavedPhotos'\n\n        /**\n         * Saves the image to the camera roll / gallery.\n         *\n         * The CameraRoll API is not yet implemented for Android.\n         *\n         * @tag On Android, this is a local URI, such as \"file:///sdcard/img.png\".\n         * On iOS, the tag can be one of the following:\n         *      local URI\n         *      assets-library tag\n         *      a tag not maching any of the above, which means the image data will be stored in memory (and consume memory as long as the process is alive)\n         *\n         * @param successCallback Invoked with the value of tag on success.\n         * @param errorCallback Invoked with error message on error.\n         */\n        saveImageWithTag( tag: string, successCallback: ( tag?: string ) => void, errorCallback: ( error: Error ) => void ): void\n\n        /**\n         * Invokes callback with photo identifier objects from the local camera roll of the device matching shape defined by getPhotosReturnChecker.\n         *\n         * @param {object} params See getPhotosParamChecker.\n         * @param {function} callback Invoked with arg of shape defined by getPhotosReturnChecker on success.\n         * @param {function} errorCallback Invoked with error message on error.\n         */\n        getPhotos( fetch: CameraRollFetchParams,\n                   callback: ( assetInfo: CameraRollAssetInfo ) => void,\n                   errorCallback: ( error: Error )=> void ): void;\n    }\n\n    export interface FetchableListenable<T> {\n        fetch: () => Promise<T>\n\n        /**\n         * eventName is expected to be `change`\n         * //FIXME: No doc - inferred from NetInfo.js\n         */\n        addEventListener: ( eventName: string, listener: ( result: T ) => void ) => void\n\n        /**\n         * eventName is expected to be `change`\n         * //FIXME: No doc - inferred from NetInfo.js\n         */\n        removeEventListener: ( eventName: string, listener: ( result: T ) => void ) => void\n    }\n\n    /**\n     * NetInfo exposes info about online/offline status\n     *\n     * Asynchronously determine if the device is online and on a cellular network.\n     *\n     * - `none` - device is offline\n     * - `wifi` - device is online and connected via wifi, or is the iOS simulator\n     * - `cell` - device is connected via Edge, 3G, WiMax, or LTE\n     * - `unknown` - error case and the network status is unknown\n\n     * @see https://facebook.github.io/react-native/docs/netinfo.html#content\n     */\n    export interface NetInfoStatic extends FetchableListenable<string> {\n\n        /**\n         *\n         * Available on all platforms.\n         * Asynchronously fetch a boolean to determine internet connectivity.\n         */\n        isConnected: FetchableListenable<boolean>\n\n        //FIXME: Documentation missing\n        isConnectionMetered: any\n    }\n\n\n    export interface PanResponderGestureState {\n\n        /**\n         *  ID of the gestureState- persisted as long as there at least one touch on\n         */\n        stateID: number\n\n        /**\n         *  the latest screen coordinates of the recently-moved touch\n         */\n        moveX: number\n\n        /**\n         *  the latest screen coordinates of the recently-moved touch\n         */\n        moveY: number\n\n        /**\n         * the screen coordinates of the responder grant\n         */\n        x0: number\n\n        /**\n         * the screen coordinates of the responder grant\n         */\n        y0: number\n\n        /**\n         * accumulated distance of the gesture since the touch started\n         */\n        dx: number\n\n        /**\n         * accumulated distance of the gesture since the touch started\n         */\n        dy: number\n\n        /**\n         * current velocity of the gesture\n         */\n        vx: number\n\n        /**\n         * current velocity of the gesture\n         */\n        vy: number\n\n        /**\n         * Number of touches currently on screeen\n         */\n        numberActiveTouches: number\n\n\n        // All `gestureState` accounts for timeStamps up until:\n        _accountsForMovesUpTo: number\n    }\n\n\n    /**\n     * @see documentation of GestureResponderHandlers\n     */\n    export interface PanResponderCallbacks {\n        onMoveShouldSetPanResponder?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n        onStartShouldSetPanResponder?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderGrant?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderMove?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderRelease?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderTerminate?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n\n        onMoveShouldSetPanResponderCapture?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n        onStartShouldSetPanResponderCapture?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n        onPanResponderReject?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderStart?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderEnd?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderTerminationRequest?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n    }\n\n    export interface PanResponderInstance {\n        panHandlers: GestureResponderHandlers\n    }\n\n    /**\n     * PanResponder reconciles several touches into a single gesture.\n     * It makes single-touch gestures resilient to extra touches,\n     * and can be used to recognize simple multi-touch gestures.\n     *\n     * It provides a predictable wrapper of the responder handlers provided by the gesture responder system.\n     * For each handler, it provides a new gestureState object alongside the normal event.\n     */\n    export interface PanResponderStatic {\n        /**\n         * @param config Enhanced versions of all of the responder callbacks\n         * that provide not only the typical `ResponderSyntheticEvent`, but also the\n         * `PanResponder` gesture state.  Simply replace the word `Responder` with\n         * `PanResponder` in each of the typical `onResponder*` callbacks. For\n         * example, the `config` object would look like:\n         *\n         *  - `onMoveShouldSetPanResponder: (e, gestureState) => {...}`\n         *  - `onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}`\n         *  - `onStartShouldSetPanResponder: (e, gestureState) => {...}`\n         *  - `onStartShouldSetPanResponderCapture: (e, gestureState) => {...}`\n         *  - `onPanResponderReject: (e, gestureState) => {...}`\n         *  - `onPanResponderGrant: (e, gestureState) => {...}`\n         *  - `onPanResponderStart: (e, gestureState) => {...}`\n         *  - `onPanResponderEnd: (e, gestureState) => {...}`\n         *  - `onPanResponderRelease: (e, gestureState) => {...}`\n         *  - `onPanResponderMove: (e, gestureState) => {...}`\n         *  - `onPanResponderTerminate: (e, gestureState) => {...}`\n         *  - `onPanResponderTerminationRequest: (e, gestureState) => {...}`\n         *\n         *  In general, for events that have capture equivalents, we update the\n         *  gestureState once in the capture phase and can use it in the bubble phase\n         *  as well.\n         *\n         *  Be careful with onStartShould* callbacks. They only reflect updated\n         *  `gestureState` for start/end events that bubble/capture to the Node.\n         *  Once the node is the responder, you can rely on every start/end event\n         *  being processed by the gesture and `gestureState` being updated\n         *  accordingly. (numberActiveTouches) may not be totally accurate unless you\n         *  are the responder.\n         */\n        create( config: PanResponderCallbacks ): PanResponderInstance\n    }\n\n    export interface PushNotificationPermissions {\n        alert?: boolean\n        badge?: boolean\n        sound?: boolean\n    }\n\n    export interface PushNotification {\n\n\n        /**\n         * An alias for `getAlert` to get the notification's main message string\n         */\n        getMessage(): string | Object\n\n        /**\n         * Gets the sound string from the `aps` object\n         */\n        getSound(): string\n\n        /**\n         * Gets the notification's main message from the `aps` object\n         */\n        getAlert(): string | Object\n\n        /**\n         * Gets the badge count number from the `aps` object\n         */\n        getBadgeCount(): number\n\n        /**\n         * Gets the data object on the notif\n         */\n        getData(): Object\n\n    }\n\n\n    /**\n     * Handle push notifications for your app, including permission handling and icon badge number.\n     * @see https://facebook.github.io/react-native/docs/pushnotificationios.html#content\n     *\n     * //FIXME: BGR: The documentation seems completely off compared to the actual js implementation. I could never get the example to run\n     */\n    export interface PushNotificationIOSStatic {\n\n        /**\n         * Sets the badge number for the app icon on the home screen\n         */\n        setApplicationIconBadgeNumber( number: number ): void\n\n        /**\n         * Gets the current badge number for the app icon on the home screen\n         */\n        getApplicationIconBadgeNumber( callback: ( badge: number ) => void ): void\n\n        /**\n         * Attaches a listener to remote notifications while the app is running in the\n         * foreground or the background.\n         *\n         * The handler will get be invoked with an instance of `PushNotificationIOS`\n         *\n         * The type MUST be 'notification'\n         */\n        addEventListener( type: string, handler: ( notification: PushNotification ) => void ):void\n\n        /**\n         * Requests all notification permissions from iOS, prompting the user's\n         * dialog box.\n         */\n        requestPermissions(): void\n\n        /**\n         * See what push permissions are currently enabled. `callback` will be\n         * invoked with a `permissions` object:\n         *\n         *  - `alert` :boolean\n         *  - `badge` :boolean\n         *  - `sound` :boolean\n         */\n        checkPermissions( callback: ( permissions: PushNotificationPermissions ) => void ): void\n\n        /**\n         * Removes the event listener. Do this in `componentWillUnmount` to prevent\n         * memory leaks\n         */\n        removeEventListener( type: string, handler: ( notification: PushNotification ) => void ): void\n\n        /**\n         * An initial notification will be available if the app was cold-launched\n         * from a notification.\n         *\n         * The first caller of `popInitialNotification` will get the initial\n         * notification object, or `null`. Subsequent invocations will return null.\n         */\n        popInitialNotification(): PushNotification\n    }\n\n\n    /**\n     * @enum('default', 'light-content')\n     */\n    export type StatusBarStyle = string\n\n    /**\n     * @enum('none','fade', 'slide')\n     */\n    type StatusBarAnimation = string\n\n\n    /**\n     * //FIXME: No documentation is available (although this is self explanatory)\n     *\n     * @see https://facebook.github.io/react-native/docs/statusbarios.html#content\n     */\n    export interface StatusBarIOSStatic {\n\n        setStyle(style: StatusBarStyle, animated?: boolean): void\n\n        setHidden(hidden: boolean, animation?: StatusBarAnimation): void\n\n        setNetworkActivityIndicatorVisible(visible: boolean): void\n    }\n\n    /**\n     * The Vibration API is exposed at VibrationIOS.vibrate().\n     * On iOS, calling this function will trigger a one second vibration.\n     * The vibration is asynchronous so this method will return immediately.\n     *\n     * There will be no effect on devices that do not support Vibration, eg. the iOS simulator.\n     *\n     * Vibration patterns are currently unsupported.\n     *\n     * @see https://facebook.github.io/react-native/docs/vibrationios.html#content\n     */\n    export interface VibrationIOSStatic {\n        vibrate(): void\n    }\n\n    //////////////////////////////////////////////////////////////////////////\n    //\n    //  R E - E X P O R T S\n    //\n    //////////////////////////////////////////////////////////////////////////\n\n    // export var AppRegistry: AppRegistryStatic;\n\n\n    export var ActivityIndicatorIOS: ActivityIndicatorIOSStatic\n    export type ActivityIndicatorIOS = ActivityIndicatorIOSStatic\n\n    export var DatePickerIOS: DatePickerIOSStatic\n    export type DatePickerIOS = DatePickerIOSStatic\n\n    export var Image: ImageStatic\n    export type Image = ImageStatic\n\n    export var LayoutAnimation: LayoutAnimationStatic\n    export type LayoutAnimation = LayoutAnimationStatic\n\n    export var ListView: ListViewStatic\n    export type ListView = ListViewStatic\n\n    export var MapView: MapViewStatic\n    export type MapView = MapViewStatic\n\n    export var Navigator: NavigatorStatic\n    export type Navigator = NavigatorStatic\n\n    export var NavigatorIOS: NavigatorIOSStatic\n    export type NavigatorIOS = NavigatorIOSStatic\n\n    export var PickerIOS: PickerIOSStatic\n    export type PickerIOS = PickerIOSStatic\n\n    export var SliderIOS: SliderIOSStatic\n    export type SliderIOS = SliderIOSStatic\n\n    export var ScrollView: ScrollViewStatic\n    export type ScrollView = ScrollViewStatic\n\n    export var StyleSheet: StyleSheetStatic\n    export type StyleSheet = StyleSheetStatic\n\n    export var SwitchIOS: SwitchIOSStatic\n    export type SwitchIOS = SwitchIOSStatic\n\n    export var TabBarIOS: TabBarIOSStatic\n    export type TabBarIOS = TabBarIOSStatic\n\n    export var Text: TextStatic\n    export type Text = TextStatic\n\n    export var TextInput: TextInputStatic\n    export type TextInput = TextInputStatic\n\n    export var TouchableHighlight: TouchableHighlightStatic\n    export type TouchableHighlight = TouchableHighlightStatic\n\n    export var TouchableNativeFeedback: TouchableNativeFeedbackStatic\n    export type TouchableNativeFeedback = TouchableNativeFeedbackStatic\n\n    export var TouchableOpacity: TouchableOpacityStatic\n    export type TouchableOpacity = TouchableOpacityStatic\n\n    export var TouchableWithoutFeedback: TouchableWithoutFeedbackStatic\n    export type TouchableWithoutFeedback= TouchableWithoutFeedbackStatic\n\n    export var View: ViewStatic\n    export type View = ViewStatic\n\n    export var WebView: WebViewStatic\n    export type WebView = WebViewStatic\n\n\n    //////////// APIS //////////////\n    export var ActionSheetIOS: ActionSheetIOSStatic\n    export type ActionSheetIOS = ActionSheetIOSStatic\n\n    export var AdSupportIOS: AdSupportIOSStatic\n    export type AdSupportIOS = AdSupportIOSStatic\n\n    export var AlertIOS: AlertIOSStatic\n    export type AlertIOS = AlertIOSStatic\n\n    export var AppStateIOS: AppStateIOSStatic\n    export type AppStateIOS = AppStateIOSStatic\n\n    export var AsyncStorage: AsyncStorageStatic\n    export type AsyncStorage = AsyncStorageStatic\n\n    export var CameraRoll: CameraRollStatic\n    export type CameraRoll = CameraRollStatic\n\n    export var NetInfo: NetInfoStatic\n    export type NetInfo = NetInfoStatic\n\n    export var PanResponder: PanResponderStatic\n    export type PanResponder = PanResponderStatic\n\n    export var PushNotificationIOS: PushNotificationIOSStatic\n    export type PushNotificationIOS = PushNotificationIOSStatic\n\n    export var StatusBarIOS: StatusBarIOSStatic\n    export type StatusBarIOS = StatusBarIOSStatic\n\n    export var VibrationIOS: VibrationIOSStatic\n    export type VibrationIOS = VibrationIOSStatic\n\n\n    //\n    // /TODO: BGR: These are leftovers of the initial port that must be revisited\n    //\n\n    export var SegmentedControlIOS: React.ComponentClass<SegmentedControlIOSProperties>\n\n    export var PixelRatio: PixelRatioStatic\n    export var DeviceEventEmitter: DeviceEventEmitterStatic\n    export var DeviceEventSubscription: DeviceEventSubscriptionStatic\n    export type DeviceEventSubscription = DeviceEventSubscriptionStatic\n    export var InteractionManager: InteractionManagerStatic\n\n    //////////////////////////////////////////////////////////////////////////\n    //\n    // Additional ( and controversial)\n    //\n    //////////////////////////////////////////////////////////////////////////\n\n    export function __spread( target: any, ...sources: any[] ): any;\n\n\n    export interface GlobalStatic {\n\n        /**\n         * Accepts a function as its only argument and calls that function before the next repaint.\n         * It is an essential building block for animations that underlies all of the JavaScript-based animation APIs.\n         * In general, you shouldn't need to call this yourself - the animation API's will manage frame updates for you.\n         * @see https://facebook.github.io/react-native/docs/animations.html#requestanimationframe\n         */\n        requestAnimationFrame( fn: () => void ) : void;\n\n    }\n\n    //\n    // Add-Ons\n    //\n    namespace addons {\n\n        //FIXME: Documentation ?\n        export interface TestModuleStatic {\n\n            verifySnapshot: ( done: ( indicator?: any ) => void ) => void\n            markTestPassed: ( indicator: any ) => void\n            markTestCompleted: () => void\n        }\n\n        export var TestModule: TestModuleStatic\n        export type TestModule = TestModuleStatic\n    }\n\n\n}\n\ndeclare module \"react-native\" {\n\n    import ReactNative = __React\n    export = ReactNative\n}\n\ndeclare var global: __React.GlobalStatic\n\ndeclare function require( name: string ): any\n\n\n//TODO: BGR: this is a left-over from the initial port. Not sure it makes any sense\ndeclare module \"Dimensions\" {\n    import * as React from 'react-native';\n\n    interface Dimensions {\n        get( what: string ): React.ScaledSize;\n    }\n\n    var ExportDimensions: Dimensions;\n    export = ExportDimensions;\n}\n"
  },
  {
    "path": "example/.watchmanconfig",
    "content": "{}"
  },
  {
    "path": "example/README.md",
    "content": "###Example usage react-native-photos-framework\n\nNOTICE: The base of the example code is taken from this repository:\nhttps://github.com/jeanpan/react-native-camera-roll-picker\nIf your looking for a ImagePicker to pair with this library, check it out!\nAnd thanks @jeanpan for letting me borrow your work here.\n"
  },
  {
    "path": "example/album-list.js",
    "content": "import React, { Component } from 'react';\nimport {\n  View,\n  StyleSheet,\n  Text,\n  Image,\n  ListView,\n  TouchableOpacity,\n  Dimensions,\n  TextInput,\n  AlertIOS\n} from 'react-native'\nimport RNPhotosFramework from './react-native-photos-framework';\nimport { Actions } from 'react-native-router-flux';\nimport minusIcon from './images/minus.png';\n//ion-ios-remove-circle\nvar simple_timer = require('simple-timer');\nimport RNFetchBlob from 'react-native-fetch-blob';\n\nexport default class AlbumList extends Component {\n\n  constructor() {\n    super();\n    this.state = {\n      dataSource: new ListView.DataSource({\n        rowHasChanged: (r1, r2) => r1 !== r2 || this.state.rerenderAll\n      }),\n      rerenderAll: true,\n      pendingTitles: []\n    };\n  }\n\n  componentDidMount() {\n    Actions.refresh({\n      renderRightButton: this\n        .renderRightButton\n        .bind(this),\n      renderLeftButton: this\n        .renderLeftButton\n        .bind(this),\n      edit: false\n    });\n  }\n\n  onEditAlbums() {\n    if (this.props.edit) {\n      this\n        .state\n        .albumsFetchResult\n        .albums\n        .forEach(album => album.pendingTitle && album.updateTitle(album.pendingTitle));\n    }\n    Actions.refresh({\n      edit: !this.props.edit\n    });\n  }\n\n  createAlbum(albumName) {\n    RNPhotosFramework.createAlbum(albumName);\n  }\n\n  onAlbumAdd() {\n    AlertIOS.prompt('Create new album', 'Enter album name.', [\n      {\n        text: 'Cancel',\n        onPress: () => console.log('Cancel Pressed'),\n        style: 'cancel'\n      }, {\n        text: 'OK',\n        onPress: this\n          .createAlbum\n          .bind(this)\n      }\n    ], 'plain-text');\n  }\n\n  renderRightButton(props, a) {\n    return (\n      <TouchableOpacity onPress={this\n        .onEditAlbums\n        .bind(this)}>\n        <Text style={styles.changeButton}>Edit</Text>\n      </TouchableOpacity>\n    );\n  }\n\n  renderLeftButton() {\n    return (\n      <TouchableOpacity onPress={this\n        .onAlbumAdd\n        .bind(this)}>\n        <Text style={styles.addButtonPlus}>+</Text>\n      </TouchableOpacity>\n    );\n  }\n\n  componentWillMount() {\n    simple_timer.start('first_album_fetch');\n    RNPhotosFramework\n      .requestAuthorization()\n      .then((status) => {\n        RNPhotosFramework.getAlbumsCommon({\n          assetCount: 'exact',\n          includeMetadata: true,\n          previewAssets: 2,\n          trackInsertsAndDeletes: true,\n          trackChanges: true,\n          assetFetchOptions: {\n            includeHiddenAssets: true,\n          }\n        }, true).then((albumsFetchResult) => {\n\n          albumsFetchResult.onChange((changeDetails, update, unsubscribe) => {\n            if (update) {\n              update((newAlbumFetchResult) => {\n                this.setState({ albumsFetchResult: newAlbumFetchResult });\n                this.albumPropsToListView();\n              });\n            }\n          });\n          simple_timer.stop('first_album_fetch');\n          console.debug('react-native-photos-framework albums request took %s milliseconds.', simple_timer.get('first_album_fetch').delta)\n          this.setState({ albumsFetchResult: albumsFetchResult });\n          this.albumPropsToListView();\n        });\n      });\n\n    var { width } = Dimensions.get('window');\n    const imagesPerRow = 2;\n    const imageMargin = 10;\n    this._imageSize = (width - (imagesPerRow + 1) * imageMargin) / imagesPerRow;\n  }\n\n  renderFinnishEditingButton() {\n    return (\n      <TouchableOpacity onPress={this\n        .onEditAlbums\n        .bind(this)}>\n        <Text style={styles.changeButton}>Done</Text>\n      </TouchableOpacity>\n    );\n  }\n\n  componentWillReceiveProps(nextProps) {\n    if (this.props.edit !== nextProps.edit && nextProps.edit) {\n      Actions.refresh({\n        renderRightButton: this\n          .renderFinnishEditingButton\n          .bind(this)\n      });\n      this.albumPropsToListView();\n    }\n    if (this.props.edit !== nextProps.edit && !nextProps.edit) {\n      Actions.refresh({\n        renderRightButton: this\n          .renderRightButton\n          .bind(this)\n      });\n      this.albumPropsToListView();\n    }\n  }\n\n  chunk(arr, len) {\n    var chunks = [],\n      i = 0,\n      n = arr.length;\n    while (i < n) {\n      chunks.push(arr.slice(i, i += len));\n    }\n    return chunks;\n  }\n\n  albumPropsToListView(props) {\n    if (this.state.albumsFetchResult && this.state.albumsFetchResult.albums) {\n      const rows = this.chunk(this.state.albumsFetchResult.albums, 2);\n      this.setState({\n        dataSource: this\n          .state\n          .dataSource\n          .cloneWithRows(rows, undefined, rows.map((row, index) => (index)))\n      });\n    }\n  }\n\n  onAlbumPress(album) {\n    Actions.cameraRollPicker({ album: album, title: album.title });\n  }\n\n  _renderAlbum(album, index, columnIndex) {\n    const canDeleteAlbum = album.deletePermitted();\n    const canRenameAlbum = album.renamePermitted();\n    const editable = canDeleteAlbum && canRenameAlbum;\n    return (\n      <View\n        key={index.toString() + columnIndex.toString()}\n        style={{\n          opacity: (this.props.edit && !editable)\n            ? 0.3\n            : 1\n        }}>\n        <TouchableOpacity\n          disabled={this.props.edit}\n          style={styles.listColumn}\n          onPress={this\n            .onAlbumPress\n            .bind(this, album)}>\n          {album.previewAsset\n            ? <Image\n              zIndex={0}\n              source={{\n                uri: album.previewAsset.image.uri,\n                width: this._imageSize,\n                height: this._imageSize\n              }}></Image>\n            : <View\n              style={{\n                backgroundColor: '#D6D6D6',\n                width: this._imageSize,\n                height: this._imageSize\n              }}></View>}\n          {editable\n            ? this.renderRemoveIcon(album)\n            : null}\n          {this.renderTextField(editable, album, index, columnIndex)}\n          <Text style={styles.assetCount}>{album.assetCount}</Text>\n        </TouchableOpacity>\n      </View>\n\n    );\n  }\n\n  renderTextField(editable, album, rowIndex, columnIndex) {\n    const value = album.pendingTitle !== undefined\n      ? album.pendingTitle\n      : album.title;\n    if (editable && this.props.edit) {\n      const key = rowIndex.toString() + columnIndex.toString();\n      return (\n        <TextInput\n          onChangeText={(text) => {\n            album.pendingTitle = text;\n            this.forceUpdate();\n          }}\n          style={styles.title}\n          value={value}></TextInput>\n      );\n    }\n    return <Text style={styles.titleText}>{value}</Text>\n  }\n\n  renderRemoveIcon(album) {\n    if (!this.props.edit) {\n      return null;\n    }\n    return (\n      <TouchableOpacity\n        style={styles.removeIconContainer}\n        onPress={() => album.delete()}>\n        <Image source={minusIcon} style={styles.minusIcon}></Image>\n      </TouchableOpacity>\n    );\n  }\n\n  _renderRow(albums, sectionIndex, rowIndex) {\n    return (\n      <View style={styles.listRow}>\n        {albums.map((album, columnIndex) => this._renderAlbum(album, rowIndex, columnIndex))}\n      </View>\n    );\n  }\n\n  render() {\n    return (\n      <View style={styles.container}>\n        <ListView\n          style={{\n            flex: 1\n          }}\n          removeClippedSubviews={true}\n          dataSource={this.state.dataSource}\n          renderRow={this\n            ._renderRow\n            .bind(this)} />\n      </View>\n    );\n  }\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    paddingTop: 20,\n    marginTop: 50\n  },\n  listRow: {\n    flexDirection: 'row',\n    paddingLeft: 5\n  },\n  listColumn: {\n    padding: 5\n  },\n  title: {\n    height: 28,\n    fontSize: 15,\n    paddingLeft: 0\n  },\n  titleText: {\n    paddingVertical: 10,\n    height: 28,\n    lineHeight: 13,\n    fontSize: 15\n  },\n  assetCount: {\n    fontSize: 15,\n    marginTop: -2,\n    color: 'rgb(158, 158, 158)',\n    marginBottom: 5\n  },\n  addButtonPlus: {\n    width: 30,\n    height: 40,\n    top: -10,\n    fontSize: 32,\n    color: 'rgb(0, 113, 255)',\n    backgroundColor: 'transparent'\n  },\n  changeButton: {\n    fontSize: 18,\n    color: 'rgb(0, 113, 255)'\n  },\n  removeIconContainer: {\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    borderRadius: 14,\n    height: 20,\n    width: 23\n  },\n  minusIcon: {\n    width: 25,\n    height: 25\n  }\n})\n"
  },
  {
    "path": "example/android/app/BUCK",
    "content": "import re\n\n# To learn about Buck see [Docs](https://buckbuild.com/).\n# To run your application with Buck:\n# - install Buck\n# - `npm start` - to start the packager\n# - `cd android`\n# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname \"CN=Android Debug,O=Android,C=US\"`\n# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck\n# - `buck install -r android/app` - compile, install and run application\n#\n\nlib_deps = []\nfor jarfile in glob(['libs/*.jar']):\n  name = 'jars__' + re.sub(r'^.*/([^/]+)\\.jar$', r'\\1', jarfile)\n  lib_deps.append(':' + name)\n  prebuilt_jar(\n    name = name,\n    binary_jar = jarfile,\n  )\n\nfor aarfile in glob(['libs/*.aar']):\n  name = 'aars__' + re.sub(r'^.*/([^/]+)\\.aar$', r'\\1', aarfile)\n  lib_deps.append(':' + name)\n  android_prebuilt_aar(\n    name = name,\n    aar = aarfile,\n  )\n\nandroid_library(\n  name = 'all-libs',\n  exported_deps = lib_deps\n)\n\nandroid_library(\n  name = 'app-code',\n  srcs = glob([\n    'src/main/java/**/*.java',\n  ]),\n  deps = [\n    ':all-libs',\n    ':build_config',\n    ':res',\n  ],\n)\n\nandroid_build_config(\n  name = 'build_config',\n  package = 'com.example',\n)\n\nandroid_resource(\n  name = 'res',\n  res = 'src/main/res',\n  package = 'com.example',\n)\n\nandroid_binary(\n  name = 'app',\n  package_type = 'debug',\n  manifest = 'src/main/AndroidManifest.xml',\n  keystore = '//android/keystores:debug',\n  deps = [\n    ':app-code',\n  ],\n)\n"
  },
  {
    "path": "example/android/app/build.gradle",
    "content": "apply plugin: \"com.android.application\"\n\nimport com.android.build.OutputFile\n\n/**\n * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets\n * and bundleReleaseJsAndAssets).\n * These basically call `react-native bundle` with the correct arguments during the Android build\n * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the\n * bundle directly from the development server. Below you can see all the possible configurations\n * and their defaults. If you decide to add a configuration block, make sure to add it before the\n * `apply from: \"../../node_modules/react-native/react.gradle\"` line.\n *\n * project.ext.react = [\n *   // the name of the generated asset file containing your JS bundle\n *   bundleAssetName: \"index.android.bundle\",\n *\n *   // the entry file for bundle generation\n *   entryFile: \"index.android.js\",\n *\n *   // whether to bundle JS and assets in debug mode\n *   bundleInDebug: false,\n *\n *   // whether to bundle JS and assets in release mode\n *   bundleInRelease: true,\n *\n *   // whether to bundle JS and assets in another build variant (if configured).\n *   // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants\n *   // The configuration property can be in the following formats\n *   //         'bundleIn${productFlavor}${buildType}'\n *   //         'bundleIn${buildType}'\n *   // bundleInFreeDebug: true,\n *   // bundleInPaidRelease: true,\n *   // bundleInBeta: true,\n *\n *   // the root of your project, i.e. where \"package.json\" lives\n *   root: \"../../\",\n *\n *   // where to put the JS bundle asset in debug mode\n *   jsBundleDirDebug: \"$buildDir/intermediates/assets/debug\",\n *\n *   // where to put the JS bundle asset in release mode\n *   jsBundleDirRelease: \"$buildDir/intermediates/assets/release\",\n *\n *   // where to put drawable resources / React Native assets, e.g. the ones you use via\n *   // require('./image.png')), in debug mode\n *   resourcesDirDebug: \"$buildDir/intermediates/res/merged/debug\",\n *\n *   // where to put drawable resources / React Native assets, e.g. the ones you use via\n *   // require('./image.png')), in release mode\n *   resourcesDirRelease: \"$buildDir/intermediates/res/merged/release\",\n *\n *   // by default the gradle tasks are skipped if none of the JS files or assets change; this means\n *   // that we don't look at files in android/ or ios/ to determine whether the tasks are up to\n *   // date; if you have any other folders that you want to ignore for performance reasons (gradle\n *   // indexes the entire tree), add them here. Alternatively, if you have JS files in android/\n *   // for example, you might want to remove it from here.\n *   inputExcludes: [\"android/**\", \"ios/**\"],\n *\n *   // override which node gets called and with what additional arguments\n *   nodeExecutableAndArgs: [\"node\"]\n *\n *   // supply additional arguments to the packager\n *   extraPackagerArgs: []\n * ]\n */\n\napply from: \"../../node_modules/react-native/react.gradle\"\n\n/**\n * Set this to true to create two separate APKs instead of one:\n *   - An APK that only works on ARM devices\n *   - An APK that only works on x86 devices\n * The advantage is the size of the APK is reduced by about 4MB.\n * Upload all the APKs to the Play Store and people will download\n * the correct one based on the CPU architecture of their device.\n */\ndef enableSeparateBuildPerCPUArchitecture = false\n\n/**\n * Run Proguard to shrink the Java bytecode in release builds.\n */\ndef enableProguardInReleaseBuilds = false\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"23.0.1\"\n\n    defaultConfig {\n        applicationId \"com.example\"\n        minSdkVersion 16\n        targetSdkVersion 22\n        versionCode 1\n        versionName \"1.0\"\n        ndk {\n            abiFilters \"armeabi-v7a\", \"x86\"\n        }\n    }\n    splits {\n        abi {\n            reset()\n            enable enableSeparateBuildPerCPUArchitecture\n            universalApk false  // If true, also generate a universal APK\n            include \"armeabi-v7a\", \"x86\"\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled enableProguardInReleaseBuilds\n            proguardFiles getDefaultProguardFile(\"proguard-android.txt\"), \"proguard-rules.pro\"\n        }\n    }\n    // applicationVariants are e.g. debug, release\n    applicationVariants.all { variant ->\n        variant.outputs.each { output ->\n            // For each separate APK per architecture, set a unique version code as described here:\n            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits\n            def versionCodes = [\"armeabi-v7a\":1, \"x86\":2]\n            def abi = output.getFilter(OutputFile.ABI)\n            if (abi != null) {  // null for the universal-debug, universal-release variants\n                output.versionCodeOverride =\n                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode\n            }\n        }\n    }\n}\n\ndependencies {\n    compile project(':react-native-fetch-blob')\n    compile project(':react-native-video')\n    compile fileTree(dir: \"libs\", include: [\"*.jar\"])\n    compile \"com.android.support:appcompat-v7:23.0.1\"\n    compile \"com.facebook.react:react-native:+\"  // From node_modules\n}\n\n// Run this once to be able to run the application with BUCK\n// puts all compile dependencies into folder libs for BUCK to use\ntask copyDownloadableDepsToLibs(type: Copy) {\n    from configurations.compile\n    into 'libs'\n}\n"
  },
  {
    "path": "example/android/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Disabling obfuscation is useful if you collect stack traces from production crashes\n# (unless you are using a system that supports de-obfuscate the stack traces).\n-dontobfuscate\n\n# React Native\n\n# Keep our interfaces so they can be used by other ProGuard rules.\n# See http://sourceforge.net/p/proguard/bugs/466/\n-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip\n-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters\n-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip\n\n# Do not strip any method/class that is annotated with @DoNotStrip\n-keep @com.facebook.proguard.annotations.DoNotStrip class *\n-keep @com.facebook.common.internal.DoNotStrip class *\n-keepclassmembers class * {\n    @com.facebook.proguard.annotations.DoNotStrip *;\n    @com.facebook.common.internal.DoNotStrip *;\n}\n\n-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {\n  void set*(***);\n  *** get*();\n}\n\n-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }\n-keep class * extends com.facebook.react.bridge.NativeModule { *; }\n-keepclassmembers,includedescriptorclasses class * { native <methods>; }\n-keepclassmembers class *  { @com.facebook.react.uimanager.UIProp <fields>; }\n-keepclassmembers class *  { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }\n-keepclassmembers class *  { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }\n\n-dontwarn com.facebook.react.**\n\n# okhttp\n\n-keepattributes Signature\n-keepattributes *Annotation*\n-keep class okhttp3.** { *; }\n-keep interface okhttp3.** { *; }\n-dontwarn okhttp3.**\n\n# okio\n\n-keep class sun.misc.Unsafe { *; }\n-dontwarn java.nio.file.*\n-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement\n-dontwarn okio.**\n"
  },
  {
    "path": "example/android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.example\"\n    android:versionCode=\"1\"\n    android:versionName=\"1.0\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>\n\n    <uses-sdk\n        android:minSdkVersion=\"16\"\n        android:targetSdkVersion=\"22\" />\n\n    <application\n      android:name=\".MainApplication\"\n      android:allowBackup=\"true\"\n      android:label=\"@string/app_name\"\n      android:icon=\"@mipmap/ic_launcher\"\n      android:theme=\"@style/AppTheme\">\n      <activity\n        android:name=\".MainActivity\"\n        android:label=\"@string/app_name\"\n        android:configChanges=\"keyboard|keyboardHidden|orientation|screenSize\">\n        <intent-filter>\n            <action android:name=\"android.intent.action.MAIN\" />\n            <category android:name=\"android.intent.category.LAUNCHER\" />\n        </intent-filter>\n      </activity>\n      <activity android:name=\"com.facebook.react.devsupport.DevSettingsActivity\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "example/android/app/src/main/java/com/example/MainActivity.java",
    "content": "package com.example;\n\nimport com.facebook.react.ReactActivity;\n\npublic class MainActivity extends ReactActivity {\n\n    /**\n     * Returns the name of the main component registered from JavaScript.\n     * This is used to schedule rendering of the component.\n     */\n    @Override\n    protected String getMainComponentName() {\n        return \"Example\";\n    }\n}\n"
  },
  {
    "path": "example/android/app/src/main/java/com/example/MainApplication.java",
    "content": "package com.example;\n\nimport android.app.Application;\nimport android.util.Log;\n\nimport com.facebook.react.ReactApplication;\nimport com.RNFetchBlob.RNFetchBlobPackage;\nimport com.brentvatne.react.ReactVideoPackage;\nimport com.facebook.react.ReactInstanceManager;\nimport com.facebook.react.ReactNativeHost;\nimport com.facebook.react.ReactPackage;\nimport com.facebook.react.shell.MainReactPackage;\nimport com.facebook.soloader.SoLoader;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class MainApplication extends Application implements ReactApplication {\n\n  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {\n    @Override\n    protected boolean getUseDeveloperSupport() {\n      return BuildConfig.DEBUG;\n    }\n\n    @Override\n    protected List<ReactPackage> getPackages() {\n      return Arrays.<ReactPackage>asList(\n          new MainReactPackage(),\n            new RNFetchBlobPackage(),\n            new ReactVideoPackage()\n      );\n    }\n  };\n\n  @Override\n  public ReactNativeHost getReactNativeHost() {\n    return mReactNativeHost;\n  }\n\n  @Override\n  public void onCreate() {\n    super.onCreate();\n    SoLoader.init(this, /* native exopackage */ false);\n  }\n}\n"
  },
  {
    "path": "example/android/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Example</string>\n</resources>\n"
  },
  {
    "path": "example/android/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "example/android/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:1.3.1'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        mavenLocal()\n        jcenter()\n        maven {\n            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm\n            url \"$rootDir/../node_modules/react-native/android\"\n        }\n    }\n}\n"
  },
  {
    "path": "example/android/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.4-all.zip\n"
  },
  {
    "path": "example/android/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n\nandroid.useDeprecatedNdk=true\n"
  },
  {
    "path": "example/android/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "example/android/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "example/android/keystores/BUCK",
    "content": "keystore(\n  name = 'debug',\n  store = 'debug.keystore',\n  properties = 'debug.keystore.properties',\n  visibility = [\n    'PUBLIC',\n  ],\n)\n"
  },
  {
    "path": "example/android/keystores/debug.keystore.properties",
    "content": "key.store=debug.keystore\nkey.alias=androiddebugkey\nkey.store.password=android\nkey.alias.password=android\n"
  },
  {
    "path": "example/android/settings.gradle",
    "content": "rootProject.name = 'Example'\ninclude ':react-native-fetch-blob'\nproject(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android')\ninclude ':react-native-video'\nproject(':react-native-video').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-video/android')\n\ninclude ':app'\n"
  },
  {
    "path": "example/index.android.js",
    "content": "/**\n * Sample React Native App\n * https://github.com/facebook/react-native\n * @flow\n */\n\nimport React, { Component } from 'react';\nimport {\n  AppRegistry,\n  StyleSheet,\n  Text,\n  View\n} from 'react-native';\n\nexport default class Example extends Component {\n  render() {\n    return (\n      <View style={styles.container}>\n        <Text style={styles.welcome}>\n          Welcome to React Native!\n        </Text>\n        <Text style={styles.instructions}>\n          To get started, edit index.android.js\n        </Text>\n        <Text style={styles.instructions}>\n          Double tap R on your keyboard to reload,{'\\n'}\n          Shake or press menu button for dev menu\n        </Text>\n      </View>\n    );\n  }\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    justifyContent: 'center',\n    alignItems: 'center',\n    backgroundColor: '#F5FCFF',\n  },\n  welcome: {\n    fontSize: 20,\n    textAlign: 'center',\n    margin: 10,\n  },\n  instructions: {\n    textAlign: 'center',\n    color: '#333333',\n    marginBottom: 5,\n  },\n});\n\nAppRegistry.registerComponent('Example', () => Example);\n"
  },
  {
    "path": "example/index.ios-ajax.js",
    "content": "/**\n * Sample React Native App\n * https://github.com/facebook/react-native\n * @flow\n */\n\nimport React, { Component } from 'react';\nimport { AppRegistry, StyleSheet, Text, View, Image } from 'react-native';\nimport RNPhotosFramework from './react-native-photos-framework';\nimport {postAsset, postAssets} from './react-native-photos-framework/src/ajax-helper';\n\nexport default class Example extends Component {\n\n    constructor() {\n        super();\n        this.state = {\n            images: []\n        };\n    }\n\n    componentDidMount() {\n        RNPhotosFramework.requestAuthorization().then((statusObj) => {\n            if (statusObj.isAuthorized) {\n                RNPhotosFramework.getAlbums({\n                    type: 'smartAlbum',\n                    subType: 'smartAlbumUserLibrary',\n                    assetCount: 'exact',\n                    fetchOptions: {\n                        sortDescriptors: [\n                            {\n                                key: 'title',\n                                ascending: true\n                            }\n                        ],\n                        includeHiddenAssets: false,\n                        includeAllBurstAssets: false\n                    },\n                    //When you say 'trackInsertsAndDeletes or trackChanges' for an albums query result,\n                    //They will be cached and tracking will start.\n                    //Call queryResult.stopTracking() to stop this. ex. on componentDidUnmount\n                    trackInsertsAndDeletes: true,\n                    trackChanges: false\n\n                }).then((queryResult) => {\n                    const album = queryResult.albums[0];\n                    return album.getAssets({\n                        fetchOptions: {\n                           // mediaTypes: ['video']\n                        },\n                        includeResourcesMetadata : true,\n\n                        //The fetch-options from the outer query will apply here, if we get\n                        startIndex: 0,\n                        endIndex: 10,\n                        //When you say 'trackInsertsAndDeletes or trackAssetsChange' for an albums assets,\n                        //They will be cached and tracking will start.\n                        //Call album.stopTracking() to stop this. ex. on componentDidUnmount\n                        trackInsertsAndDeletes: true,\n                        trackChanges: false\n                    }).then((response) => {\n                       /* response.assets[1].getImageMetadata().then((asset) => {\n                            debugger;\n                        });*/\n                        setTimeout(() => {\n                            const assets = [response.assets[0], response.assets[1]];\n                            postAssets(assets, {\n                                url: 'http://localhost:3000/upload',\n                                headers : {},\n                                onProgress: (progressPercentage, details) => {\n                                    console.log('On Progress called', progressPercentage);\n                                },\n                                onComplete : (asset, status, responseText, xhr) => {\n                                    console.log('Asset upload completed successfully');\n                                },\n                                onError : (asset, status, responseText, xhr) => {\n                                    console.log('Asset upload failed');\n                                },\n                                onFinnished : (completedItems) => {\n                                    console.log('Operation complete');\n                                },\n                                modifyAssetData : (postableAsset, asset) => {\n                                    postableAsset.name = `${postableAsset.name}-special-name-maybe-guid.jpg`;\n                                    return postableAsset;\n                                }\n                            }).then((result) => {\n                                console.log('Operation complete, promise resolved', result);\n                            });\n                        }, 2000);\n\n                        this.setState({\n                            images: [response.assets[0]]\n                        });\n                    });\n                });\n            }\n        });\n    }\n\n    renderImage(asset, index) {\n        return (\n            <Image key={index} source={asset.image} style={{ width: 100, height: 100 }}></Image>\n        );\n    }\n\n    render() {\n        return (\n            <View style={styles.container}>\n                {this.state.images.map(this.renderImage.bind(this))}\n            </View>\n        );\n    }\n}\n\nconst styles = StyleSheet.create({\n    container: {\n        flex: 1,\n        justifyContent: 'center',\n        alignItems: 'center',\n        backgroundColor: '#F5FCFF'\n    },\n    welcome: {\n        fontSize: 20,\n        textAlign: 'center',\n        margin: 10\n    },\n    instructions: {\n        textAlign: 'center',\n        color: '#333333',\n        marginBottom: 5\n    }\n});\n\nAppRegistry.registerComponent('Example', () => Example);"
  },
  {
    "path": "example/index.ios.js",
    "content": "console.debug = console.debug || console.log;\nimport React, { Component } from 'react';\nimport { AppRegistry, StyleSheet, Text, View, TouchableOpacity, AlertIOS } from 'react-native';\nimport AlbumList from './album-list';\nimport { Scene, Router } from 'react-native-router-flux';\nimport CameraRollPicker from './react-native-camera-roll-picker';\nimport { Actions } from 'react-native-router-flux'\n\n\nexport default class Example extends Component {\n\n  constructor() {\n    super();\n    this.state = {\n      albumEditMode: false\n    };\n  }\n\n  render() {\n    return (\n      <Router>\n        <Scene key=\"root\">\n          <Scene\n            key=\"albumList\"\n            component={AlbumList}\n            title=\"Album\" />\n          <Scene key=\"cameraRollPicker\" component={CameraRollPicker} title=\"Bilder\" />\n        </Scene>\n      </Router>\n    );\n  }\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1\n  }\n});\n\nAppRegistry.registerComponent('Example', () => Example);\n"
  },
  {
    "path": "example/ios/Example/AppDelegate.h",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (nonatomic, strong) UIWindow *window;\n\n@end\n"
  },
  {
    "path": "example/ios/Example/AppDelegate.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import \"AppDelegate.h\"\n\n#import <React/RCTBundleURLProvider.h>\n#import <React/RCTRootView.h>\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n  NSURL *jsCodeLocation;\n\n  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\"index.ios\" fallbackResource:nil];\n\n  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation\n                                                      moduleName:@\"Example\"\n                                               initialProperties:nil\n                                                   launchOptions:launchOptions];\n  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];\n\n  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n  UIViewController *rootViewController = [UIViewController new];\n  rootViewController.view = rootView;\n  self.window.rootViewController = rootViewController;\n  [self.window makeKeyAndVisible];\n  return YES;\n}\n\n@end\n"
  },
  {
    "path": "example/ios/Example/Base.lproj/LaunchScreen.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"7702\" systemVersion=\"14D136\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"7701\"/>\n        <capability name=\"Constraints with non-1.0 multipliers\" minToolsVersion=\"5.1\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <view contentMode=\"scaleToFill\" id=\"iN0-l3-epB\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"480\" height=\"480\"/>\n            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n            <subviews>\n                <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Powered by React Native\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"9\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8ie-xW-0ye\">\n                    <rect key=\"frame\" x=\"20\" y=\"439\" width=\"441\" height=\"21\"/>\n                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                    <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                    <nil key=\"highlightedColor\"/>\n                </label>\n                <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Example\" textAlignment=\"center\" lineBreakMode=\"middleTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kId-c2-rCX\">\n                    <rect key=\"frame\" x=\"20\" y=\"140\" width=\"441\" height=\"43\"/>\n                    <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"36\"/>\n                    <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                    <nil key=\"highlightedColor\"/>\n                </label>\n            </subviews>\n            <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n            <constraints>\n                <constraint firstItem=\"kId-c2-rCX\" firstAttribute=\"centerY\" secondItem=\"iN0-l3-epB\" secondAttribute=\"bottom\" multiplier=\"1/3\" constant=\"1\" id=\"5cJ-9S-tgC\"/>\n                <constraint firstAttribute=\"centerX\" secondItem=\"kId-c2-rCX\" secondAttribute=\"centerX\" id=\"Koa-jz-hwk\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"8ie-xW-0ye\" secondAttribute=\"bottom\" constant=\"20\" id=\"Kzo-t9-V3l\"/>\n                <constraint firstItem=\"8ie-xW-0ye\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"MfP-vx-nX0\"/>\n                <constraint firstAttribute=\"centerX\" secondItem=\"8ie-xW-0ye\" secondAttribute=\"centerX\" id=\"ZEH-qu-HZ9\"/>\n                <constraint firstItem=\"kId-c2-rCX\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"fvb-Df-36g\"/>\n            </constraints>\n            <nil key=\"simulatedStatusBarMetrics\"/>\n            <freeformSimulatedSizeMetrics key=\"simulatedDestinationMetrics\"/>\n            <point key=\"canvasLocation\" x=\"548\" y=\"455\"/>\n        </view>\n    </objects>\n</document>\n"
  },
  {
    "path": "example/ios/Example/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "example/ios/Example/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n  <dict>\n    <key>CFBundleDevelopmentRegion</key>\n    <string>en</string>\n    <key>CFBundleExecutable</key>\n    <string>$(EXECUTABLE_NAME)</string>\n    <key>CFBundleIdentifier</key>\n    <string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>\n    <key>CFBundleInfoDictionaryVersion</key>\n    <string>6.0</string>\n    <key>CFBundleName</key>\n    <string>$(PRODUCT_NAME)</string>\n    <key>CFBundlePackageType</key>\n    <string>APPL</string>\n    <key>CFBundleShortVersionString</key>\n    <string>1.0</string>\n    <key>CFBundleSignature</key>\n    <string>????</string>\n    <key>CFBundleVersion</key>\n    <string>1</string>\n    <key>LSRequiresIPhoneOS</key>\n    <true/>\n    <key>UILaunchStoryboardName</key>\n    <string>LaunchScreen</string>\n    <key>UIRequiredDeviceCapabilities</key>\n    <array>\n      <string>armv7</string>\n    </array>\n    <key>UISupportedInterfaceOrientations</key>\n    <array>\n      <string>UIInterfaceOrientationPortrait</string>\n      <string>UIInterfaceOrientationLandscapeLeft</string>\n      <string>UIInterfaceOrientationLandscapeRight</string>\n    </array>\n    <key>UIViewControllerBasedStatusBarAppearance</key>\n    <false/>\n    <key>NSLocationWhenInUseUsageDescription</key>\n    <string/>\n    <key>NSPhotoLibraryUsageDescription</key>\n    <string>Using photo library to select pictures</string>\n    <key>NSAppTransportSecurity</key>\n    <dict>\n      <key>NSExceptionDomains</key>\n      <dict>\n        <key>yt-dash-mse-test.commondatastorage.googleapis.com</key>\n        <dict>\n          <key>NSExceptionAllowsInsecureHTTPLoads</key>\n          <true/>\n        </dict>\n        <key>localhost</key>\n        <dict>\n          <key>NSExceptionAllowsInsecureHTTPLoads</key>\n          <true/>\n        </dict>\n      </dict>\n    </dict>\n  </dict>\n</plist>"
  },
  {
    "path": "example/ios/Example/main.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import <UIKit/UIKit.h>\n\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n  @autoreleasepool {\n    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n  }\n}\n"
  },
  {
    "path": "example/ios/Example.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };\n\t\t00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };\n\t\t00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };\n\t\t00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };\n\t\t00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };\n\t\t00E356F31AD99517003FC87E /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ExampleTests.m */; };\n\t\t133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };\n\t\t139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };\n\t\t139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };\n\t\t13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };\n\t\t13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };\n\t\t13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };\n\t\t13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };\n\t\t140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };\n\t\t146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };\n\t\t1739D1AC585B4622A7327DAA /* libRNFetchBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C5D3A9DB79C744EF8D211E4D /* libRNFetchBlob.a */; };\n\t\t5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };\n\t\t832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };\n\t\t8C2A0F441E22AF3300E31596 /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C2A0F431E22AF1F00E31596 /* libRCTVideo.a */; };\n\t\t8C2A0F4E1E23E00500E31596 /* test-video2.MOV in Resources */ = {isa = PBXBuildFile; fileRef = 8C2A0F4D1E23E00500E31596 /* test-video2.MOV */; };\n\t\t8C34207D1E22A32E00EFB5C5 /* test-video.MOV in Resources */ = {isa = PBXBuildFile; fileRef = 8C34207C1E22A32E00EFB5C5 /* test-video.MOV */; };\n\t\t8C9E84A51E1E7609006F00CA /* testimage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 8C9E84A31E1E7609006F00CA /* testimage.jpg */; };\n\t\t8C9E84A61E1E7609006F00CA /* testimage2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 8C9E84A41E1E7609006F00CA /* testimage2.jpg */; };\n\t\t8CEAA5861E1D7D5800AD097D /* libRNPhotosFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8CEAA5831E1D7D4700AD097D /* libRNPhotosFramework.a */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTActionSheet;\n\t\t};\n\t\t00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTGeolocation;\n\t\t};\n\t\t00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B5115D1A9E6B3D00147676;\n\t\t\tremoteInfo = RCTImage;\n\t\t};\n\t\t00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B511DB1A9E6C8500147676;\n\t\t\tremoteInfo = RCTNetwork;\n\t\t};\n\t\t00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 832C81801AAF6DEF007FA2F7;\n\t\t\tremoteInfo = RCTVibration;\n\t\t};\n\t\t00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 13B07F861A680F5B00A75B9A;\n\t\t\tremoteInfo = Example;\n\t\t};\n\t\t139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTSettings;\n\t\t};\n\t\t139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3C86DF461ADF2C930047B81A;\n\t\t\tremoteInfo = RCTWebSocket;\n\t\t};\n\t\t146834031AC3E56700842450 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;\n\t\t\tremoteInfo = React;\n\t\t};\n\t\t3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A283A1D9B042B00D4039D;\n\t\t\tremoteInfo = \"RCTImage-tvOS\";\n\t\t};\n\t\t3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A28471D9B043800D4039D;\n\t\t\tremoteInfo = \"RCTLinking-tvOS\";\n\t\t};\n\t\t3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A28541D9B044C00D4039D;\n\t\t\tremoteInfo = \"RCTNetwork-tvOS\";\n\t\t};\n\t\t3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A28611D9B046600D4039D;\n\t\t\tremoteInfo = \"RCTSettings-tvOS\";\n\t\t};\n\t\t3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A287B1D9B048500D4039D;\n\t\t\tremoteInfo = \"RCTText-tvOS\";\n\t\t};\n\t\t3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A28881D9B049200D4039D;\n\t\t\tremoteInfo = \"RCTWebSocket-tvOS\";\n\t\t};\n\t\t3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A28131D9B038B00D4039D;\n\t\t\tremoteInfo = \"React-tvOS\";\n\t\t};\n\t\t3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D3C059A1DE3340900C268FA;\n\t\t\tremoteInfo = yoga;\n\t\t};\n\t\t3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D3C06751DE3340C00C268FA;\n\t\t\tremoteInfo = \"yoga-tvOS\";\n\t\t};\n\t\t3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4;\n\t\t\tremoteInfo = cxxreact;\n\t\t};\n\t\t3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4;\n\t\t\tremoteInfo = \"cxxreact-tvOS\";\n\t\t};\n\t\t3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4;\n\t\t\tremoteInfo = jschelpers;\n\t\t};\n\t\t3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D3CD9181DE5FBD800167DC4;\n\t\t\tremoteInfo = \"jschelpers-tvOS\";\n\t\t};\n\t\t5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTAnimation;\n\t\t};\n\t\t5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 2D2A28201D9B03D100D4039D;\n\t\t\tremoteInfo = \"RCTAnimation-tvOS\";\n\t\t};\n\t\t63369B731E959CBA002B65F8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = E01403DDD3CF4C7CB243E5C5 /* RNFetchBlob.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = A15C300E1CD25C330074CB35;\n\t\t\tremoteInfo = RNFetchBlob;\n\t\t};\n\t\t63D83B701F653C63009EF4A6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 139D7ECE1E25DB7D00323FB7;\n\t\t\tremoteInfo = \"third-party\";\n\t\t};\n\t\t63D83B721F653C63009EF4A6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D383D3C1EBD27B6005632C8;\n\t\t\tremoteInfo = \"third-party-tvOS\";\n\t\t};\n\t\t63D83B741F653C63009EF4A6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 139D7E881E25C6D100323FB7;\n\t\t\tremoteInfo = \"double-conversion\";\n\t\t};\n\t\t63D83B761F653C63009EF4A6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3D383D621EBD27B9005632C8;\n\t\t\tremoteInfo = \"double-conversion-tvOS\";\n\t\t};\n\t\t63D83B7F1F655B0A009EF4A6 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B5115D1A9E6B3D00147676;\n\t\t\tremoteInfo = RCTCameraRoll;\n\t\t};\n\t\t78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTLinking;\n\t\t};\n\t\t832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B5119B1A9E6C1200147676;\n\t\t\tremoteInfo = RCTText;\n\t\t};\n\t\t8C2A0F421E22AF1F00E31596 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 8C2A0F3E1E22AF1F00E31596 /* RCTVideo.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTVideo;\n\t\t};\n\t\t8CEAA5821E1D7D4700AD097D /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 8CEAA5641E1D7D4700AD097D /* RNPhotosFramework.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 632F8C131DB758E7007E83E1;\n\t\t\tremoteInfo = RNPhotosFramework;\n\t\t};\n\t\t8CEAA5841E1D7D4700AD097D /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 8CEAA5641E1D7D4700AD097D /* RNPhotosFramework.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 632D5ED01DF19458006A862C;\n\t\t\tremoteInfo = RNPhotosFrameworkTests;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = \"<group>\"; };\n\t\t00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTActionSheet.xcodeproj; path = \"../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTGeolocation.xcodeproj; path = \"../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTImage.xcodeproj; path = \"../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTNetwork.xcodeproj; path = \"../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTVibration.xcodeproj; path = \"../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t00E356EE1AD99517003FC87E /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t00E356F21AD99517003FC87E /* ExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleTests.m; sourceTree = \"<group>\"; };\n\t\t139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTSettings.xcodeproj; path = \"../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTWebSocket.xcodeproj; path = \"../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t13B07F961A680F5B00A75B9A /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Example/AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Example/AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = \"<group>\"; };\n\t\t13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Example/Images.xcassets; sourceTree = \"<group>\"; };\n\t\t13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = \"<group>\"; };\n\t\t13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = \"<group>\"; };\n\t\t146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = React.xcodeproj; path = \"../node_modules/react-native/React/React.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTAnimation.xcodeproj; path = \"../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTCameraRoll.xcodeproj; path = \"../node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTLinking.xcodeproj; path = \"../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTText.xcodeproj; path = \"../node_modules/react-native/Libraries/Text/RCTText.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t8C2A0F3E1E22AF1F00E31596 /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTVideo.xcodeproj; path = \"../node_modules/react-native-video/ios/RCTVideo.xcodeproj\"; sourceTree = \"<group>\"; };\n\t\t8C2A0F4D1E23E00500E31596 /* test-video2.MOV */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = \"test-video2.MOV\"; sourceTree = \"<group>\"; };\n\t\t8C34207C1E22A32E00EFB5C5 /* test-video.MOV */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = \"test-video.MOV\"; sourceTree = \"<group>\"; };\n\t\t8C9E84A31E1E7609006F00CA /* testimage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = testimage.jpg; sourceTree = \"<group>\"; };\n\t\t8C9E84A41E1E7609006F00CA /* testimage2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = testimage2.jpg; sourceTree = \"<group>\"; };\n\t\t8CEAA5641E1D7D4700AD097D /* RNPhotosFramework.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RNPhotosFramework.xcodeproj; path = ../../ios/RNPhotosFramework.xcodeproj; sourceTree = \"<group>\"; };\n\t\tC5D3A9DB79C744EF8D211E4D /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = \"<group>\"; };\n\t\tE01403DDD3CF4C7CB243E5C5 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = \"wrapper.pb-project\"; name = RNFetchBlob.xcodeproj; path = \"../node_modules/react-native-fetch-blob/ios/RNFetchBlob.xcodeproj\"; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t00E356EB1AD99517003FC87E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F8C1A680F5B00A75B9A /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8C2A0F441E22AF3300E31596 /* libRCTVideo.a in Frameworks */,\n\t\t\t\t8CEAA5861E1D7D5800AD097D /* libRNPhotosFramework.a in Frameworks */,\n\t\t\t\t5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,\n\t\t\t\t146834051AC3E58100842450 /* libReact.a in Frameworks */,\n\t\t\t\t00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,\n\t\t\t\t00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,\n\t\t\t\t00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,\n\t\t\t\t133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,\n\t\t\t\t00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,\n\t\t\t\t139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,\n\t\t\t\t832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,\n\t\t\t\t00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,\n\t\t\t\t139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,\n\t\t\t\t1739D1AC585B4622A7327DAA /* libRNFetchBlob.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t00C302A81ABCB8CE00DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302B61ABCB90400DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302BC1ABCB91800DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,\n\t\t\t\t3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302D41ABCB9D200DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,\n\t\t\t\t3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302E01ABCB9EE00DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00E356EF1AD99517003FC87E /* ExampleTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00E356F21AD99517003FC87E /* ExampleTests.m */,\n\t\t\t\t00E356F01AD99517003FC87E /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = ExampleTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00E356F01AD99517003FC87E /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00E356F11AD99517003FC87E /* Info.plist */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t139105B71AF99BAD00B5F7CC /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,\n\t\t\t\t3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t139FDEE71B06529A00C62182 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,\n\t\t\t\t3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t13B07FAE1A68108700A75B9A /* Example */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t008F07F21AC5B25A0029DE68 /* main.jsbundle */,\n\t\t\t\t13B07FAF1A68108700A75B9A /* AppDelegate.h */,\n\t\t\t\t13B07FB01A68108700A75B9A /* AppDelegate.m */,\n\t\t\t\t13B07FB51A68108700A75B9A /* Images.xcassets */,\n\t\t\t\t13B07FB61A68108700A75B9A /* Info.plist */,\n\t\t\t\t13B07FB11A68108700A75B9A /* LaunchScreen.xib */,\n\t\t\t\t13B07FB71A68108700A75B9A /* main.m */,\n\t\t\t);\n\t\t\tname = Example;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t146834001AC3E56700842450 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t146834041AC3E56700842450 /* libReact.a */,\n\t\t\t\t3DAD3EA31DF850E9000B6D8A /* libReact.a */,\n\t\t\t\t3DAD3EA51DF850E9000B6D8A /* libyoga.a */,\n\t\t\t\t3DAD3EA71DF850E9000B6D8A /* libyoga.a */,\n\t\t\t\t3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */,\n\t\t\t\t3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */,\n\t\t\t\t3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */,\n\t\t\t\t3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */,\n\t\t\t\t63D83B711F653C63009EF4A6 /* libthird-party.a */,\n\t\t\t\t63D83B731F653C63009EF4A6 /* libthird-party.a */,\n\t\t\t\t63D83B751F653C63009EF4A6 /* libdouble-conversion.a */,\n\t\t\t\t63D83B771F653C63009EF4A6 /* libdouble-conversion.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t5E91572E1DD0AC6500FF2AA8 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */,\n\t\t\t\t5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t63369B561E959CBA002B65F8 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t63369B741E959CBA002B65F8 /* libRNFetchBlob.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t63D83B7C1F655B0A009EF4A6 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t63D83B801F655B0A009EF4A6 /* libRCTCameraRoll.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t78C398B11ACF4ADC00677621 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t78C398B91ACF4ADC00677621 /* libRCTLinking.a */,\n\t\t\t\t3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t832341AE1AAA6A7D00B99B32 /* Libraries */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */,\n\t\t\t\t8C2A0F3E1E22AF1F00E31596 /* RCTVideo.xcodeproj */,\n\t\t\t\t8CEAA5641E1D7D4700AD097D /* RNPhotosFramework.xcodeproj */,\n\t\t\t\t5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */,\n\t\t\t\t146833FF1AC3E56700842450 /* React.xcodeproj */,\n\t\t\t\t00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,\n\t\t\t\t00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,\n\t\t\t\t00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,\n\t\t\t\t78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,\n\t\t\t\t00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,\n\t\t\t\t139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,\n\t\t\t\t832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,\n\t\t\t\t00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,\n\t\t\t\t139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,\n\t\t\t\tE01403DDD3CF4C7CB243E5C5 /* RNFetchBlob.xcodeproj */,\n\t\t\t);\n\t\t\tname = Libraries;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t832341B11AAA6A8300B99B32 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t832341B51AAA6A8300B99B32 /* libRCTText.a */,\n\t\t\t\t3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t83CBB9F61A601CBA00E9B192 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8C34207C1E22A32E00EFB5C5 /* test-video.MOV */,\n\t\t\t\t8C2A0F4D1E23E00500E31596 /* test-video2.MOV */,\n\t\t\t\t8C9E84A31E1E7609006F00CA /* testimage.jpg */,\n\t\t\t\t8C9E84A41E1E7609006F00CA /* testimage2.jpg */,\n\t\t\t\t13B07FAE1A68108700A75B9A /* Example */,\n\t\t\t\t832341AE1AAA6A7D00B99B32 /* Libraries */,\n\t\t\t\t00E356EF1AD99517003FC87E /* ExampleTests */,\n\t\t\t\t83CBBA001A601CBA00E9B192 /* Products */,\n\t\t\t);\n\t\t\tindentWidth = 2;\n\t\t\tsourceTree = \"<group>\";\n\t\t\ttabWidth = 2;\n\t\t};\n\t\t83CBBA001A601CBA00E9B192 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07F961A680F5B00A75B9A /* Example.app */,\n\t\t\t\t00E356EE1AD99517003FC87E /* ExampleTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t8C2A0F3F1E22AF1F00E31596 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8C2A0F431E22AF1F00E31596 /* libRCTVideo.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t8CEAA5651E1D7D4700AD097D /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8CEAA5831E1D7D4700AD097D /* libRNPhotosFramework.a */,\n\t\t\t\t8CEAA5851E1D7D4700AD097D /* RNPhotosFrameworkTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t00E356ED1AD99517003FC87E /* ExampleTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget \"ExampleTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t00E356EA1AD99517003FC87E /* Sources */,\n\t\t\t\t00E356EB1AD99517003FC87E /* Frameworks */,\n\t\t\t\t00E356EC1AD99517003FC87E /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t00E356F51AD99517003FC87E /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = ExampleTests;\n\t\t\tproductName = ExampleTests;\n\t\t\tproductReference = 00E356EE1AD99517003FC87E /* ExampleTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t13B07F861A680F5B00A75B9A /* Example */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget \"Example\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t13B07F871A680F5B00A75B9A /* Sources */,\n\t\t\t\t13B07F8C1A680F5B00A75B9A /* Frameworks */,\n\t\t\t\t13B07F8E1A680F5B00A75B9A /* Resources */,\n\t\t\t\t00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Example;\n\t\t\tproductName = \"Hello World\";\n\t\t\tproductReference = 13B07F961A680F5B00A75B9A /* Example.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t83CBB9F71A601CBA00E9B192 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 610;\n\t\t\t\tORGANIZATIONNAME = Facebook;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t00E356ED1AD99517003FC87E = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.2;\n\t\t\t\t\t\tDevelopmentTeam = 5BEG6QJ94B;\n\t\t\t\t\t\tTestTargetID = 13B07F861A680F5B00A75B9A;\n\t\t\t\t\t};\n\t\t\t\t\t13B07F861A680F5B00A75B9A = {\n\t\t\t\t\t\tDevelopmentTeam = 5BEG6QJ94B;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject \"Example\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 83CBB9F61A601CBA00E9B192;\n\t\t\tproductRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */;\n\t\t\t\t\tProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 63D83B7C1F655B0A009EF4A6 /* Products */;\n\t\t\t\t\tProjectRef = 63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 78C398B11ACF4ADC00677621 /* Products */;\n\t\t\t\t\tProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;\n\t\t\t\t\tProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 832341B11AAA6A8300B99B32 /* Products */;\n\t\t\t\t\tProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 8C2A0F3F1E22AF1F00E31596 /* Products */;\n\t\t\t\t\tProjectRef = 8C2A0F3E1E22AF1F00E31596 /* RCTVideo.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 139FDEE71B06529A00C62182 /* Products */;\n\t\t\t\t\tProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 146834001AC3E56700842450 /* Products */;\n\t\t\t\t\tProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 63369B561E959CBA002B65F8 /* Products */;\n\t\t\t\t\tProjectRef = E01403DDD3CF4C7CB243E5C5 /* RNFetchBlob.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 8CEAA5651E1D7D4700AD097D /* Products */;\n\t\t\t\t\tProjectRef = 8CEAA5641E1D7D4700AD097D /* RNPhotosFramework.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t13B07F861A680F5B00A75B9A /* Example */,\n\t\t\t\t00E356ED1AD99517003FC87E /* ExampleTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXReferenceProxy section */\n\t\t00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTActionSheet.a;\n\t\t\tremoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTGeolocation.a;\n\t\t\tremoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTImage.a;\n\t\t\tremoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTNetwork.a;\n\t\t\tremoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTVibration.a;\n\t\t\tremoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTSettings.a;\n\t\t\tremoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTWebSocket.a;\n\t\t\tremoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t146834041AC3E56700842450 /* libReact.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libReact.a;\n\t\t\tremoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libRCTImage-tvOS.a\";\n\t\t\tremoteRef = 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libRCTLinking-tvOS.a\";\n\t\t\tremoteRef = 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libRCTNetwork-tvOS.a\";\n\t\t\tremoteRef = 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libRCTSettings-tvOS.a\";\n\t\t\tremoteRef = 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libRCTText-tvOS.a\";\n\t\t\tremoteRef = 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libRCTWebSocket-tvOS.a\";\n\t\t\tremoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EA31DF850E9000B6D8A /* libReact.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libReact.a;\n\t\t\tremoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libyoga.a;\n\t\t\tremoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libyoga.a;\n\t\t\tremoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libcxxreact.a;\n\t\t\tremoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libcxxreact.a;\n\t\t\tremoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libjschelpers.a;\n\t\t\tremoteRef = 3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libjschelpers.a;\n\t\t\tremoteRef = 3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTAnimation.a;\n\t\t\tremoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTAnimation.a;\n\t\t\tremoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t63369B741E959CBA002B65F8 /* libRNFetchBlob.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRNFetchBlob.a;\n\t\t\tremoteRef = 63369B731E959CBA002B65F8 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t63D83B711F653C63009EF4A6 /* libthird-party.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libthird-party.a\";\n\t\t\tremoteRef = 63D83B701F653C63009EF4A6 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t63D83B731F653C63009EF4A6 /* libthird-party.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libthird-party.a\";\n\t\t\tremoteRef = 63D83B721F653C63009EF4A6 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t63D83B751F653C63009EF4A6 /* libdouble-conversion.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libdouble-conversion.a\";\n\t\t\tremoteRef = 63D83B741F653C63009EF4A6 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t63D83B771F653C63009EF4A6 /* libdouble-conversion.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = \"libdouble-conversion.a\";\n\t\t\tremoteRef = 63D83B761F653C63009EF4A6 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t63D83B801F655B0A009EF4A6 /* libRCTCameraRoll.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTCameraRoll.a;\n\t\t\tremoteRef = 63D83B7F1F655B0A009EF4A6 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTLinking.a;\n\t\t\tremoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t832341B51AAA6A8300B99B32 /* libRCTText.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTText.a;\n\t\t\tremoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t8C2A0F431E22AF1F00E31596 /* libRCTVideo.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTVideo.a;\n\t\t\tremoteRef = 8C2A0F421E22AF1F00E31596 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t8CEAA5831E1D7D4700AD097D /* libRNPhotosFramework.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRNPhotosFramework.a;\n\t\t\tremoteRef = 8CEAA5821E1D7D4700AD097D /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t8CEAA5851E1D7D4700AD097D /* RNPhotosFrameworkTests.xctest */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.cfbundle;\n\t\t\tpath = RNPhotosFrameworkTests.xctest;\n\t\t\tremoteRef = 8CEAA5841E1D7D4700AD097D /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n/* End PBXReferenceProxy section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t00E356EC1AD99517003FC87E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F8E1A680F5B00A75B9A /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,\n\t\t\t\t8C2A0F4E1E23E00500E31596 /* test-video2.MOV in Resources */,\n\t\t\t\t13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,\n\t\t\t\t8C9E84A61E1E7609006F00CA /* testimage2.jpg in Resources */,\n\t\t\t\t8C9E84A51E1E7609006F00CA /* testimage.jpg in Resources */,\n\t\t\t\t8C34207D1E22A32E00EFB5C5 /* test-video.MOV in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Bundle React Native code and images\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"export NODE_BINARY=node\\n../node_modules/react-native/scripts/react-native-xcode.sh\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t00E356EA1AD99517003FC87E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t00E356F31AD99517003FC87E /* ExampleTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F871A680F5B00A75B9A /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,\n\t\t\t\t13B07FC11A68108700A75B9A /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t00E356F51AD99517003FC87E /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 13B07F861A680F5B00A75B9A /* Example */;\n\t\t\ttargetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07FB21A68108700A75B9A /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.xib;\n\t\t\tpath = Example;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t00E356F61AD99517003FC87E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = ExampleTests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/$(TARGET_NAME)\\\"\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/$(TARGET_NAME)\\\"\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/Example.app/Example\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t00E356F71AD99517003FC87E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tINFOPLIST_FILE = ExampleTests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/$(TARGET_NAME)\\\"\",\n\t\t\t\t\t\"\\\"$(SRCROOT)/$(TARGET_NAME)\\\"\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/Example.app/Example\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t13B07F941A680F5B00A75B9A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEAD_CODE_STRIPPING = NO;\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tINFOPLIST_FILE = Example/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = Example;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t13B07F951A680F5B00A75B9A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tINFOPLIST_FILE = Example/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = Example;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t83CBBA201A601CBA00E9B192 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t83CBBA211A601CBA00E9B192 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget \"ExampleTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t00E356F61AD99517003FC87E /* Debug */,\n\t\t\t\t00E356F71AD99517003FC87E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget \"Example\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t13B07F941A680F5B00A75B9A /* Debug */,\n\t\t\t\t13B07F951A680F5B00A75B9A /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject \"Example\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t83CBBA201A601CBA00E9B192 /* Debug */,\n\t\t\t\t83CBBA211A601CBA00E9B192 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;\n}\n"
  },
  {
    "path": "example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0820\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"NO\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"83CBBA2D1A601D0E00E9B192\"\n               BuildableName = \"libReact.a\"\n               BlueprintName = \"React\"\n               ReferencedContainer = \"container:../node_modules/react-native/React/React.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n               BuildableName = \"Example.app\"\n               BlueprintName = \"Example\"\n               ReferencedContainer = \"container:Example.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"NO\"\n            buildForArchiving = \"NO\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"00E356ED1AD99517003FC87E\"\n               BuildableName = \"ExampleTests.xctest\"\n               BlueprintName = \"ExampleTests\"\n               ReferencedContainer = \"container:Example.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"632D5ECF1DF19458006A862C\"\n               BuildableName = \"RNPhotosFrameworkTests.xctest\"\n               BlueprintName = \"RNPhotosFrameworkTests\"\n               ReferencedContainer = \"container:../../ios/RNPhotosFramework.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"Example.app\"\n            BlueprintName = \"Example\"\n            ReferencedContainer = \"container:Example.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"Example.app\"\n            BlueprintName = \"Example\"\n            ReferencedContainer = \"container:Example.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Debug\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"Example.app\"\n            BlueprintName = \"Example\"\n            ReferencedContainer = \"container:Example.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "example/ios/ExampleTests/ExampleTests.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import <UIKit/UIKit.h>\n#import <XCTest/XCTest.h>\n\n#import <React/RCTLog.h>\n#import <React/RCTRootView.h>\n\n#define TIMEOUT_SECONDS 600\n#define TEXT_TO_LOOK_FOR @\"Welcome to React Native!\"\n\n@interface ExampleTests : XCTestCase\n\n@end\n\n@implementation ExampleTests\n\n- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test\n{\n  if (test(view)) {\n    return YES;\n  }\n  for (UIView *subview in [view subviews]) {\n    if ([self findSubviewInView:subview matching:test]) {\n      return YES;\n    }\n  }\n  return NO;\n}\n\n- (void)testRendersWelcomeScreen\n{\n  UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];\n  NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];\n  BOOL foundElement = NO;\n\n  __block NSString *redboxError = nil;\n  RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {\n    if (level >= RCTLogLevelError) {\n      redboxError = message;\n    }\n  });\n\n  while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {\n    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n    [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n\n    foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {\n      if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {\n        return YES;\n      }\n      return NO;\n    }];\n  }\n\n  RCTSetLogFunction(RCTDefaultLogFunction);\n\n  XCTAssertNil(redboxError, @\"RedBox error: %@\", redboxError);\n  XCTAssertTrue(foundElement, @\"Couldn't find element with text '%@' in %d seconds\", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);\n}\n\n\n@end\n"
  },
  {
    "path": "example/ios/ExampleTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "example/library-test.js",
    "content": "import RNPhotosFramework from 'react-native-photos-framework';\nvar simple_timer = require('simple-timer');\nconst TEST_ALBUM_ONE = 'RNPF-test-1';\nconst TEST_ALBUM_TWO = 'RNPF-test-2';\n\nexport default class LibraryTest {\n\n  addTestImagesToAlbumOne(album) {\n    return RNPhotosFramework.createAssets({\n      album: album,\n      images: [\n        {\n          uri: 'https://c1.staticflickr.com/6/5337/8940995208_5da979c52f.jpg'\n        }, {\n          uri: 'https://upload.wikimedia.org/wikipedia/commons/d/db/Patern_test.jpg'\n        }\n      ]\n    });\n  }\n\n  addTestImagesToAlbumTwo(album) {\n    return RNPhotosFramework.createAssets({\n      album: album,\n      includeMetadata: true,\n      images: [\n        {\n          uri: 'https://c1.staticflickr.com/6/5337/8940995208_5da979c52f.jpg'\n        }, {\n          uri: 'https://upload.wikimedia.org/wikipedia/commons/d/db/Patern_test.jpg'\n        }\n      ]\n    }).then((assets) => {\n      return assets;\n    });\n  }\n\n\n\n  _componentWillMount() {\n    RNPhotosFramework\n      .requestAuthorization()\n      .then((status) => {\n        if (status.isAuthorized) {\n          this\n            .cleanUp()\n            .then(() => {\n              this\n                .readd()\n                .then(() => {});\n            });\n        } else {\n          alert('Application is not authorized to use Photos Framework! Pleade check settings.');\n        }\n      });\n  }\n\n  readd() {\n    return this\n      .testAlbumsExist()\n      .then((albums) => {\n        return Promise.all([\n          this.addTestImagesToAlbumOne(albums[0]),\n          this.addTestImagesToAlbumTwo(albums[1])\n        ]).then((assets) => {}, (li) => {\n          //ProgressCallback\n        }).then(() => {\n          //Complete\n        });\n      });\n  }\n\n  removeAlbums(albums) {\n    return RNPhotosFramework.deleteAlbums(albums);\n  }\n\n  cleanUp() {\n    console.debug('Will search for test-albums');\n    return RNPhotosFramework\n      .getAlbumsByTitles([TEST_ALBUM_ONE, TEST_ALBUM_TWO])\n      .then((fetchResult) => {\n        console.debug(`Found ${fetchResult.albums.length} test albums`);\n        const albums = fetchResult\n          .albums\n          .filter(album => [TEST_ALBUM_ONE, TEST_ALBUM_TWO].some(testAlbum => testAlbum === album.title));\n        const promises = albums.map(album => {\n          console.debug(`Fetching album ${album.title}'s assets`);\n          return album\n            .getAssets()\n            .then((assetResultObj) => {\n              console.debug(`Deleting album ${album.title}'s assets: ${assetResultObj.assets.length} assets`);\n              return RNPhotosFramework.deleteAssets(assetResultObj.assets);\n            });\n        });\n        return Promise\n          .all(promises)\n          .then(() => {\n            console.debug(`Deleting albums ${albums.length}`);\n            return RNPhotosFramework\n              .deleteAlbums(albums)\n              .then((result) => {\n                console.debug('Cleanup comlete');\n                return result;\n              });\n          });\n      });\n  }\n\n  testAlbumsExist() {\n    return RNPhotosFramework\n      .getAlbumsByTitles([TEST_ALBUM_ONE, TEST_ALBUM_TWO])\n      .then((fetchResult) => {\n        const albumsThatDoExit = [TEST_ALBUM_ONE, TEST_ALBUM_TWO].filter(testAlbumTitle => fetchResult.albums.some(album => album.title === testAlbumTitle));\n        const albumsThatDontExit = [TEST_ALBUM_ONE, TEST_ALBUM_TWO].filter(testAlbumTitle => !fetchResult.albums.some(album => album.title === testAlbumTitle));\n        if (albumsThatDontExit.length) {\n          return RNPhotosFramework\n            .createAlbums(albumsThatDontExit)\n            .then((newAlbums) => {\n              return albumsThatDoExit.concat(newAlbums);\n            });\n        }\n        return fetchResult.albums;\n      });\n  }\n}\n"
  },
  {
    "path": "example/package.json",
    "content": "{\n  \"name\": \"Example\",\n  \"version\": \"0.0.1\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"node node_modules/react-native/local-cli/cli.js start\",\n    \"test\": \"jest\",\n    \"link-all\": \"wml add ~/react-native-photos-framework/src ~/react-native-photos-framework/example/react-native-photos-framework/src && wml start\"\n  },\n  \"dependencies\": {\n    \"babel\": \"^6.23.0\",\n    \"babel-plugin-module-alias\": \"^1.6.0\",\n    \"react\": \"16.0.0-alpha.12\",\n    \"react-native\": \"0.48.2\",\n    \"react-native-fetch-blob\": \"^0.10.8\",\n    \"react-native-photos-framework\": \"latest\",\n    \"react-native-router-flux\": \"^4.0.0-beta.21\",\n    \"react-native-video\": \"git://github.com/olofd/react-native-video.git#react-native-photos-framework\",\n    \"simple-timer\": \"0.0.5\"\n  },\n  \"jest\": {\n    \"preset\": \"jest-react-native\"\n  },\n  \"devDependencies\": {\n    \"babel-jest\": \"21.0.2\",\n    \"babel-preset-react-native\": \"3.0.2\",\n    \"jest\": \"21.0.2\",\n    \"jest-react-native\": \"18.0.0\",\n    \"react-test-renderer\": \"15.6.1\"\n  }\n}\n"
  },
  {
    "path": "example/react-native-camera-roll-picker/ImageItem.js",
    "content": "import React, { Component } from 'react';\nimport {\n  Image,\n  StyleSheet,\n  Dimensions,\n  TouchableOpacity,\n  Text,\n  View\n} from 'react-native';\nimport Video from 'react-native-video';\n\nclass ImageItem extends Component {\n  constructor(props) {\n    super(props);\n    this.state = { videoPaused: true };\n  }\n\n  componentWillMount() {\n    var {width} = Dimensions.get('window');\n    var {imageMargin, imagesPerRow, containerWidth} = this.props;\n\n    if (typeof containerWidth != \"undefined\") {\n      width = containerWidth;\n    }\n    this._imageSize = (width - (imagesPerRow + 1) * imageMargin) / imagesPerRow;\n  }\n\n  toogleVideoPlay() {\n    this.setState({\n      videoPaused : !this.state.videoPaused\n    });\n  }\n\n  renderVideo() {\n    if (this.props.item.mediaType !== 'video' || this.state.videoPaused) {\n      return null;\n    }\n    return (\n      <Video source={this.props.item.video}   // Can be a URL or a local file.\n        ref={(ref) => {\n          this.player = ref\n        }}\n        resizeMode='cover'\n        onPlaybackRateChange={() => { } }                             // Store reference\n        rate={1.0}                     // 0 is paused, 1 is normal.\n        volume={1.0}                   // 0 is muted, 1 is normal.\n        muted={false}                  // Mutes the audio entirely.\n        paused={this.state.videoPaused}                 // Pauses playback entirely.\n        repeat={true}                  // Repeat forever.\n        playInBackground={false}       // Audio continues to play when app entering background.\n        playWhenInactive={false}       // [iOS] Video continues to play when control or notification center are shown.\n        progressUpdateInterval={250.0} // [iOS] Interval to fire onProgress (default to ~250ms)\n        style={styles.thumbVideo} />\n    );\n  }\n\n  renderVideoSymbol() {\n    if (this.props.item.mediaType !== 'video') {\n      return null;\n    }\n    return (\n      <TouchableOpacity style={styles.playButtonContainer} onPress={this.toogleVideoPlay.bind(this)}>\n        <Text style={[styles.playButton, !this.state.videoPaused ? styles.paused : styles.playing]}>{!this.state.videoPaused ? '▐▐' : '►'}</Text>\n      </TouchableOpacity>\n    );\n  }\n\n  render() {\n    var {item, selected, selectedMarker, imageMargin} = this.props;\n\n    var marker = selectedMarker ? selectedMarker :\n      <Image\n        style={[styles.marker, { width: 25, height: 25 }]}\n        source={require('./circle-check.png')}\n        />;\n\n    var image = item.image;\n\n    return (\n      <TouchableOpacity\n        style={{ marginBottom: imageMargin, marginRight: imageMargin }}\n        onPress={() => this._handleClick(item)}>\n        <Image\n          source={{ uri: image.uri }}\n          style={{ height: this._imageSize, width: this._imageSize }} >\n        </Image>\n        {this.props.displayDates ? (<View style={styles.dates}><Text style={styles.creationText}>{`Created: ${item.creationDate.toDateString()}`}</Text>\n          <Text style={styles.modificationText}>{`Modified: ${item.modificationDate.toDateString()}`}</Text></View>\n        ) : null}\n        {this.renderVideo()}\n        {this.renderVideoSymbol()}\n        {(selected) ? marker : null}\n      </TouchableOpacity>\n    );\n  }\n\n  _handleClick(item) {\n    this.props.onClick(item);\n  }\n}\n\nconst styles = StyleSheet.create({\n  marker: {\n    position: 'absolute',\n    top: 5,\n    right: 5,\n    backgroundColor: 'transparent',\n  },\n  creationText: {\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    backgroundColor: 'rgba(0, 0, 0, 0.5)',\n    color: 'white',\n    padding: 3,\n    fontSize: 10\n  },\n  modificationText: {\n    position: 'absolute',\n    top: 35,\n    left: 0,\n    backgroundColor: 'rgba(0, 0, 0, 0.5)',\n    color: 'white',\n    padding: 3,\n    fontSize: 10\n  },\n  dates: {\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    right: 0,\n    bottom: 0\n  },\n  playButtonContainer: {\n    position: 'absolute',\n    bottom: 5,\n    right: 5,\n    backgroundColor: 'rgba(0, 0, 0, 0.9)',\n    borderRadius: 15,\n    width: 30,\n    height: 30,\n    alignItems: 'center',\n    justifyContent: 'center',\n    borderWidth: 1,\n    borderColor: 'white'\n  },\n  playButton: {\n    backgroundColor: 'transparent',\n    color: 'white',\n    fontSize: 18,\n    fontFamily: 'Arial',\n    left: 2\n  },\n  paused : {\n    fontSize: 12,\n    left: -2\n  },\n  playing : {\n\n  },\n  thumbVideo: {\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    right: 0,\n    bottom: 0,\n    backgroundColor : 'transparent'\n  }\n})\n\nImageItem.defaultProps = {\n  item: {},\n  selected: false,\n}\n\nImageItem.propTypes = {\n  item: React.PropTypes.object,\n  selected: React.PropTypes.bool,\n  selectedMarker: React.PropTypes.element,\n  imageMargin: React.PropTypes.number,\n  imagesPerRow: React.PropTypes.number,\n  onClick: React.PropTypes.func,\n}\n\nexport default ImageItem;\n"
  },
  {
    "path": "example/react-native-camera-roll-picker/camera-roll-picker.js",
    "content": "import React, { Component } from 'react';\nimport {\n  CameraRoll,\n  Platform,\n  StyleSheet,\n  View,\n  Text,\n  ListView,\n  ActivityIndicator\n} from 'react-native';\nimport ImageItem from './ImageItem';\nimport RNPhotosFramework from '../react-native-photos-framework';\nimport { postAssets } from '../react-native-photos-framework/src/ajax-helper'\nvar simple_timer = require('simple-timer')\nimport RNFetchBlob from 'react-native-fetch-blob';\n\nclass CameraRollPicker extends Component {\n  constructor(props) {\n    super(props);\n\n    this.state = {\n      images: [],\n      selected: this.props.selected,\n      lastCursor: null,\n      loadingMore: false,\n      noMore: false,\n      dataSource: new ListView.DataSource({\n        rowHasChanged: (r1, r2) => r1 !== r2\n      })\n    };\n  }\n\n  componentWillReceiveProps(nextProps) {\n    this.setState({ selected: nextProps.selected });\n    if (nextProps.album !== this.props.album) {\n      this.setState({\n        images: [],\n        loadingMore: false,\n        dataSource: this\n          .state\n          .dataSource\n          .cloneWithRows([])\n      });\n      this._fetch(true, nextProps);\n    }\n  }\n\n  fetch() {\n    if (!this.state.loadingMore) {\n      this.setState({\n        loadingMore: true\n      }, () => {\n        this._fetch();\n      });\n    }\n  }\n\n  componentWillMount() {\n    this.fetch();\n    this.unsubscribe = this\n      .props\n      .album\n      .onChange((changeDetails, update) => {\n        update(this.state.images, (images) => {\n          console.log(images[0]);\n          this.state.images = images;\n          this.state.dataSource = this\n            .state\n            .dataSource\n            .cloneWithRows(this._nEveryRow(this.state.images, this.props.imagesPerRow));\n          this.setState({ images: this.state.images, dataSource: this.state.dataSource });\n        }, {\n            includeMetadata: true\n          });\n\n      });\n  }\n\n  componentWillUnmount() {\n    this\n      .props\n      .album\n      .stopTracking();\n    this.unsubscribe && this.unsubscribe();\n  }\n\n  _fetch(reset, nextProps) {\n    if (this.lm) {\n      return;\n    }\n    this.lm = true;\n    let props = nextProps || this.props;\n    simple_timer.start('fetch_timer');\n    props\n      .album\n      .getAssets({\n        includeMetadata: true,\n        trackInsertsAndDeletes: true,\n        //  trackChanges: true,\n        startIndex: this.state.images.length,\n        endIndex: 0,\n        fetchOptions: {\n          includeHiddenAssets: true\n        },\n      })\n      .then((data) => {\n\n        console.log(RNFetchBlob.fs.dirs);\n        const dirs = RNFetchBlob.fs.dirs\n\n        const imageOptions = {\n          loadOptions: {\n            scale: 1, //defaults to 1\n            deliveryMode: 'highQuality', //defaults to highQuality, avaliable: highQuality, fast, opportunistic(should not be used)\n            version : 'current', //defaults to current, also avaliable: 'original', 'unadjusted'\n            contentMode: 'fill', //default to fill, also avaliable: fit\n            width: 20, //defaults to 0, 0 means original width\n            height: 20, //default to 0, 0 means original height,\n            resizeMode: 'none', //Default to none if width and height is not specified, otherwise defaults fast, avaliable: 'none', 'fast', 'exact'\n            cropRect: '1000|700|500|500' //Rect to crop image to. x,y,width,height (!!Will override properies 'width' and 'height')\n          },\n          postProcessOptions: {\n            quality: 10,  //0 means 100 (uncompressed)\n            rotation: 90, //0 means 0 DEG\n            format: 'JPEG' //Also accepts 'PNG'\n          }\n        };\n\n        const videoOptions = {\n          loadOptions: {\n            deliveryMode: 'automatic', //defaults to automatic, avaliable: highQuality, mediumQuality, fast\n            version : 'current' //defaults to current, also avaliable: 'original'\n          },\n          //For docs on values see links provided and se string values. Can be outdate. refer to SDK in xcode for updated values\n          postProcessOptions: {\n            outputFileType: 'public.mpeg-4', //defaults to 'public.mpeg-4'(AVFileTypeMPEG4), other avaliable:  https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.7.sdk/System/Library/Frameworks/AVFoundation.framework/Versions/A/Headers/AVMediaFormat.h#L50\n            codecKey: 'avc1', //defaults to 'avc1' (AVVideoCodecH264), other avaliable: https://github.com/bruce0505/ios7frameworks/blob/master/AVFoundation/AVVideoSettings.h#L35\n            bitrateMultiplier: 3,\n            minimumBitrate: 300000,\n            width : 100,\n            height : 50\n          }\n        };\n       /* RNPhotosFramework.saveAssetsToDisk(data.assets.map(asset => ({\n          asset: asset,\n          options: videoOptions\n        })), {\n            onProgress: (e) => {\n              console.log(e);\n            }\n          }).then((result) => {\n            //debugger;\n          });*/\n        data.assets[0].saveAssetToDisk({ \n          fileName : 'test.png',\n          dir: RNFetchBlob.fs.dirs.DocumentDir,\n          ...videoOptions\n        }, (e) => {\n          console.log(e);\n        }).then((result) => {\n          console.log('finnished');\n          RNFetchBlob.fs.exists(result.fileUrl)\n            .then((exist) => {\n              console.log(`file ${result.fileUrl} ${exist ? '' : 'not'} exists`)\n            });\n        });\n\n\n        console.log(data.assets.map(x => x.collectionIndex));\n        simple_timer.stop('fetch_timer');\n        console.log('react-native-photos-framework fetch request took %s milliseconds.', simple_timer.get('fetch_timer').delta)\n        this._appendImages(data);\n      }, (e) => console.log(e));\n  }\n\n  _appendImages(data) {\n    var assets = data.assets;\n    var newState = {\n      loadingMore: false\n    };\n\n    if (data.includesLastAsset) {\n      newState.noMore = true;\n    }\n\n    if (assets.length > 0) {\n      newState.images = this\n        .state\n        .images\n        .concat(assets);\n      newState.dataSource = this\n        .state\n        .dataSource\n        .cloneWithRows(this._nEveryRow(newState.images, this.props.imagesPerRow));\n    }\n\n    this.setState(newState);\n  }\n\n  render() {\n    var { dataSource } = this.state;\n    var {\n      scrollRenderAheadDistance,\n      initialListSize,\n      pageSize,\n      removeClippedSubviews,\n      imageMargin,\n      backgroundColor,\n      emptyText,\n      emptyTextStyle\n    } = this.props;\n\n    var listViewOrEmptyText = dataSource.getRowCount() > 0\n      ? (<ListView\n        style={{\n          flex: 1\n        }}\n        scrollRenderAheadDistance={scrollRenderAheadDistance}\n        initialListSize={initialListSize}\n        pageSize={pageSize}\n        removeClippedSubviews={removeClippedSubviews}\n        renderFooter={this\n          ._renderFooterSpinner\n          .bind(this)}\n        onEndReached={this\n          ._onEndReached\n          .bind(this)}\n        onEndReachedThreshold={2000}\n        dataSource={dataSource}\n        renderRow={rowData => this._renderRow(rowData)} />)\n      : (\n        <Text\n          style={[\n            {\n              textAlign: 'center'\n            },\n            emptyTextStyle\n          ]}>{emptyText}</Text>\n      );\n\n    return (\n      <View\n        style={[\n          styles.wrapper, {\n            padding: imageMargin,\n            paddingRight: 0,\n            backgroundColor: backgroundColor\n          }\n        ]}>\n        {listViewOrEmptyText}\n      </View>\n    );\n  }\n\n  _renderImage(item) {\n    var { selected } = this.state;\n    var { imageMargin, selectedMarker, imagesPerRow, containerWidth } = this.props;\n    var uri = item.uri;\n    var isSelected = (this._arrayObjectIndexOf(selected, 'uri', uri) >= 0)\n      ? true\n      : false;\n\n    return (<ImageItem\n      key={uri}\n      displayDates={true}\n      item={item}\n      selected={isSelected}\n      imageMargin={imageMargin}\n      selectedMarker={selectedMarker}\n      imagesPerRow={imagesPerRow}\n      containerWidth={containerWidth}\n      onClick={this\n        ._selectImage\n        .bind(this)} />);\n  }\n\n  _renderRow(rowData) {\n    var items = rowData.map((item) => {\n      if (item === null) {\n        return null;\n      }\n      return this._renderImage(item);\n    });\n\n    return (\n      <View style={styles.row}>\n        {items}\n      </View>\n    );\n  }\n\n  _renderFooterSpinner() {\n    if (!this.state.noMore) {\n      return <ActivityIndicator style={styles.spinner} />;\n    }\n    return null;\n  }\n\n  _onEndReached() {\n    if (!this.state.noMore) {\n      this.fetch();\n    }\n  }\n\n  _selectImage(image) {\n    var { maximum, imagesPerRow, callback } = this.props;\n\n    var selected = this.state.selected,\n      index = this._arrayObjectIndexOf(selected, 'uri', image.uri);\n\n    if (index >= 0) {\n      selected.splice(index, 1);\n    } else {\n      if (selected.length < maximum) {\n        selected.push(image);\n      }\n    }\n\n    this.setState({\n      selected: selected,\n      dataSource: this\n        .state\n        .dataSource\n        .cloneWithRows(this._nEveryRow(this.state.images, imagesPerRow))\n    });\n\n    callback(this.state.selected, image);\n  }\n\n  _nEveryRow(data, n) {\n    var result = [],\n      temp = [];\n\n    for (var i = 0; i < data.length; ++i) {\n      if (i > 0 && i % n === 0) {\n        result.push(temp);\n        temp = [];\n      }\n      temp.push(data[i]);\n    }\n\n    if (temp.length > 0) {\n      while (temp.length !== n) {\n        temp.push(null);\n      }\n      result.push(temp);\n    }\n\n    return result;\n  }\n\n  _arrayObjectIndexOf(array, property, value) {\n    return array.map((o) => {\n      return o[property];\n    }).indexOf(value);\n  }\n\n}\n\nconst styles = StyleSheet.create({\n  wrapper: {\n    flex: 1\n  },\n  row: {\n    flexDirection: 'row',\n    flex: 1\n  },\n  marker: {\n    position: 'absolute',\n    top: 5,\n    backgroundColor: 'transparent'\n  }\n})\n\nCameraRollPicker.propTypes = {\n  scrollRenderAheadDistance: React.PropTypes.number,\n  initialListSize: React.PropTypes.number,\n  pageSize: React.PropTypes.number,\n  removeClippedSubviews: React.PropTypes.bool,\n  groupTypes: React\n    .PropTypes\n    .oneOf([\n      'Album',\n      'All',\n      'Event',\n      'Faces',\n      'Library',\n      'PhotoStream',\n      'SavedPhotos'\n    ]),\n  maximum: React.PropTypes.number,\n  assetType: React\n    .PropTypes\n    .oneOf(['Photos', 'Videos', 'All']),\n  imagesPerRow: React.PropTypes.number,\n  imageMargin: React.PropTypes.number,\n  containerWidth: React.PropTypes.number,\n  callback: React.PropTypes.func,\n  selected: React.PropTypes.array,\n  selectedMarker: React.PropTypes.element,\n  backgroundColor: React.PropTypes.string,\n  emptyText: React.PropTypes.string,\n  emptyTextStyle: Text.propTypes.style\n}\n\nCameraRollPicker.defaultProps = {\n  scrollRenderAheadDistance: 800,\n  initialListSize: 1,\n  pageSize: 12,\n  removeClippedSubviews: true,\n  groupTypes: 'SavedPhotos',\n  maximum: 15,\n  imagesPerRow: 3,\n  imageMargin: 5,\n  assetType: 'Photos',\n  backgroundColor: 'white',\n  selected: [],\n  callback: function (selectedImages, currentImage) {\n    console.log(currentImage);\n    console.log(selectedImages);\n  },\n  emptyText: 'No photos.'\n}\n\nexport default CameraRollPicker;\n"
  },
  {
    "path": "example/react-native-camera-roll-picker/index.ios.js",
    "content": "import React, { Component } from 'react';\nimport {\n  AppRegistry,\n  StyleSheet,\n  Text,\n  View,\n  TouchableOpacity,\n  AlertIOS,\n  Image\n} from 'react-native';\nimport CameraRollPicker from './camera-roll-picker';\nimport { Actions } from 'react-native-router-flux';\nimport RNPhotosFramework from '../react-native-photos-framework';\nimport TrashIcon from '../images/trash2.png';\n\nexport default class ReactNativeCameraRollPicker extends Component {\n  constructor(props) {\n    super(props);\n\n    this.state = {\n      num: 0,\n      selected: [],\n      edit: false\n    };\n  }\n\n  componentDidMount() {\n    Actions.refresh({\n      renderRightButton: this\n        .renderRightButton\n        .bind(this),\n      edit: false\n    });\n  }\n\n  removeSelectedFromAlbum() {\n    this\n      .props\n      .album\n      .removeAssets(this.state.selected);\n  }\n\n  deleteSelectedFromLibrary() {\n    RNPhotosFramework\n      .deleteAssets(this.state.selected)\n      .then((status) => {\n        if (status.success) {\n          const remaining = this\n            .state\n            .selected\n            .filter(x => status.localIdentifiers.some(y => y === x.localIdentfier));\n          this.setState({ selected: remaining });\n          Actions.refresh({\n            renderRightButton: this\n              .renderRightButton\n              .bind(this, this.props.edit, !!remaining.length)\n          });\n        }\n      });\n  }\n\n  afterRemove() {\n\n  }\n\n  removeSelectedImages() {\n    AlertIOS.alert('Remove media', 'Select how to remove', [\n      {\n        text: 'Remove from album',\n        onPress: this\n          .removeSelectedFromAlbum\n          .bind(this)\n      }, {\n        text: 'Delete from library',\n        onPress: this\n          .deleteSelectedFromLibrary\n          .bind(this)\n      }, {\n        text: 'Cancel',\n        onPress: () => console.log('Cancel Pressed'),\n        style: 'cancel'\n      }\n    ], );\n  }\n\n  renderRightButton(edit, hasSelectedMedia) {\n    return (\n      <View style={{\n        flexDirection: 'row'\n      }}>\n        {(edit && (hasSelectedMedia === true))\n          ? (\n            <TouchableOpacity\n              onPress={this\n                .removeSelectedImages\n                .bind(this)}>\n              <Image source={TrashIcon} style={styles.trashIcon}></Image>\n            </TouchableOpacity>\n          )\n          : null}\n\n        <TouchableOpacity\n          style={{\n            marginLeft: 24\n          }}\n          onPress={this\n            .onEditAlbum\n            .bind(this)}>\n          <Text style={styles.changeButton}>{(edit\n            ? 'Done'\n            : 'Edit')}</Text>\n        </TouchableOpacity>\n      </View>\n\n    );\n  }\n\n  onEditAlbum() {\n    Actions.refresh({\n      edit: !this.props.edit\n    });\n  }\n\n  componentWillReceiveProps(nextProps) {\n    if (this.props.edit !== nextProps.edit) {\n      Actions.refresh({\n        renderRightButton: this\n          .renderRightButton\n          .bind(this, nextProps.edit)\n      });\n    }\n  }\n\n  getSelectedImages(images, current) {\n    var num = images.length;\n    this.setState({ num: num, selected: images });\n    Actions.refresh({\n      renderRightButton: this\n        .renderRightButton\n        .bind(this, this.props.edit, !!images.length)\n    });\n  }\n\n  downloadTenRandom() {\n    RNPhotosFramework.createAssets({\n      images: [\n        {\n          uri: 'https://static1.squarespace.com/static/54864b83e4b0c89104abed87/t/54c6102fe4b02c' +\n          'f35cfb7e97/1422266417481/stock-photo-vancouver-sunrise-27499741.jpg?format=1500w'\n        }, {\n          uri: 'https://d1wtqaffaaj63z.cloudfront.net/images/E-0510.JPG'\n        }, {\n          uri: 'https://upload.wikimedia.org/wikipedia/commons/c/c6/Kimi_Raikkonen_2006_test.jpg'\n        }, {\n          uri: 'https://www.w3.org/MarkUp/Test/xhtml-print/20050519/tests/jpeg420exif.jpg'\n        }, {\n          uri: 'https://screensaver.riotgames.com/latest/content/original/Runeterra/Ionia/ionia-' +\n          '01.jpg'\n        }\n      ]\n    }, (progressData) => { \n      //OnProgress \n      console.log(progressData);\n    }).then((assets) => {\n      this\n        .props\n        .album\n        .addAssets(assets)\n        .then((status) => { });\n    });\n  }\n\n  insertLocalImage() {\n    RNPhotosFramework.createAssets({\n      images: [\n        {\n          uri: 'testimage.jpg'\n        }\n      ]\n    }, (progressData) => {\n      //OnProgress\n      console.log(progressData);\n    }).then((assets) => {\n      this\n        .props\n        .album\n        .addAssets(assets)\n        .then((status) => { });\n    });\n  }\n\n  insertTwoLocalImages() {\n    RNPhotosFramework.createAssets({\n      images: [\n        {\n          uri: 'testimage.jpg'\n        },\n        {\n          uri: 'testimage2.jpg'\n        }\n      ]\n    }).then((assets) => {\n      this\n        .props\n        .album\n        .addAssets(assets)\n        .then((status) => { });\n    });\n  }\n\n  insertLocalVideo() {\n    RNPhotosFramework.createAssets({\n      videos: [\n        {\n          uri: 'test-video',\n          type: 'MOV'\n        }\n      ]\n    }).then((assets) => {\n      this\n        .props\n        .album\n        .addAssets(assets)\n        .then((status) => { });\n    });\n  }\n\n  insertTwoLocalVideos() {\n    RNPhotosFramework.createAssets({\n      videos: [\n        {\n          uri: 'test-video',\n          type: 'MOV'\n        },\n        {\n          uri: 'test-video2',\n          type: 'MOV'\n        }\n      ]\n    }).then((assets) => {\n      this\n        .props\n        .album\n        .addAssets(assets)\n        .then((status) => { });\n    });\n  }\n\n  insertRemoteLocalVideo() {\n    RNPhotosFramework.createAssets({\n      videos: [\n        {\n          uri: 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4',\n          type: 'mp4'\n        },\n        {\n          uri: 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4',\n          type: 'mp4'\n        },\n        {\n          uri: 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4',\n          type: 'mp4'\n        },\n        {\n          uri: 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4',\n          type: 'mp4'\n        },\n        {\n          uri: 'http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4',\n          type: 'mp4'\n        }\n      ],\n      images: [{\n        uri: 'testimage.jpg'\n      }],\n    }, (progressData) => {\n      //OnProgress\n      console.log(progressData);\n    }).then((assets) => {\n      this\n        .props\n        .album\n        .addAssets(assets)\n        .then((status) => { });\n    });\n  }\n\n  downloadDialog() {\n    AlertIOS.alert('Add media', 'Select what to add:', [\n      {\n        text: 'Insert local image',\n        onPress: this\n          .insertLocalImage\n          .bind(this)\n      },\n      {\n        text: 'Insert two local images',\n        onPress: this\n          .insertTwoLocalImages\n          .bind(this)\n      },\n      {\n        text: 'Insert local video',\n        onPress: this\n          .insertLocalVideo\n          .bind(this)\n      },\n      {\n        text: 'Insert two local videos',\n        onPress: this\n          .insertTwoLocalVideos\n          .bind(this)\n      },\n      {\n        text: 'Insert remote video',\n        onPress: this\n          .insertRemoteLocalVideo\n          .bind(this)\n      },\n      {\n        text: 'Insert 5 remote photos',\n        onPress: this\n          .downloadTenRandom\n          .bind(this)\n      }, {\n        text: 'Cancel',\n        onPress: () => console.log('Cancel Pressed'),\n        style: 'cancel'\n      }\n    ], );\n  }\n\n  render() {\n    return (\n      <View style={styles.container}>\n\n        <CameraRollPicker\n          album={this.props.album}\n          removeClippedSubviews={true}\n          groupTypes='SavedPhotos'\n          batchSize={5}\n          maximum={99}\n          selected={this.state.selected}\n          assetType='Photos'\n          imagesPerRow={3}\n          imageMargin={5}\n          callback={this\n            .getSelectedImages\n            .bind(this)} />\n\n        <View style={[styles.addMediaContainer, {\n          opacity: this\n            .props\n            .album.addContentPermitted() ? 1 : 0\n        }]}>\n          <TouchableOpacity\n            style={styles.addMediaButton}\n            onPress={this\n              .downloadDialog\n              .bind(this)}>\n            <Text style={styles.addMediaText}>Add media</Text>\n          </TouchableOpacity>\n        </View>\n      </View>\n    );\n  }\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    marginTop: 65\n  },\n  addMediaContainer: {\n    position: 'absolute',\n    bottom: 0,\n    left: 0,\n    right: 0,\n    backgroundColor: 'rgba(255, 255, 255, 0.6)',\n    padding: 10\n  },\n  addMediaButton: {\n    padding: 20,\n    backgroundColor: 'white',\n    borderWidth: 1,\n    borderColor: 'rgb(34, 125, 197)',\n    borderRadius: 10,\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n  addMediaText: {\n    color: 'rgb(34, 125, 197)',\n    fontSize: 20,\n    fontWeight: 'bold',\n    backgroundColor: 'transparent'\n  },\n  content: {\n    marginTop: 15,\n    height: 50,\n    flexDirection: 'row',\n    justifyContent: 'center',\n    alignItems: 'center',\n    flexWrap: 'wrap'\n  },\n  text: {\n    fontSize: 16,\n    alignItems: 'center',\n    color: '#fff'\n  },\n  bold: {\n    fontWeight: 'bold'\n  },\n  info: {\n    fontSize: 12\n  },\n  addButtonPlus: {\n    width: 30,\n    height: 40,\n    top: -10,\n    fontSize: 32,\n    color: 'rgb(0, 113, 255)',\n    backgroundColor: 'transparent'\n  },\n  trashIcon: {\n    width: 25,\n    height: 25\n  },\n  changeButton: {\n    fontSize: 18,\n    color: 'rgb(0, 113, 255)'\n  },\n  removeIconContainer: {\n    position: 'absolute',\n    top: 5,\n    left: 0,\n    backgroundColor: 'white',\n    borderRadius: 14,\n    height: 20,\n    width: 23\n  },\n  removeIcon: {\n    top: -5,\n    fontSize: 28,\n    color: 'red',\n    backgroundColor: 'transparent'\n  },\n  backgroundVideo: {\n    width: 500,\n    height: 500\n  }\n});\n"
  },
  {
    "path": "example/react-native-photos-framework/event-emitter.js",
    "content": "import EventEmitter from \"EventEmitter\";\nexport default EventEmitter;\n"
  },
  {
    "path": "example/react-native-photos-framework/index.js",
    "content": "import RNPFManager from './src/index';\nexport default RNPFManager;\n"
  },
  {
    "path": "example/tsconfig.json",
    "content": "{\"compilerOptions\":{\"allowJs\":true},\"exclude\":[\"node_modules\"]}"
  },
  {
    "path": "index.js",
    "content": "import RNPFManager from './src/index';\nexport default RNPFManager;\n"
  },
  {
    "path": "install.js",
    "content": "const fs = require('fs');\nconst path = require('path');\nconst configPath = path.join(process.cwd(), '../../package.json');\nif (fs.existsSync(configPath)) {\n    const rnpmConfig = require('./local-cli/core/config');\n    const link = require('./local-cli/link/link.js');\n    const xcode = require('xcode');\n    const getPlist = require('./local-cli/link/ios/getPlist');\n    const getPlistPath = require('./local-cli/link/ios/getPlistPath');\n    const plistParser = require('plist');\n\n    const config = {\n        getProjectConfig: rnpmConfig.getProjectConfig,\n        getDependencyConfig: rnpmConfig.getDependencyConfig,\n    };\n\n    const projectConfig = config.getProjectConfig(path.join(process.cwd(), '../../'));\n    const project = xcode.project(projectConfig.ios.pbxprojPath).parseSync();\n    const plist = getPlist(project, projectConfig.ios.sourceDir);\n    if (!plist.NSPhotoLibraryUsageDescription) {\n        plist.NSPhotoLibraryUsageDescription = 'Using photo library to select pictures';\n        console.log('Added NSPhotoLibraryUsageDescription to Info.plist');\n    }\n\n    fs.writeFileSync(\n        getPlistPath(project, projectConfig.ios.sourceDir),\n        plistParser.build(plist)\n    );\n}"
  },
  {
    "path": "ios/RNPhotosFramework/ImageHelpers.h",
    "content": "/*\n File: ImageHelpers.h\n\n Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple\n Inc. (\"Apple\") in consideration of your agreement to the following\n terms, and your use, installation, modification or redistribution of\n this Apple software constitutes acceptance of these terms.  If you do\n not agree with these terms, please do not use, install, modify or\n redistribute this Apple software.\n\n In consideration of your agreement to abide by the following terms, and\n subject to these terms, Apple grants you a personal, non-exclusive\n license, under Apple's copyrights in this original Apple software (the\n \"Apple Software\"), to use, reproduce, modify and redistribute the Apple\n Software, with or without modifications, in source and/or binary forms;\n provided that if you redistribute the Apple Software in its entirety and\n without modifications, you must retain this notice and the following\n text and disclaimers in all such redistributions of the Apple Software.\n Neither the name, trademarks, service marks or logos of Apple Inc. may\n be used to endorse or promote products derived from the Apple Software\n without specific prior written permission from Apple.  Except as\n expressly stated in this notice, no other rights or licenses, express or\n implied, are granted by Apple herein, including but not limited to any\n patent rights that may be infringed by your derivative works or by other\n works in which the Apple Software may be incorporated.\n\n The Apple Software is provided by Apple on an \"AS IS\" basis.  APPLE\n MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION\n THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS\n FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND\n OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.\n\n IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL\n OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,\n MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED\n AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),\n STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE\n POSSIBILITY OF SUCH DAMAGE.\n\n Copyright (C) 2009 Apple Inc. All Rights Reserved.\n */\n\n#include <UIKit/UIKit.h>\n\nextern const CGBitmapInfo RNPFkDefaultCGBitmapInfo;\nextern const CGBitmapInfo RNPFkDefaultCGBitmapInfoNoAlpha;\n\nfloat\t\t\tRNPFGetScaleForProportionalResize( CGSize theSize, CGSize intoSize, bool onlyScaleDown, bool maximize );\nCGContextRef\tRNPFCreateCGBitmapContextForWidthAndHeight( unsigned int width, unsigned int height, CGColorSpaceRef optionalColorSpace, CGBitmapInfo optionalInfo );\n\nCGImageRef\t\tRNPFCreateCGImageFromUIImageScaled( UIImage* inImage, float scaleFactor );\n\n@interface UIImage (scale)\n-(UIImage*)scaleToSize:(CGSize)toSize;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/ImageHelpers.m",
    "content": "/*\n File: ImageHelpers.m\n\n Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple\n Inc. (\"Apple\") in consideration of your agreement to the following\n terms, and your use, installation, modification or redistribution of\n this Apple software constitutes acceptance of these terms.  If you do\n not agree with these terms, please do not use, install, modify or\n redistribute this Apple software.\n\n In consideration of your agreement to abide by the following terms, and\n subject to these terms, Apple grants you a personal, non-exclusive\n license, under Apple's copyrights in this original Apple software (the\n \"Apple Software\"), to use, reproduce, modify and redistribute the Apple\n Software, with or without modifications, in source and/or binary forms;\n provided that if you redistribute the Apple Software in its entirety and\n without modifications, you must retain this notice and the following\n text and disclaimers in all such redistributions of the Apple Software.\n Neither the name, trademarks, service marks or logos of Apple Inc. may\n be used to endorse or promote products derived from the Apple Software\n without specific prior written permission from Apple.  Except as\n expressly stated in this notice, no other rights or licenses, express or\n implied, are granted by Apple herein, including but not limited to any\n patent rights that may be infringed by your derivative works or by other\n works in which the Apple Software may be incorporated.\n\n The Apple Software is provided by Apple on an \"AS IS\" basis.  APPLE\n MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION\n THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS\n FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND\n OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.\n\n IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL\n OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,\n MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED\n AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),\n STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE\n POSSIBILITY OF SUCH DAMAGE.\n\n Copyright (C) 2009 Apple Inc. All Rights Reserved.\n */\n\n#include \"ImageHelpers.h\"\n\nconst CGBitmapInfo RNPFkDefaultCGBitmapInfo\t= (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);\nconst CGBitmapInfo RNPFkDefaultCGBitmapInfoNoAlpha\t= (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host);\n\nCGColorSpaceRef\tRNPFGetDeviceRGBColorSpace() {\n    static CGColorSpaceRef\tdeviceRGBSpace\t= NULL;\n    if( deviceRGBSpace == NULL )\n        deviceRGBSpace\t= CGColorSpaceCreateDeviceRGB();\n    return deviceRGBSpace;\n}\n\nfloat RNPFGetScaleForProportionalResize( CGSize theSize, CGSize intoSize, bool onlyScaleDown, bool maximize )\n{\n    float\tsx = theSize.width;\n    float\tsy = theSize.height;\n    float\tdx = intoSize.width;\n    float\tdy = intoSize.height;\n    float\tscale\t= 1;\n\n    if( sx != 0 && sy != 0 )\n    {\n        dx\t= dx / sx;\n        dy\t= dy / sy;\n\n        // if maximize is true, take LARGER of the scales, else smaller\n        if( maximize )\t\tscale\t= (dx > dy)\t? dx : dy;\n        else\t\t\t\tscale\t= (dx < dy)\t? dx : dy;\n\n        if( scale > 1 && onlyScaleDown )\t// reset scale\n            scale\t= 1;\n    }\n    else\n    {\n        scale\t = 0;\n    }\n    return scale;\n}\n\nCGContextRef RNPFCreateCGBitmapContextForWidthAndHeight( unsigned int width, unsigned int height,\n                                                    CGColorSpaceRef optionalColorSpace, CGBitmapInfo optionalInfo )\n{\n    CGColorSpaceRef\tcolorSpace\t= (optionalColorSpace == NULL) ? RNPFGetDeviceRGBColorSpace() : optionalColorSpace;\n    CGBitmapInfo\talphaInfo\t= ( (int32_t)optionalInfo < 0 ) ? RNPFkDefaultCGBitmapInfo : optionalInfo;\n    return CGBitmapContextCreate( NULL, width, height, 8, 0, colorSpace, alphaInfo );\n}\n\nCGImageRef RNPFCreateCGImageFromUIImageScaled( UIImage* image, float scaleFactor )\n{\n    CGImageRef\t\t\tnewImage\t\t= NULL;\n    CGContextRef\t\tbmContext\t\t= NULL;\n    BOOL\t\t\t\tmustTransform\t= YES;\n    CGAffineTransform\ttransform\t\t= CGAffineTransformIdentity;\n    UIImageOrientation\torientation\t\t= image.imageOrientation;\n\n    CGImageRef\t\t\tsrcCGImage\t\t= CGImageRetain( image.CGImage );\n\n    size_t width\t= CGImageGetWidth(srcCGImage) * scaleFactor;\n    size_t height\t= CGImageGetHeight(srcCGImage) * scaleFactor;\n\n    // These Orientations are rotated 0 or 180 degrees, so they retain the width/height of the image\n    if( (orientation == UIImageOrientationUp) || (orientation == UIImageOrientationDown) || (orientation == UIImageOrientationUpMirrored) || (orientation == UIImageOrientationDownMirrored)  )\n    {\n        bmContext\t= RNPFCreateCGBitmapContextForWidthAndHeight( width, height, NULL, RNPFkDefaultCGBitmapInfo );\n    }\n    else\t// The other Orientations are rotated ±90 degrees, so they swap width & height.\n    {\n        bmContext\t= RNPFCreateCGBitmapContextForWidthAndHeight( height, width, NULL, RNPFkDefaultCGBitmapInfo );\n    }\n\n    //CGContextSetInterpolationQuality( bmContext, kCGInterpolationLow );\n    CGContextSetBlendMode( bmContext, kCGBlendModeCopy );\t// we just want to copy the data\n\n    switch(orientation)\n    {\n        case UIImageOrientationDown:\t\t// 0th row is at the bottom, and 0th column is on the right - Rotate 180 degrees\n            transform\t= CGAffineTransformMake(-1.0, 0.0, 0.0, -1.0, width, height);\n            break;\n\n        case UIImageOrientationLeft:\t\t// 0th row is on the left, and 0th column is the bottom - Rotate -90 degrees\n            transform\t= CGAffineTransformMake(0.0, 1.0, -1.0, 0.0, height, 0.0);\n            break;\n\n        case UIImageOrientationRight:\t\t// 0th row is on the right, and 0th column is the top - Rotate 90 degrees\n            transform\t= CGAffineTransformMake(0.0, -1.0, 1.0, 0.0, 0.0, width);\n            break;\n\n        case UIImageOrientationUpMirrored:\t// 0th row is at the top, and 0th column is on the right - Flip Horizontal\n            transform\t= CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, width, 0.0);\n            break;\n\n        case UIImageOrientationDownMirrored:\t// 0th row is at the bottom, and 0th column is on the left - Flip Vertical\n            transform\t= CGAffineTransformMake(1.0, 0.0, 0, -1.0, 0.0, height);\n            break;\n\n        case UIImageOrientationLeftMirrored:\t// 0th row is on the left, and 0th column is the top - Rotate -90 degrees and Flip Vertical\n            transform\t= CGAffineTransformMake(0.0, -1.0, -1.0, 0.0, height, width);\n            break;\n\n        case UIImageOrientationRightMirrored:\t// 0th row is on the right, and 0th column is the bottom - Rotate 90 degrees and Flip Vertical\n            transform\t= CGAffineTransformMake(0.0, 1.0, 1.0, 0.0, 0.0, 0.0);\n            break;\n\n        default:\n            mustTransform\t= NO;\n            break;\n    }\n\n    if( mustTransform )\tCGContextConcatCTM( bmContext, transform );\n\n    CGContextDrawImage( bmContext, CGRectMake(0.0, 0.0, width, height), srcCGImage );\n    CGImageRelease( srcCGImage );\n    newImage = CGBitmapContextCreateImage( bmContext );\n    CFRelease( bmContext );\n\n    return newImage;\n}\n\n@implementation UIImage (scale)\n\n-(UIImage*) scaleToSize:(CGSize)toSize\n{\n    UIImage\t*scaledImg\t= nil;\n    float\tscale\t\t= RNPFGetScaleForProportionalResize( self.size, toSize, false, false );\n    CGImageRef cgImage\t= RNPFCreateCGImageFromUIImageScaled( self, scale );\n\n    if( cgImage )\n    {\n        scaledImg\t= [UIImage imageWithCGImage:cgImage];\t// autoreleased\n        CGImageRelease( cgImage );\n    }\n    return scaledImg;\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHAssetWithCollectionIndex.h",
    "content": "#import <Foundation/Foundation.h>\n@import Photos;\n@interface PHAssetWithCollectionIndex : NSObject\n\n- (instancetype)initWithAsset:(PHAsset *)asset andCollectionIndex:(NSNumber *)index;\n+ (NSArray<PHAsset *> *) toAssetsArray:(NSArray<PHAssetWithCollectionIndex *> *)assetsWithIndexArray;\n\n@property (atomic, strong) PHAsset *asset;\n@property (strong) NSNumber *collectionIndex;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHAssetWithCollectionIndex.m",
    "content": "#import \"PHAssetWithCollectionIndex.h\"\n\n@implementation PHAssetWithCollectionIndex\n\n- (instancetype)initWithAsset:(PHAsset *)asset andCollectionIndex:(NSNumber *)index\n{\n    self = [super init];\n    if (self) {\n        self.asset = asset;\n        self.collectionIndex = index;\n    }\n    return self;\n}\n\n+ (NSArray<PHAsset *> *) toAssetsArray:(NSArray<PHAssetWithCollectionIndex *> *)assetsWithIndexArray {\n    if(assetsWithIndexArray == nil) {\n        return nil;\n    }\n    NSMutableArray *arrayWithAssets = [NSMutableArray new];\n    [assetsWithIndexArray enumerateObjectsUsingBlock:^(PHAssetWithCollectionIndex * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {\n        [arrayWithAssets addObject:[obj asset]];\n    }];\n    return arrayWithAssets;\n}\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHAssetsService.h",
    "content": "#import <Foundation/Foundation.h>\n#import \"PHAssetWithCollectionIndex.h\"\n@import Photos;\n@import MobileCoreServices;\n\n@interface PHAssetsService : NSObject\n\ntypedef NS_OPTIONS(NSUInteger, AssetEnumerationDirection) {\n    AssetEnumerationDirectionFromStart = (1UL << 0),\n    AssetEnumerationDirectionFromEnd = (1UL << 1),\n};\n\n+(PHFetchResult<PHAsset *> *) getAssetsForParams:(NSDictionary *)params;\n+(NSArray<NSDictionary *> *) assetsArrayToUriArray:(NSArray<id> *)assetsArray andincludeMetadata:(BOOL)includeMetadata andIncludeAssetResourcesMetadata:(BOOL)includeResourcesMetadata;\n+(NSMutableArray<PHAssetWithCollectionIndex*> *) getAssetsForFetchResult:(PHFetchResult *)assetsFetchResult startIndex:(int)startIndex endIndex:(int)endIndex assetDisplayStartToEnd:(BOOL)assetDisplayStartToEnd andAssetDisplayBottomUp:(BOOL)assetDisplayBottomUp;\n+(NSMutableArray<PHAssetWithCollectionIndex*> *) getAssetsForFetchResult:(PHFetchResult *)assetsFetchResult atIndecies:(NSArray<NSNumber *> *)indecies;\n+(PHFetchResult<PHAsset *> *) getAssetsFromArrayOfLocalIdentifiers:(NSArray<NSString *> *)arrayWithLocalIdentifiers;\n+(NSMutableDictionary *)extendAssetDictWithAssetMetadata:(NSMutableDictionary *)dictToExtend andPHAsset:(PHAsset *)asset;\n+(NSMutableDictionary *)extendAssetDictWithAssetResourcesMetadata:(NSMutableDictionary *)dictToExtend andPHAsset:(PHAsset *)asset;\n+(void)extendAssetDictWithPhotoAssetEditingMetadata:(NSMutableDictionary *)dictToExtend andPHAsset:(PHAsset *)asset andCompletionBlock:(void(^)(NSMutableDictionary * dict))completeBlock;\n+(void)deleteAssets:(PHFetchResult<PHAsset *> *)assetsToDelete andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error, NSArray<NSString *> * localIdentifiers))completeBlock;\n+(void)updateAssetWithParams:(NSDictionary *)params completionBlock:(void(^)(BOOL success, NSError * _Nullable error, NSString * _Nullable localIdentifier))completionBlock andAsset:(PHAsset *)asset;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHAssetsService.m",
    "content": "#import \"PHAssetsService.h\"\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n#import \"PHFetchOptionsService.h\"\n#import \"PHCache.h\"\n#import \"RNPFHelpers.h\"\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n#import <React/RCTProfile.h>\n#import \"PHAssetWithCollectionIndex.h\"\n\n@import Photos;\n@implementation PHAssetsService\n\n+(PHFetchResult<PHAsset *> *) getAssetsForParams:(NSDictionary *)params  {\n    NSString * cacheKey = [RCTConvert NSString:params[@\"_cacheKey\"]];\n    NSString * albumLocalIdentifier = [RCTConvert NSString:params[@\"albumLocalIdentifier\"]];\n\n    if(cacheKey != nil) {\n        PHCachedFetchResult *cachedResultSet = [[PHCache sharedPHCache] getFetchResultFromCacheWithuuid:cacheKey];\n        if(cachedResultSet != nil) {\n            return [cachedResultSet fetchResult];\n        }\n    }\n\n    PHFetchResult<PHAsset *> *fetchResult;\n    if(albumLocalIdentifier != nil) {\n        fetchResult = [self getAssetsForParams:params andAlbumLocalIdentifier:albumLocalIdentifier];\n    }\n    if(fetchResult == nil) {\n        fetchResult = [PHAssetsService getAllAssetsForParams:params];\n    }\n\n    if(cacheKey != nil && fetchResult != nil) {\n        [[PHCache sharedPHCache] cacheFetchResultWithUUID:fetchResult andObjectType:[PHAsset class] andUUID:cacheKey andOrginalFetchParams:params];\n    }\n\n    return fetchResult;\n}\n\n+(PHFetchResult<PHAsset *> *)getAssetsForParams:(NSDictionary *)params andAlbumLocalIdentifier:(NSString *)albumLocalIdentifier {\n    PHFetchOptions *options = [PHFetchOptionsService getAssetFetchOptionsFromParams:params];\n    PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[albumLocalIdentifier] options:nil];\n\n    PHFetchResult<PHAsset *> * assets = [PHAsset fetchAssetsInAssetCollection:collections.firstObject options:options];\n    return assets;\n}\n\n+(PHFetchResult<PHAsset *> *) getAssetsFromArrayOfLocalIdentifiers:(NSArray<NSString *> *)arrayWithLocalIdentifiers {\n    PHFetchOptions *fetchOptions = [PHFetchOptions new];\n    fetchOptions.includeHiddenAssets = YES;\n    fetchOptions.includeAllBurstAssets = YES;\n    return [PHAsset fetchAssetsWithLocalIdentifiers:arrayWithLocalIdentifiers options:fetchOptions];\n}\n\n+(PHFetchResult<PHAsset *> *) getAllAssetsForParams:(NSDictionary *)params {\n    PHFetchOptions *options = [PHFetchOptionsService getAssetFetchOptionsFromParams:params];\n    return [PHAsset fetchAssetsWithOptions:options];\n}\n\n+(NSArray<NSDictionary *> *) assetsArrayToUriArray:(NSArray<id> *)assetsArray andincludeMetadata:(BOOL)includeMetadata andIncludeAssetResourcesMetadata:(BOOL)includeResourcesMetadata {\n    RCT_PROFILE_BEGIN_EVENT(0, @\"-[RCTCameraRollRNPhotosFrameworkManager assetsArrayToUriArray\", nil);\n\n    NSMutableArray *uriArray = [NSMutableArray arrayWithCapacity:assetsArray.count];\n    NSDictionary *reveredMediaTypes = [RCTConvert PHAssetMediaTypeValuesReversed];\n    for(int i = 0;i < assetsArray.count; i++) {\n        id assetObj = [assetsArray objectAtIndex:i];\n        NSNumber *assetIndex = (NSNumber *)[NSNull null];\n        PHAsset *asset;\n        if([assetObj isKindOfClass:[PHAsset class]]) {\n            asset = assetObj;\n        }else {\n            PHAssetWithCollectionIndex *assetWithCollectionIndex = assetObj;\n            asset = assetWithCollectionIndex.asset;\n            assetIndex = assetWithCollectionIndex.collectionIndex;\n        }\n\n        NSMutableDictionary *responseDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:\n                                             [asset localIdentifier], @\"localIdentifier\",\n                                             @([asset pixelWidth]), @\"width\",\n                                             @([asset pixelHeight]), @\"height\",\n                                             [reveredMediaTypes objectForKey:@([asset mediaType])], @\"mediaType\",\n                                             assetIndex, @\"collectionIndex\",\n                                             nil];\n        \n        if([asset mediaType] == PHAssetMediaTypeVideo || [asset mediaType] == PHAssetMediaTypeAudio) {\n            [responseDict setObject:@([asset duration]) forKey:@\"duration\"];\n        }\n\n        if(includeMetadata) {\n            [self extendAssetDictWithAssetMetadata:responseDict andPHAsset:asset];\n        }\n        if(includeResourcesMetadata) {\n            [self extendAssetDictWithAssetResourcesMetadata:responseDict andPHAsset:asset];\n        }\n        \n\n        [uriArray addObject:responseDict];\n    }\n    RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @\"\");\n\n    return uriArray;\n}\n\n+(NSMutableDictionary *)extendAssetDictWithAssetMetadata:(NSMutableDictionary *)dictToExtend andPHAsset:(PHAsset *)asset {\n\n    [dictToExtend setObject:@([RNPFHelpers getTimeSince1970:[asset creationDate]]) forKey:@\"creationDateUTCSeconds\"];\n    [dictToExtend setObject:@([RNPFHelpers getTimeSince1970:[asset modificationDate]])forKey:@\"modificationDateUTCSeconds\"];\n    [dictToExtend setObject:[RNPFHelpers CLLocationToJson:[asset location]] forKey:@\"location\"];\n    [dictToExtend setObject:[RNPFHelpers nsOptionsToArray:[asset mediaSubtypes] andBitSize:32 andReversedEnumDict:[RCTConvert PHAssetMediaSubtypeValuesReversed]] forKey:@\"mediaSubTypes\"];\n    [dictToExtend setObject:@([asset isFavorite]) forKey:@\"isFavorite\"];\n    [dictToExtend setObject:@([asset isHidden]) forKey:@\"isHidden\"];\n    if ([asset respondsToSelector:@selector(sourceType)]) {\n        // not available in iOS 8\n        [dictToExtend setObject:[RNPFHelpers nsOptionsToValue:[asset sourceType] andBitSize:32 andReversedEnumDict:[RCTConvert PHAssetSourceTypeValuesReversed]] forKey:@\"sourceType\"];\n    }\n    NSString *burstIdentifier = [asset burstIdentifier];\n    if(burstIdentifier != nil) {\n        [dictToExtend setObject:burstIdentifier forKey:@\"burstIdentifier\"];\n        [dictToExtend setObject:@([asset representsBurst]) forKey:@\"representsBurst\"];\n        [dictToExtend setObject:[RNPFHelpers nsOptionsToArray:[asset burstSelectionTypes] andBitSize:32 andReversedEnumDict:[RCTConvert PHAssetBurstSelectionTypeValuesReversed]] forKey:@\"burstSelectionTypes\"];\n    }\n\n    NSMutableArray *albumNames = [NSMutableArray array];\n    PHFetchResult *albums = [PHAssetCollection fetchAssetCollectionsContainingAsset:asset withType:PHAssetCollectionTypeAlbum options:nil];\n    for(PHCollection *album in albums) {\n        [albumNames addObject: album.localizedTitle];\n    }\n    PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsContainingAsset:asset withType:PHAssetCollectionTypeSmartAlbum options:nil];\n    for(PHCollection *album in smartAlbums) {\n        [albumNames addObject: album.localizedTitle];\n    }\n    [dictToExtend setObject:albumNames forKey:@\"inAlbums\"];\n\n    return dictToExtend;\n}\n\n+(NSMutableDictionary *)extendAssetDictWithAssetResourcesMetadata:(NSMutableDictionary *)dictToExtend andPHAsset:(PHAsset *)asset {\n\n    NSArray<PHAssetResource *> *resources = [PHAssetResource assetResourcesForAsset:asset];\n    NSMutableArray *arrayWithResourcesMetadata = [NSMutableArray new];\n\n    for(int i = 0; i < resources.count;i++) {\n        PHAssetResource *resourceMetadata = [resources objectAtIndex:i];\n        \n        NSString *mimeType = (NSString *)[NSNull null];\n        CFStringRef mimeTypeCString = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(resourceMetadata.uniformTypeIdentifier), kUTTagClassMIMEType);\n        if(mimeTypeCString != nil) {\n            mimeType = (__bridge NSString *)(mimeTypeCString);\n        }\n        \n        [arrayWithResourcesMetadata addObject:@{\n                                                     @\"originalFilename\" : resourceMetadata.originalFilename,\n                                                     @\"assetLocalIdentifier\" : resourceMetadata.assetLocalIdentifier,\n                                                     @\"uniformTypeIdentifier\" : resourceMetadata.uniformTypeIdentifier,\n                                                     @\"type\" : [[RCTConvert PHAssetResourceTypeValuesReversed] objectForKey:@(resourceMetadata.type)],\n                                                     @\"mimeType\" : mimeType,\n                                                     @\"fileExtension\" : [resourceMetadata.originalFilename pathExtension]\n                                                     }];\n    }\n\n    [dictToExtend setObject:arrayWithResourcesMetadata forKey:@\"resourcesMetadata\"];\n\n    return dictToExtend;\n}\n\n+(void)extendAssetDictWithPhotoAssetEditingMetadata:(NSMutableDictionary *)dictToExtend andPHAsset:(PHAsset *)asset andCompletionBlock:(void(^)(NSMutableDictionary * dict))completeBlock  {\n    __block NSMutableDictionary * dictionaryToExtendBlocked = dictToExtend;\n    [PHAssetsService requestEditingMetadataWithCompletionBlock:^(NSDictionary<NSString *,id> *dict) {\n        [dictionaryToExtendBlocked setObject:dict forKey:@\"imageMetadata\"];\n        completeBlock(dictionaryToExtendBlocked);\n    } andAsset:asset];\n}\n\n\n+(NSMutableArray<PHAssetWithCollectionIndex*> *) getAssetsForFetchResult:(PHFetchResult *)assetsFetchResult startIndex:(int)startIndex endIndex:(int)endIndex assetDisplayStartToEnd:(BOOL)assetDisplayStartToEnd andAssetDisplayBottomUp:(BOOL)assetDisplayBottomUp {\n\n    NSMutableArray<PHAssetWithCollectionIndex *> *assets = [NSMutableArray new];\n    int assetCount = (int)assetsFetchResult.count;\n\n    if(assetCount != 0) {\n\n        NSDictionary *startAndEndIndex = [self getStartAndEndIndexorAssetEnumerationWithAssetCount:(int)assetsFetchResult.count startIndex:startIndex endIndex:endIndex assetDisplayStartToEnd:assetDisplayStartToEnd];\n        int first = [[startAndEndIndex objectForKey:@\"startIndex\"] intValue];\n        int last = [[startAndEndIndex objectForKey:@\"endIndex\"] intValue];\n\n        AssetEnumerationDirection enumerationOptionsStartToEnd = assetDisplayBottomUp ? AssetEnumerationDirectionFromEnd : AssetEnumerationDirectionFromStart;\n        AssetEnumerationDirection enumerationOptionsEndToStart = assetDisplayBottomUp ? AssetEnumerationDirectionFromStart : AssetEnumerationDirectionFromEnd;\n        // display assets from the bottom to top of page if assetDisplayBottomUp is true\n        AssetEnumerationDirection enumerationOptions = assetDisplayStartToEnd ? enumerationOptionsStartToEnd : enumerationOptionsEndToStart;\n        \n        \n        if(enumerationOptions == AssetEnumerationDirectionFromStart) {\n            for(int i = first; i < last; i++) {\n                PHAsset *asset = [assetsFetchResult objectAtIndex:i];\n                [assets addObject:[[PHAssetWithCollectionIndex alloc] initWithAsset:asset andCollectionIndex:[NSNumber numberWithInt:i]]];\n                \n            }\n        }else {\n            for(int i = (last - 1); i >= first; i--) {\n                PHAsset *asset = [assetsFetchResult objectAtIndex:i];\n                [assets addObject:[[PHAssetWithCollectionIndex alloc] initWithAsset:asset andCollectionIndex:[NSNumber numberWithInt:i]]];\n                \n            }\n        }\n    }\n\n    return assets;\n}\n\n+(NSMutableArray<PHAssetWithCollectionIndex*> *) getAssetsForFetchResult:(PHFetchResult *)assetsFetchResult atIndecies:(NSArray<NSNumber *> *)indecies {\n    NSMutableArray<PHAssetWithCollectionIndex *> *assets = [NSMutableArray new];\n    NSUInteger assetCount = assetsFetchResult.count;\n    for(int i = 0; i < indecies.count; i++) {\n        int collectionIndex = [[indecies objectAtIndex:i] intValue];\n        if(collectionIndex <= (assetCount - 1) && collectionIndex >= 0) {\n            PHAsset *asset = [assetsFetchResult objectAtIndex:collectionIndex];\n            [assets addObject:[[PHAssetWithCollectionIndex alloc] initWithAsset:asset andCollectionIndex:@(collectionIndex)]];\n\n        }\n    }\n    return assets;\n}\n\n\n+(NSIndexSet *) getIndexSetForAssetEnumerationWithAssetCount:(int)assetCount startIndex:(int)startIndex endIndex:(int)endIndex assetDisplayStartToEnd:(BOOL)assetDisplayStartToEnd {\n        int originalStartIndex = startIndex;\n        int originalEndIndex = endIndex;\n        startIndex = (assetCount - endIndex) - 1;\n        endIndex = assetCount - originalStartIndex;\n        // load oldest assets from library first if assetDisplayStartToEnd is true\n        if(assetDisplayStartToEnd) {\n            startIndex = originalStartIndex;\n            endIndex = originalEndIndex;\n        }\n        if(startIndex < 0) {\n            startIndex = 0;\n        }\n        if(endIndex < 0) {\n            endIndex = 0;\n        }\n        if(startIndex >= assetCount) {\n            startIndex = assetCount;\n        }\n        if(endIndex >= assetCount) {\n            endIndex = assetCount;\n        }\n        int indexRangeLength = endIndex - startIndex;\n        // adjust range length calculation if original and active index are 0\n        if(originalStartIndex == 0 && startIndex == 0){\n            indexRangeLength = (endIndex - startIndex) + 1;\n        }\n        if(indexRangeLength >= assetCount){\n            indexRangeLength = assetCount;\n        }\n        return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(startIndex, indexRangeLength)];\n}\n\n+(NSDictionary *) getStartAndEndIndexorAssetEnumerationWithAssetCount:(int)assetCount startIndex:(int)startIndex endIndex:(int)endIndex assetDisplayStartToEnd:(BOOL)assetDisplayStartToEnd {\n    int originalStartIndex = startIndex;\n    int originalEndIndex = endIndex;\n    startIndex = (assetCount - endIndex) - 1;\n    endIndex = assetCount - originalStartIndex;\n    // load oldest assets from library first if assetDisplayStartToEnd is true\n    if(assetDisplayStartToEnd) {\n        startIndex = originalStartIndex;\n        endIndex = originalEndIndex;\n    }\n    if(startIndex < 0) {\n        startIndex = 0;\n    }\n    if(endIndex < 0) {\n        endIndex = 0;\n    }\n    if(startIndex >= assetCount) {\n        startIndex = assetCount;\n    }\n    if(endIndex >= assetCount) {\n        endIndex = assetCount;\n    }\n    int indexRangeLength = endIndex - startIndex;\n    // adjust range length calculation if original and active index are 0\n    if(originalStartIndex == 0 && startIndex == 0){\n        indexRangeLength = (endIndex - startIndex) + 1;\n    }\n    if(indexRangeLength >= assetCount){\n        indexRangeLength = assetCount;\n    }\n    return @{\n             @\"startIndex\" : @(startIndex),\n             @\"endIndex\" : @(startIndex + indexRangeLength),\n            };\n}\n\n\n+(void)deleteAssets:(PHFetchResult<PHAsset *> *)assetsToDelete andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error, NSArray<NSString *> * localIdentifiers))completeBlock {\n    __block NSMutableArray<NSString *> *deletedAssetsLocalIdentifers = [NSMutableArray arrayWithCapacity:assetsToDelete.count];\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        for(int i = 0; i< assetsToDelete.count; i++) {\n            PHAsset *assetToDelete = [assetsToDelete objectAtIndex:i];\n            BOOL req = [assetToDelete canPerformEditOperation:PHAssetEditOperationDelete];\n            if (req) {\n                [deletedAssetsLocalIdentifers addObject:assetToDelete.localIdentifier];\n                [PHAssetChangeRequest deleteAssets:@[assetToDelete]];\n            }\n        }\n    } completionHandler:^(BOOL success, NSError *error) {\n        completeBlock(success, error, deletedAssetsLocalIdentifers);\n    }];\n}\n\n+(void)requestEditingMetadataWithCompletionBlock:(void(^)(NSDictionary<NSString *,id> * dict))completeBlock andAsset:(PHAsset *)asset{\n    PHImageRequestOptions *options = [PHImageRequestOptions new];\n    options.networkAccessAllowed = YES;\n    options.synchronous = NO;\n    options.version = PHImageRequestOptionsVersionOriginal;\n    PHImageManager *manager = [[PHImageManager alloc] init];\n\n    [manager requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info){\n        CIImage *image = [CIImage imageWithData:imageData];\n\n        NSMutableDictionary *editingDictionary = [image.properties mutableCopy];\n        if ([info objectForKey:@\"PHImageFileURLKey\"]) {\n            NSURL *path = [info objectForKey:@\"PHImageFileURLKey\"];\n            [editingDictionary setObject:[path absoluteString] forKey:@\"fileUrl\"];\n        }\n        \n        completeBlock(editingDictionary);\n    }];\n}\n\n+(void)updateAssetWithParams:(NSDictionary *)params completionBlock:(void(^)(BOOL success, NSError * _Nullable error, NSString * _Nullable localIdentifier))completionBlock andAsset:(PHAsset *)asset {\n    if(!params || !asset) {\n        return completionBlock(NO, [NSError errorWithDomain:@\"react-native-photos-framework\" code:1 userInfo:@{@\"info\" : @\"[updateAssetWithParams] params or asset was nil\"}], asset.localIdentifier);\n    }\n    BOOL runUpdate = NO;\n    BOOL updateHidden = NO;\n    BOOL updateFavorite = NO;\n    BOOL updateCreationDate = NO;\n    BOOL updateLocation = NO;\n    \n    NSString *hiddenValue = [params objectForKey:@\"hidden\"];\n    BOOL hidden = false;\n    if(hiddenValue) {\n        hidden = [RCTConvert BOOL:params[@\"hidden\"]];\n        if(hidden != asset.hidden) {\n            runUpdate = YES;\n            updateHidden = YES;\n        }\n    }\n    \n    NSString *favoriteValue = [params objectForKey:@\"favorite\"];\n    BOOL favorite = false;\n    if(favoriteValue) {\n        favorite = [RCTConvert BOOL:params[@\"favorite\"]];\n        if(favorite != asset.favorite) {\n            runUpdate = YES;\n            updateFavorite = YES;\n        }\n    }\n    \n    \n    NSString *creationDateValue = [params objectForKey:@\"creationDate\"];\n    NSDate *creationDate = asset.creationDate;\n    if(creationDateValue) {\n        creationDate = [RCTConvert NSDate:creationDateValue];\n        if(creationDate) {\n            runUpdate = YES;\n            updateCreationDate = YES;\n        }\n    }\n    \n    NSDictionary *locationValue = [RCTConvert NSDictionary:params[@\"location\"]];\n    CLLocation *location = asset.location;\n    if(locationValue) {\n        location = [RCTConvert CLLocation:locationValue];\n        if(location) {\n            runUpdate = YES;\n            updateLocation = YES;\n        }\n    }\n    if(!runUpdate) {\n        return completionBlock(YES, nil, asset.localIdentifier);\n    }\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest changeRequestForAsset:asset];\n        if(updateHidden) {\n            assetRequest.hidden = hidden;\n        }\n        if(updateFavorite) {\n            assetRequest.favorite = favorite;\n        }\n        if(updateCreationDate) {\n            assetRequest.creationDate = creationDate;\n        }\n        if(updateLocation) {\n            assetRequest.location = location;\n        }\n    } completionHandler:^(BOOL success, NSError *error) {\n        completionBlock(success, error, asset.localIdentifier);\n    }];\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCache.h",
    "content": "#import \"PHCachedFetchResult.h\"\n#import <Foundation/Foundation.h>\n@import Photos;\n@interface PHCache : NSObject\n\n+ (PHCache *)sharedPHCache;\n-(NSString *) cacheFetchResultAndReturnUUID:(PHFetchResult *)fetchResult andObjectType:(Class)objectType andOrginalFetchParams:(NSDictionary *)params;\n-(NSString *) cacheFetchResultWithUUID:(PHFetchResult *)fetchResult andObjectType:(Class)objectType andUUID:(NSString *)uuid andOrginalFetchParams:(NSDictionary *)params;\n-(PHCachedFetchResult *) getFetchResultFromCacheWithuuid:(NSString *)uuid;\n-(void) removeFetchResultFromCacheWithUUID:(NSString *)uuid;\n-(void) cleanCache;\n\n@property (strong, nonatomic) NSMutableDictionary<NSString *, PHCachedFetchResult *> *fetchResults;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCache.m",
    "content": "#import \"PHCache.h\"\n\n@implementation PHCache\n\n+ (PHCache *)sharedPHCache {\n    static PHCache *sharedPHCache = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedPHCache = [[PHCache alloc] init];\n        sharedPHCache.fetchResults = [[NSMutableDictionary alloc] init];\n    });\n    return sharedPHCache;\n}\n\n-(void) cleanCache {\n    if(self.fetchResults) {\n        self.fetchResults = [[NSMutableDictionary alloc] init];\n    }\n}\n\n-(NSString *) cacheFetchResultAndReturnUUID:(PHFetchResult *)fetchResult andObjectType:(Class)objectType andOrginalFetchParams:(NSDictionary *)params {\n    NSString *uuid = [[NSUUID UUID] UUIDString];\n    @synchronized (self.fetchResults) {\n        [self.fetchResults setObject:[[PHCachedFetchResult alloc] initWithFetchResult:fetchResult andObjectType:objectType andOriginalFetchParams:params] forKey:uuid];\n    }\n    return uuid;\n}\n\n-(NSString *) cacheFetchResultWithUUID:(PHFetchResult *)fetchResult andObjectType:(Class)objectType andUUID:(NSString *)uuid andOrginalFetchParams:(NSDictionary *)params  {\n    @synchronized (self.fetchResults) {\n        [self.fetchResults setObject:[[PHCachedFetchResult alloc] initWithFetchResult:fetchResult andObjectType:objectType andOriginalFetchParams:params] forKey:uuid];\n    }\n    return uuid;\n}\n\n-(void) removeFetchResultFromCacheWithUUID:(NSString *)uuid {\n    @synchronized (self.fetchResults) {\n        [self.fetchResults removeObjectForKey:uuid];\n    }\n}\n\n-(PHCachedFetchResult *) getFetchResultFromCacheWithuuid:(NSString *)uuid {\n    @synchronized (self.fetchResults) {\n        return [self.fetchResults objectForKey:uuid];\n    }\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCachedFetchResult.h",
    "content": "#import <Foundation/Foundation.h>\n@import Photos;\n@interface PHCachedFetchResult : NSObject\n\n- (instancetype)initWithFetchResult:(PHFetchResult *)fetcHResult andObjectType:(Class)objectType andOriginalFetchParams:(NSDictionary *)params;\n\n@property Class objectType;\n@property (strong) PHFetchResult *fetchResult;\n@property (strong) NSDictionary *originalFetchParams;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCachedFetchResult.m",
    "content": "#import \"PHCachedFetchResult.h\"\n\n@implementation PHCachedFetchResult\n- (instancetype)initWithFetchResult:(PHFetchResult *)fetcHResult andObjectType:(Class)objectType andOriginalFetchParams:(NSDictionary *)params\n{\n    self = [super init];\n    if (self) {\n        self.fetchResult = fetcHResult;\n        self.objectType = objectType;\n        self.originalFetchParams = params;\n    }\n    return self;\n}\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCachingImageManagerInstance.h",
    "content": "#import <Foundation/Foundation.h>\n@import Photos;\n\n@interface PHCachingImageManagerInstance : NSObject\n\n+ (PHCachingImageManager *)sharedCachingManager;\n\n@end\n\n\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCachingImageManagerInstance.m",
    "content": "#import \"PHCachingImageManagerInstance.h\"\n\n@implementation PHCachingImageManagerInstance\n\n#pragma mark Singleton Methods\n\n+ (PHCachingImageManager *)sharedCachingManager {\n  static PHCachingImageManager *sharedMyManager = nil;\n  static dispatch_once_t onceToken;\n  dispatch_once(&onceToken, ^{\n    sharedMyManager = [[PHCachingImageManager alloc] init];\n    [sharedMyManager setAllowsCachingHighQualityImages:NO];\n  });\n  return sharedMyManager;\n}\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCancellationToken.h",
    "content": "#import <Foundation/Foundation.h>\n\n@interface PHCancellationToken : NSObject\n\n@property (strong, atomic) NSString* id;\n@property BOOL isCancelled;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCancellationToken.m",
    "content": "#import \"PHCancellationToken.h\"\n\n@implementation PHCancellationToken\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCancellationTokenManager.h",
    "content": "//\n//  PHCancellationTokenManager.h\n//  RNPhotosFramework\n//\n//  Created by Olof Dahlbom on 2017-09-03.\n//  Copyright © 2017 Olof Dahlbom. All rights reserved.\n//\n\n#import \"PHCancellationToken.h\";\n#import <Foundation/Foundation.h>\n\n@interface PHCancellationTokenManager : NSObject\n\n@property (strong, nonatomic) NSArray<PHCancellationToken *> * CancellationTokens;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCancellationTokenManager.m",
    "content": "//\n//  PHCancellationTokenManager.m\n//  RNPhotosFramework\n//\n//  Created by Olof Dahlbom on 2017-09-03.\n//  Copyright © 2017 Olof Dahlbom. All rights reserved.\n//\n\n#import \"PHCancellationTokenManager.h\"\n\n@implementation PHCancellationTokenManager\n\n\n+(instancetype)sharedInstance {\n    \n    static PHCancellationTokenManager *_sharedInstance = nil;\n    static dispatch_once_t onceToken;\n    \n    dispatch_once( &onceToken, ^{\n        _sharedInstance = [PHCancellationTokenManager new];\n    });\n    \n    return _sharedInstance;\n}\n\n-(void) createToken {\n    \n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHChangeObserver.h",
    "content": "#import <Foundation/Foundation.h>\n#import <React/RCTBridge.h>\n#import \"PHCachedFetchResult.h\"\n#import \"PHCachedFetchResult.h\"\n#import <React/RCTEventEmitter.h>\n\n@import Photos;\n@interface PHChangeObserver : NSObject<PHPhotoLibraryChangeObserver>\n- (instancetype)initWithEventEmitter:(RCTEventEmitter *)eventEmitter;\n- (void)removeChangeObserver;\n\n@property (weak, nonatomic) RCTEventEmitter * eventEmitter;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHChangeObserver.m",
    "content": "#import \"PHChangeObserver.h\"\n#import <React/RCTBridge.h>\n#import <React/RCTEventDispatcher.h>\n#import \"PHCachedFetchResult.h\"\n#import \"PHCollectionService.h\"\n#import \"PHAssetsService.h\"\n#import \"PHCache.h\"\n@implementation PHChangeObserver\n\n- (instancetype)initWithEventEmitter:(RCTEventEmitter *)eventEmitter\n{\n    self = [super init];\n    if (self) {\n        self.eventEmitter = eventEmitter;\n        [self setupChangeObserver];\n    }\n    return self;\n}\n\n-(void)setupChangeObserver {\n    [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];\n}\n\n-(void)removeChangeObserver {\n    [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];\n}\n\n- (void)photoLibraryDidChange:(PHChange *)changeInstance {\n    if(changeInstance != nil) {\n\n        NSMutableDictionary<NSString *, PHCachedFetchResult *> *previousFetches = [[PHCache sharedPHCache] fetchResults];\n\n        [previousFetches enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull uuid, PHCachedFetchResult * _Nonnull cachedFetchResult, BOOL * _Nonnull stop) {\n\n            PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:cachedFetchResult.fetchResult];\n\n            if(changeDetails != nil) {\n\n\n                BOOL trackInsertsAndDeletes = [RCTConvert BOOL:cachedFetchResult.originalFetchParams[@\"trackInsertsAndDeletes\"]];\n                BOOL trackChanges = [RCTConvert BOOL:cachedFetchResult.originalFetchParams[@\"trackChanges\"]];\n\n                NSMutableArray *removedLocalIdentifiers = (NSMutableArray *)[NSNull null];\n                NSArray *removedIndexes = (NSArray *)[NSNull null];\n\n                NSMutableArray *insertedObjects = (NSMutableArray *)[NSNull null];\n                NSArray *insertedIndexes = (NSArray *)[NSNull null];\n\n                if(trackInsertsAndDeletes) {\n                    removedLocalIdentifiers = [NSMutableArray arrayWithCapacity:changeDetails.removedObjects.count];\n                    removedIndexes = [self indexSetToReturnableArray:changeDetails.removedIndexes];\n                    for(int i = 0; i < [changeDetails.removedObjects count];i++) {\n                        PHObject *object = (PHObject *)[changeDetails.removedObjects objectAtIndex:i];\n                        if(object) {\n                            [removedLocalIdentifiers addObject:@{\n                                                                 @\"index\" : [removedIndexes objectAtIndex:i],\n                                                                 @\"localIdentifier\" : [object localIdentifier]\n                                                                 }];\n                        }\n                    }\n\n\n                    insertedObjects = [NSMutableArray arrayWithCapacity:changeDetails.insertedObjects.count];\n                    insertedIndexes = [self indexSetToReturnableArray:changeDetails.insertedIndexes];\n                    for(int i = 0; i < [changeDetails.insertedIndexes count];i++) {\n                        PHObject *object = (PHObject *)[changeDetails.insertedObjects objectAtIndex:i];\n                        if([object isKindOfClass:[PHCollection class]]) {\n                            PHCollection *collection = (PHCollection *)object;\n                            NSMutableDictionary *insertedObject = [[[PHCollectionService generateAlbumsResponseFromParams:cachedFetchResult.originalFetchParams andAlbums:(PHFetchResult *)@[collection] andCacheAssets:NO] objectForKey:@\"albums\"]\n                                                                   objectAtIndex:0];\n                            [insertedObjects addObject:@{\n                                                         @\"index\" : [insertedIndexes objectAtIndex:i],\n                                                         @\"obj\" : insertedObject\n                                                         }];\n                        }\n\n                        if([object isKindOfClass:[PHAsset class]]) {\n                            BOOL includeMetadata = [RCTConvert BOOL:cachedFetchResult.originalFetchParams[@\"includeMetadata\"]];\n                            BOOL includeResourcesMetadata = [RCTConvert BOOL:cachedFetchResult.originalFetchParams[@\"includeResourcesMetadata\"]];\n\n                            NSDictionary *insertedObject = [[PHAssetsService assetsArrayToUriArray:@[object] andincludeMetadata:includeMetadata andIncludeAssetResourcesMetadata:includeResourcesMetadata] objectAtIndex:0];\n                            NSNumber *collectionIndex = [insertedIndexes objectAtIndex:i];\n                            NSMutableDictionary *mutableInsertedDict = [insertedObject mutableCopy];\n                            [mutableInsertedDict setObject:collectionIndex forKey:@\"collectionIndex\"];\n                            [insertedObjects addObject:@{\n                                                         @\"index\" : collectionIndex,\n                                                         @\"obj\" : mutableInsertedDict\n                                                         }];\n                        }\n                    }\n                }\n\n                NSMutableArray *changedObjects = (NSMutableArray *)[NSNull null];\n                NSArray *changedIndexes = (NSArray *)[NSNull null];\n                if(trackChanges) {\n                    changedObjects = [NSMutableArray arrayWithCapacity:changeDetails.changedObjects.count];\n                    changedIndexes = [self indexSetToReturnableArray:changeDetails.changedIndexes];\n\n                    for(int i = 0; i < [changeDetails.changedObjects count];i++) {\n                        PHObject *object = (PHObject *)[changeDetails.changedObjects objectAtIndex:i];\n                        if([object isKindOfClass:[PHCollection class]]) {\n                            PHCollection *collection = (PHCollection *)object;\n                            NSMutableDictionary *changedObject = [[[PHCollectionService generateAlbumsResponseFromParams:cachedFetchResult.originalFetchParams andAlbums:(PHFetchResult *)@[collection] andCacheAssets:NO] objectForKey:@\"albums\"] objectAtIndex:0];\n                            [changedObjects addObject:@{\n                                                        @\"index\" : [changedIndexes objectAtIndex:i],\n                                                        @\"obj\" : changedObject\n                                                        }];\n\n                        }\n\n                        if([object isKindOfClass:[PHAsset class]]) {\n\n                            BOOL includeMetadata = [RCTConvert BOOL:cachedFetchResult.originalFetchParams[@\"includeMetadata\"]];\n                            BOOL includeResourcesMetadata = [RCTConvert BOOL:cachedFetchResult.originalFetchParams[@\"includeResourcesMetadata\"]];\n                            NSDictionary *changedObject = [[PHAssetsService assetsArrayToUriArray:@[object] andincludeMetadata:includeMetadata andIncludeAssetResourcesMetadata:includeResourcesMetadata] objectAtIndex:0];\n                            NSNumber *collectionIndex = [changedIndexes objectAtIndex:i];\n                            NSMutableDictionary *mutableChangedDict = [changedObject mutableCopy];\n                            [mutableChangedDict setObject:collectionIndex forKey:@\"collectionIndex\"];\n                            [changedObjects addObject:@{\n                                                        @\"index\" : collectionIndex,\n                                                        @\"obj\" : mutableChangedDict\n                                                        }];\n                        }\n\n                    }\n                }\n\n                if(trackInsertsAndDeletes || trackChanges) {\n                    NSMutableArray *moves = (NSMutableArray *)[NSNull null];\n                    if(changeDetails.hasMoves) {\n                        moves = [NSMutableArray new];\n                        [changeDetails enumerateMovesWithBlock:^(NSUInteger fromIndex, NSUInteger toIndex) {\n                            [moves addObject:@(fromIndex)];\n                            [moves addObject:@(toIndex)];\n                        }];\n                    }\n\n                    BOOL hasMoves = ![moves isEqual:[NSNull null]] && moves.count != 0;\n\n                    BOOL shouldNotifyForInsertOrDelete = ((\n                                                           (![insertedIndexes isEqual:[NSNull null]] && insertedIndexes.count != 0) ||\n                                                           (![removedIndexes isEqual:[NSNull null]] && removedIndexes.count != 0) ||\n                                                           hasMoves) && trackInsertsAndDeletes);\n\n                    BOOL shouldNotifyForChange = ((\n                                                   (![changedIndexes isEqual:[NSNull null]] && changedIndexes.count != 0) ||\n                                                   hasMoves) && trackChanges);\n\n                    if(shouldNotifyForInsertOrDelete || shouldNotifyForChange){\n                        if(self.eventEmitter) {\n                            [self.eventEmitter sendEventWithName:@\"onObjectChange\"\n                                                            body:@{\n                                                                   @\"_cacheKey\": uuid,\n                                                                   @\"type\" : @\"AssetChange\",\n                                                                   @\"removedIndexes\" : removedIndexes,\n                                                                   @\"insertedIndexes\" : insertedIndexes,\n                                                                   @\"changedIndexes\" : changedIndexes,\n                                                                   @\"insertedObjects\" : insertedObjects,\n                                                                   @\"removedObjects\" : removedLocalIdentifiers,\n                                                                   @\"changedObjects\" : changedObjects,\n                                                                   @\"hasIncrementalChanges\" : @(changeDetails.hasIncrementalChanges),\n                                                                   @\"moves\" : moves\n                                                                   }];\n                        }\n\n                        cachedFetchResult.fetchResult = [changeDetails fetchResultAfterChanges];\n                    }\n                }\n\n            }\n        }];\n\n        [self.eventEmitter sendEventWithName:@\"onLibraryChange\"\n                                                body:@{}];\n    }\n\n}\n\n-(NSArray *)indexSetToReturnableArray:(NSIndexSet *)inputIndexSet {\n    NSMutableArray *indexArray = (NSMutableArray *)[NSNull null];\n    if(inputIndexSet) {\n        indexArray = [NSMutableArray arrayWithCapacity:inputIndexSet.count];\n        [inputIndexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {\n            [indexArray addObject:@(idx)];\n        }];\n    }\n    return indexArray;\n}\n\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCollectionService.h",
    "content": "#import <Foundation/Foundation.h>\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n@import Photos;\n@interface PHCollectionService : NSObject\nNS_ASSUME_NONNULL_BEGIN\n\n+(NSMutableDictionary *) getAlbums:(NSDictionary *)params;\n\n+(PHAssetCollection *) getAssetCollectionForParams:(NSDictionary *)params;\n\n+(void) addAssets:(PHFetchResult<PHAsset *> *)assets toAssetCollection:(PHAssetCollection *)assetCollection andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error))completeBlock;\n\n+(void) removeAssets:(PHFetchResult<PHAsset *> *)assets fromAssetCollection:(PHAssetCollection *)assetCollection andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error))completeBlock;\n\n+(PHFetchResult<PHAssetCollection *> *)getUserAlbumsByTitles:(NSArray *)titles withParams:(NSDictionary *)params;\n\n+(NSMutableDictionary *) generateCollectionResponseWithCollections:(PHFetchResult<PHCollection *> *)collections andParams:(NSDictionary *)params;\n\n+(NSMutableDictionary *)generateAlbumsResponseFromParams:(NSDictionary *)params andAlbums:(PHFetchResult<PHCollection *> *)albums andCacheAssets:(BOOL)cacheAssets;\n\n+(void) createAlbumsWithTitles:(NSArray *)titles andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error, NSArray<NSString *> * localIdentifier))completeBlock;\n\n+(void) deleteAlbumsWithLocalIdentifers:(NSArray *)localIdentifiers andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error))completeBlock;\n\n+(void) saveImage:(UIImage *)image toAlbum:(NSString *)albumLocalIdentifier andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error, NSString *__nullable localIdentifier))completeBlock;\n+(PHAssetCollection *) getAssetForLocalIdentifer:(NSString *)localIdentifier;\n\n+(PHFetchResult<PHAssetCollection *> *)getAlbumsWithLocalIdentifiers:(NSArray<NSString *> *)localIdentifiers andParams:(NSDictionary * __nullable)params;\n\nNS_ASSUME_NONNULL_END\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCollectionService.m",
    "content": "#import \"PHCollectionService.h\"\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n#import \"PHFetchOptionsService.h\"\n#import \"PHCache.h\"\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n#import \"RNPFHelpers.h\"\n#import <React/RCTImageLoader.h>\n#import \"PHAssetsService.h\"\n\n@import Photos;\n@implementation PHCollectionService\n\nstatic id ObjectOrNull(id object)\n{\n    return object ?: [NSNull null];\n}\n\n+(PHAssetCollection *) getAssetCollectionForParams:(NSDictionary *)params {\n    NSString * albumLocalIdentifier = [RCTConvert NSString:params[@\"albumLocalIdentifier\"]];\n    if(albumLocalIdentifier) {\n        return [self getAssetForLocalIdentifer:albumLocalIdentifier];\n    }\n    [NSException raise:@\"RNPhotosFramework invalid argument\" format:@\"You need to pass albumLocalIdentifier to retrive a specific album for this operation\"];\n    return nil;\n}\n\n+(PHAssetCollection *) getAssetForLocalIdentifer:(NSString *)localIdentifier {\n    if(localIdentifier == nil) {\n        return nil;\n    }\n    PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[localIdentifier] options:nil];\n    return collections.firstObject;\n}\n\n+(PHFetchResult<PHAssetCollection *> *)getAlbumsWithLocalIdentifiers:(NSArray<NSString *> *)localIdentifiers andParams:(NSDictionary * __nullable)params{\n    PHFetchOptions *fetchOptions = [PHFetchOptionsService getCollectionFetchOptionsFromParams:params];\n    return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:localIdentifiers options:fetchOptions];\n}\n\n+(NSMutableDictionary *) getAlbums:(NSDictionary *)params {\n    PHFetchResult<PHCollection *> *albums = [PHCollectionService getAlbumsWithParams:params];\n    return [PHCollectionService generateCollectionResponseWithCollections:albums andParams:params];\n}\n\n+(PHFetchResult<PHCollection *> *)getAlbumsWithParams:(NSDictionary *)params {\n    NSString * typeString = params[@\"type\"];\n    NSString * subTypeString = params[@\"subType\"];\n    if(typeString == nil && subTypeString == nil) {\n        return [PHCollectionService getTopUserAlbums:params];\n    }\n    PHAssetCollectionType type = [RCTConvert PHAssetCollectionType:typeString];\n    PHAssetCollectionSubtype subType = [RCTConvert PHAssetCollectionSubtype:subTypeString];\n    PHFetchOptions *options = [PHFetchOptionsService getCollectionFetchOptionsFromParams:params];\n    PHFetchResult<PHCollection *> *albums = (PHFetchResult<PHCollection *> *)[PHAssetCollection fetchAssetCollectionsWithType:type subtype:subType options:options];\n    return albums;\n}\n\n+(PHFetchResult<PHCollection *> *)getTopUserAlbums:(NSDictionary *)params\n{\n    PHFetchOptions *options = [PHFetchOptionsService getCollectionFetchOptionsFromParams:params];\n    PHFetchResult<PHCollection *> *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:options];\n    return topLevelUserCollections;\n}\n\n+(PHFetchResult<PHAssetCollection *> *)getUserAlbumsByTitles:(NSArray *)titles withParams:(NSDictionary *)params {\n    PHFetchOptions *fetchOptions = [PHFetchOptionsService getCollectionFetchOptionsFromParams:params];\n    fetchOptions.predicate = [NSPredicate predicateWithFormat:@\"title in %@\", titles];\n    NSString * typeString = params[@\"type\"];\n    NSString * subTypeString = params[@\"subType\"];\n    PHAssetCollectionType type = [RCTConvert PHAssetCollectionType:typeString];\n    PHAssetCollectionSubtype subType = [RCTConvert PHAssetCollectionSubtype:subTypeString];\n    PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:type\n                                                                              subtype:subType\n                                                                              options:fetchOptions];\n    return collections;\n}\n\n\n+(NSMutableDictionary *) generateCollectionResponseWithCollections:(PHFetchResult<PHCollection *> *)collections andParams:(NSDictionary *)params {\n    BOOL trackInsertsAndDeletes = [RCTConvert BOOL:params[@\"trackInsertsAndDeletes\"]];\n    BOOL trackChanges = [RCTConvert BOOL:params[@\"trackChanges\"]];\n    BOOL preCacheAssets = [RCTConvert BOOL:params[@\"preCacheAssets\"]];\n    BOOL shouldCache = trackInsertsAndDeletes || trackChanges;\n    \n    NSMutableDictionary *multipleAlbumsResponse = [PHCollectionService generateAlbumsResponseFromParams:params andAlbums:collections andCacheAssets:preCacheAssets];\n    if(shouldCache) {\n        NSString *uuid = [[PHCache sharedPHCache] cacheFetchResultAndReturnUUID:collections andObjectType:[PHAssetCollection class] andOrginalFetchParams:params];\n        [multipleAlbumsResponse setObject:uuid forKey:@\"_cacheKey\"];\n    }\n    return multipleAlbumsResponse;\n}\n\n+(NSMutableDictionary *)generateAlbumsResponseFromParams:(NSDictionary *)params andAlbums:(PHFetchResult<PHCollection *> *)albums andCacheAssets:(BOOL)cacheAssets {\n    \n    RNPFAssetCountType countType = [RCTConvert RNPFAssetCountType:params[@\"assetCount\"]];\n    int numberOfPreviewAssets = [RCTConvert int:params[@\"previewAssets\"]];\n    BOOL includeMetadata = [RCTConvert BOOL:params[@\"includeMetadata\"]];\n    BOOL includeResourcesMetadata = [RCTConvert BOOL:params[@\"includeResourcesMetadata\"]];\n\n    NSMutableDictionary *collectionDictionary = [NSMutableDictionary new];\n    NSMutableArray *albumsArray = [NSMutableArray arrayWithCapacity:albums.count];\n    \n    //We are going to fetch only for preview items.\n    //Let's set a fetchLimit.\n    NSDictionary *fetchOptions = [RCTConvert NSDictionary:params[@\"assetFetchOptions\"]];\n    NSMutableDictionary *assetFetchParams = [[NSMutableDictionary alloc] init];\n\n    if(!cacheAssets && countType == RNPFAssetCountTypeEstimated && numberOfPreviewAssets > 0) {\n        //If we are not caching the result and the assetCount should only be estimated.\n        //We can set a fetchLimit when getting the previewAssets (Small optimization)\n        NSMutableDictionary *fetchOptionsMutable = [fetchOptions mutableCopy];\n        [fetchOptionsMutable setObject:@(numberOfPreviewAssets) forKey:@\"fetchLimit\"];\n        fetchOptions = fetchOptionsMutable;\n    }\n    if(fetchOptions) {\n        [assetFetchParams setObject:fetchOptions forKey:@\"fetchOptions\"];\n    }\n    \n    \n    for(PHCollection *collection in albums)\n    {\n        NSMutableDictionary *albumDictionary = [self generateAlbumResponseFromCollection:collection numberOfPreviewAssets:numberOfPreviewAssets countType:countType includeMetadata:includeMetadata includeResourcesMetadata:includeResourcesMetadata cacheAssets:cacheAssets assetFetchParams:assetFetchParams];\n            \n        [albumsArray addObject:albumDictionary];\n        \n    }\n    [collectionDictionary setObject:albumsArray forKey:@\"albums\"];\n    return collectionDictionary;\n}\n\n+ (NSMutableDictionary *)generateAlbumResponseFromCollection:(PHCollection *)collection numberOfPreviewAssets:(int)numberOfPreviewAssets countType:(RNPFAssetCountType)countType includeMetadata:(BOOL)includeMetadata includeResourcesMetadata:(BOOL)resourcesMetadata cacheAssets:(BOOL)cacheAssets assetFetchParams:(NSDictionary *)assetFetchParams {\n    \n    NSMutableDictionary *albumDictionary = [NSMutableDictionary new];\n\n    if([collection isKindOfClass:[PHAssetCollection class]]) {\n        PHAssetCollection *phAssetCollection = (PHAssetCollection *)collection;\n        PHAssetCollectionType albumType = [phAssetCollection assetCollectionType];\n        PHAssetCollectionSubtype subType = [phAssetCollection assetCollectionSubtype];\n        [albumDictionary setObject:[[RCTConvert PHAssetCollectionTypeValuesReversed] objectForKey:@(albumType)] forKey:@\"type\"];\n        if(subType == 1000000201) {\n            //Some kind of undocumented value here for recentlyDeleted\n            //Found references to this when i Googled.\n            [albumDictionary setObject:@\"recentlyDeleted\" forKey:@\"subType\"];\n        }else {\n            NSString *subTypeString = [[RCTConvert PHAssetCollectionSubtypeValuesReversed] objectForKey:@(subType)];\n            if(subTypeString != nil) {\n                [albumDictionary setObject:subTypeString forKey:@\"subType\"];\n            }\n        }\n        if(includeMetadata) {\n            [albumDictionary setObject:@([RNPFHelpers getTimeSince1970:phAssetCollection.startDate])forKey:@\"startDate\"];\n            [albumDictionary setObject:@([RNPFHelpers getTimeSince1970:phAssetCollection.endDate]) forKey:@\"endDate\"];\n            [albumDictionary setObject:[RNPFHelpers CLLocationToJson:phAssetCollection.approximateLocation] forKey:@\"approximateLocation\"];\n            [albumDictionary setObject:ObjectOrNull(phAssetCollection.localizedLocationNames) forKey:@\"localizedLocationNames\"];\n        }\n        if(countType == RNPFAssetCountTypeEstimated) {\n            NSUInteger estimatedAssetCount = [phAssetCollection estimatedAssetCount];\n            if(NSNotFound == estimatedAssetCount) {\n                [albumDictionary setObject:@(-1) forKey:@\"assetCount\"];\n            }else {\n                [albumDictionary setObject:@(estimatedAssetCount) forKey:@\"assetCount\"];\n            }\n        }\n        \n        if(cacheAssets || numberOfPreviewAssets > 0 || countType == RNPFAssetCountTypeExact) {\n            \n            PHFetchResult<PHAsset *> * assets = [PHCollectionService getAssetForCollection:phAssetCollection andFetchParams:assetFetchParams];\n            \n            if(cacheAssets) {\n                NSString *uuid = [[PHCache sharedPHCache] cacheFetchResultAndReturnUUID:assets andObjectType:[PHAsset class] andOrginalFetchParams:assetFetchParams];\n                [albumDictionary setObject:uuid forKey:@\"_cacheKey\"];\n            }\n            \n            if(countType == RNPFAssetCountTypeExact) {\n                [albumDictionary setObject:@(assets.count) forKey:@\"assetCount\"];\n            }\n            \n            if(numberOfPreviewAssets > 0) {\n                BOOL assetDisplayStartToEnd = [RCTConvert BOOL:assetFetchParams[@\"assetDisplayStartToEnd\"]];\n                BOOL assetDisplayBottomUp = [RCTConvert BOOL:assetFetchParams[@\"assetDisplayBottomUp\"]];\n                NSArray<NSDictionary *> *previewAssets = [PHAssetsService assetsArrayToUriArray:[PHAssetsService getAssetsForFetchResult:assets startIndex:0 endIndex:(numberOfPreviewAssets-1) assetDisplayStartToEnd:assetDisplayStartToEnd andAssetDisplayBottomUp:assetDisplayBottomUp] andincludeMetadata:NO andIncludeAssetResourcesMetadata:resourcesMetadata];\n                [albumDictionary setObject:previewAssets forKey:@\"previewAssets\"];\n            }\n            \n        }\n    }\n\n    [albumDictionary setObject:collection.localizedTitle forKey:@\"title\"];\n    [albumDictionary setObject:collection.localIdentifier forKey:@\"localIdentifier\"];\n    \n    NSMutableArray *permittedOperations = [NSMutableArray arrayWithCapacity:7];\n    for(int i = 1; i <= 7; i++) {\n        [permittedOperations addObject:@([collection canPerformEditOperation:i])];\n    }\n    [albumDictionary setObject:permittedOperations forKey:@\"permittedOperations\"];\n    return albumDictionary;\n}\n\n+(PHFetchResult<PHAsset *> *) getAssetForCollection:(PHAssetCollection *)collection andFetchParams:(NSDictionary *)params {\n    PHFetchOptions *options = [PHFetchOptionsService getAssetFetchOptionsFromParams:params];\n    return  [PHAsset fetchAssetsInAssetCollection:collection options:options];\n}\n\n\n+(void) createAlbumsWithTitles:(NSArray *)titles andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error, NSArray<NSString *> * localIdentifiers))completeBlock {\n    __block NSMutableArray<PHObjectPlaceholder *> *placeholders = [NSMutableArray arrayWithCapacity:titles.count];\n    \n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        \n        for(int i = 0; i < titles.count; i++) {\n            NSString *title = [titles objectAtIndex:i];\n            PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];\n            [placeholders addObject:[createAlbum placeholderForCreatedAssetCollection]];\n        }\n    } completionHandler:^(BOOL success, NSError *error) {\n        NSMutableArray *arrayWithLocalIdentifiers = [NSMutableArray arrayWithCapacity:placeholders.count];\n        for(int i = 0; i < placeholders.count; i++) {\n            PHObjectPlaceholder *placeHolder = [placeholders objectAtIndex:i];\n            [arrayWithLocalIdentifiers addObject:placeHolder.localIdentifier];\n        }\n        completeBlock(success, error, arrayWithLocalIdentifiers);\n    }];\n}\n\n+(void) deleteAlbumsWithLocalIdentifers:(NSArray *)localIdentifiers andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error))completeBlock {\n    PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:localIdentifiers options:nil];\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        [PHAssetCollectionChangeRequest deleteAssetCollections:collections];\n    } completionHandler:^(BOOL success, NSError *error) {\n        completeBlock(success, error);\n    }];\n}\n\n+(void) addAssets:(PHFetchResult<PHAsset *> *)assets toAssetCollection:(PHAssetCollection *)assetCollection andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error))completeBlock {\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];\n        [albumChangeRequest addAssets:assets];\n        \n    } completionHandler:^(BOOL success, NSError *error) {\n        completeBlock(success, error);\n    }];\n}\n\n+(void) removeAssets:(PHFetchResult<PHAsset *> *)assets fromAssetCollection:(PHAssetCollection *)assetCollection andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error))completeBlock {\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];\n        [albumChangeRequest removeAssets:assets];\n        \n    } completionHandler:^(BOOL success, NSError *error) {\n        completeBlock(success, error);\n    }];\n}\n\n+(void) saveImage:(UIImage *)image toAlbum:(NSString *)albumLocalIdentfier andCompleteBLock:(nullable void(^)(BOOL success, NSError *__nullable error, NSString *__nullable localIdentifier))completeBlock {\n    __block PHObjectPlaceholder *placeholder;\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n    \n        PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];\n        placeholder = [assetRequest placeholderForCreatedAsset];\n        \n        if(albumLocalIdentfier != nil) {\n            PHAssetCollection *album = [PHCollectionService getAssetForLocalIdentifer:albumLocalIdentfier];\n            PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];\n            [albumChangeRequest addAssets:@[placeholder]];\n            \n        }\n    } completionHandler:^(BOOL success, NSError *error) {\n        completeBlock(success, error, placeholder.localIdentifier);\n    }];\n}\n\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCreateMediaQueue.h",
    "content": "//\n//  PHCreateMediaQueue.h\n//  RNPhotosFramework\n//\n//  Created by Olof Dahlbom on 2017-01-12.\n//  Copyright © 2017 Olof Dahlbom. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface PHCreateMediaQueue : NSObject\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHCreateMediaQueue.m",
    "content": "//\n//  PHCreateMediaQueue.m\n//  RNPhotosFramework\n//\n//  Created by Olof Dahlbom on 2017-01-12.\n//  Copyright © 2017 Olof Dahlbom. All rights reserved.\n//\n\n#import \"PHCreateMediaQueue.h\"\n\n@implementation PHCreateMediaQueue\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHFetchOptionsService.h",
    "content": "#import <Foundation/Foundation.h>\n@import Photos;\n@interface PHFetchOptionsService : NSObject\n+(PHFetchOptions *)getAssetFetchOptionsFromParams:(NSDictionary *)params;\n+(PHFetchOptions *)getCollectionFetchOptionsFromParams:(NSDictionary *)params;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHFetchOptionsService.m",
    "content": "#import \"PHFetchOptionsService.h\"\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n@import Photos;\n@implementation PHFetchOptionsService\n\n+(PHFetchOptions *)getCommonFetchOptionsFromParams:(NSDictionary *)params andFetchOptions:(PHFetchOptions *)options {\n    if ([options respondsToSelector:@selector(includeAssetSourceTypes)]) {\n        // not available in iOS 8\n        options.includeAssetSourceTypes = [RCTConvert PHAssetSourceTypes:params[@\"sourceTypes\"]];\n    }\n    options.includeHiddenAssets = [RCTConvert BOOL:params[@\"includeHiddenAssets\"]];\n    options.includeAllBurstAssets = [RCTConvert BOOL:params[@\"includeAllBurstAssets\"]];\n    options.fetchLimit = [RCTConvert int:params[@\"fetchLimit\"]];\n    options.wantsIncrementalChangeDetails = YES;\n    BOOL disableChangeTracking = [RCTConvert BOOL:params[@\"disableChangeTracking\"]];\n    if(disableChangeTracking) {\n        options.wantsIncrementalChangeDetails = NO;\n    }\n    options.predicate = [PHFetchOptionsService getPredicate:params];\n    options.sortDescriptors = [self getSortDescriptorsFromParams:params];\n    return options;\n}\n\n+(PHFetchOptions *)getAssetFetchOptionsFromParams:(NSDictionary *)outerParams {\n    if(outerParams == nil) {\n        return nil;\n    }\n    NSDictionary *params = [RCTConvert NSDictionary:outerParams[@\"fetchOptions\"]];\n    PHFetchOptions *options = [[PHFetchOptions alloc] init];\n    options = [self getCommonFetchOptionsFromParams:params andFetchOptions:options];\n    return options;\n}\n\n+(PHFetchOptions *)getCollectionFetchOptionsFromParams:(NSDictionary *)outerParams {\n    if(outerParams == nil) {\n        return nil;\n    }\n    NSDictionary *params = [RCTConvert NSDictionary:outerParams[@\"fetchOptions\"]];\n    PHFetchOptions *options = [[PHFetchOptions alloc] init];\n    options = [self getCommonFetchOptionsFromParams:params andFetchOptions:options];\n    if(options.sortDescriptors == nil || options.sortDescriptors.count == 0) {\n        options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@\"title\" ascending:YES]];\n    }\n    return options;\n}\n\n+(NSArray<NSSortDescriptor *> *)getSortDescriptorsFromParams:(NSDictionary *)params {\n    NSArray *sortDescriptors = [RCTConvert NSArray:params[@\"sortDescriptors\"]];\n    if(sortDescriptors == nil || sortDescriptors.count == 0) {\n        return nil;\n    }\n    NSMutableArray<NSSortDescriptor *> *nsSortDescriptors = [NSMutableArray arrayWithCapacity:sortDescriptors.count];\n    for(int i = 0; i < sortDescriptors.count; i++) {\n        NSDictionary *sortDescriptorObj = [RCTConvert NSDictionary:[sortDescriptors objectAtIndex:i]];\n        BOOL sortAscending = [RCTConvert BOOL:sortDescriptorObj[@\"ascending\"]];\n        NSString *sortDescriptorKey = [RCTConvert NSString:sortDescriptorObj[@\"key\"]];\n        if(sortDescriptorKey != nil) {\n            [nsSortDescriptors addObject:[NSSortDescriptor sortDescriptorWithKey:sortDescriptorKey ascending:sortAscending]];\n        }\n    }\n    return nsSortDescriptors;\n}\n\n+(NSPredicate *) getCustomPredicatesForParams:(NSDictionary *)params {\n    NSArray *customPredicates = [RCTConvert NSArray:params[@\"customPredicates\"]];\n    if(customPredicates == nil || customPredicates.count == 0) {\n        return nil;\n    }\n    NSMutableArray<NSPredicate *> *nsPredicates = [NSMutableArray arrayWithCapacity:customPredicates.count];\n    for(int i = 0; i < customPredicates.count; i++) {\n        NSDictionary *predicateObj = [RCTConvert NSDictionary:[customPredicates objectAtIndex:i]];\n        NSString *predicate = [predicateObj objectForKey:@\"predicate\"];\n        if(predicate != nil) {\n            NSString *argument = [predicateObj objectForKey:@\"predicateArg\"];\n            [nsPredicates addObject:[NSPredicate predicateWithFormat:predicate, argument]];\n        }\n    }\n    return [NSCompoundPredicate andPredicateWithSubpredicates:nsPredicates];\n\n}\n\n+(PHFetchOptions *)extendWithDefaultsForAssets:(PHFetchOptions *)phFetchOptions {\n    return nil;\n}\n\n+(NSPredicate *) getPredicate:(NSDictionary *)params  {\n    NSPredicate *mediaTypePredicate = [PHFetchOptionsService getMediaTypePredicate:params];\n    NSPredicate *subTypePredicate = [PHFetchOptionsService getMediaSubTypePredicate:params];\n    NSPredicate *customPredicate = [PHFetchOptionsService getCustomPredicatesForParams:params];\n    NSPredicate *creationDatePredicate = [PHFetchOptionsService getCreationDatePredicate:params];\n    NSMutableArray *arrayWithPredicates = [NSMutableArray arrayWithCapacity:4];\n    if(mediaTypePredicate) {\n        [arrayWithPredicates addObject:mediaTypePredicate];\n    }\n    if(subTypePredicate) {\n        [arrayWithPredicates addObject:subTypePredicate];\n    }\n    if(customPredicate) {\n        [arrayWithPredicates addObject:customPredicate];\n    }\n    if(creationDatePredicate) {\n        [arrayWithPredicates addObject:creationDatePredicate];\n    }\n    return [NSCompoundPredicate andPredicateWithSubpredicates:arrayWithPredicates];\n}\n\n+(NSPredicate *) getMediaTypePredicate:(NSDictionary *)params {\n    NSArray<NSNumber *> * mediaTypes = [RCTConvert PHAssetMediaTypes:params[@\"mediaTypes\"]];\n    if(mediaTypes == nil) {\n        return nil;\n    }\n    return [NSPredicate predicateWithFormat:@\"mediaType in %@\", mediaTypes];\n}\n\n+(NSPredicate *) getMediaSubTypePredicate:(NSDictionary *)params {\n    NSMutableArray * mediaSubTypes = [RCTConvert PHAssetMediaSubtypes:params[@\"mediaSubTypes\"]];\n    if(mediaSubTypes == nil) {\n        return nil;\n    }\n    NSMutableArray *arrayWithPredicates = [NSMutableArray arrayWithCapacity:mediaSubTypes.count];\n    \n    for(int i = 0; i < mediaSubTypes.count;i++) {\n        PHAssetMediaSubtype mediaSubType = [[mediaSubTypes objectAtIndex:i] intValue];\n        [arrayWithPredicates addObject:[NSPredicate predicateWithFormat:@\"((mediaSubtype & %d) == %d)\", mediaSubType, mediaSubType]];\n    }\n    \n    return [NSCompoundPredicate orPredicateWithSubpredicates:arrayWithPredicates];\n}\n\n+(NSPredicate *) getCreationDatePredicate:(NSDictionary *)params {\n    NSString * olderThan = [RCTConvert NSString:params[@\"olderThan\"]];\n    if(olderThan == nil) {\n        return nil;\n    }\n    NSNumberFormatter *f = [[NSNumberFormatter alloc] init];\n    f.numberStyle = NSNumberFormatterDecimalStyle;\n    NSNumber * timestamp = [f numberFromString:olderThan];\n    if(timestamp == nil) {\n        return nil;\n    }\n    NSDate * date = [NSDate dateWithTimeIntervalSince1970:timestamp.doubleValue / 1000];\n    if(date == nil) {\n        return nil;\n    }\n    return [NSPredicate predicateWithFormat:@\"creationDate < %@\", date];\n}\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHOperationResult.h",
    "content": "#import <Foundation/Foundation.h>\n\n@interface PHOperationResult : NSObject\n\n- (instancetype)initWithLocalIdentifier:(NSString *)localIdentifier andSuccess:(BOOL)success andError:(NSError *)error;\n\n@property (strong, nonatomic) NSString *localIdentifier;\n@property (strong, nonatomic) NSError *error;\n@property (assign, nonatomic) BOOL success;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHOperationResult.m",
    "content": "#import \"PHOperationResult.h\"\n\n@implementation PHOperationResult\n- (instancetype)initWithLocalIdentifier:(NSString *)localIdentifier andSuccess:(BOOL)success andError:(NSError *)error\n{\n    self = [super init];\n    if (self) {\n        self.localIdentifier = localIdentifier;\n        self.success = success;\n        self.error = error;\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAsset.h",
    "content": "#import <Foundation/Foundation.h>\n\n@interface PHSaveAsset : NSObject\n@property (strong, nonatomic) NSString *uri;\n@property (strong, nonatomic) NSString *type;\n@property BOOL isAsset;\n@property BOOL isNetwork;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAsset.m",
    "content": "#import \"PHSaveAsset.h\"\n\n@implementation PHSaveAsset\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAssetFileRequest.h",
    "content": "#import <Foundation/Foundation.h>\n@import Photos;\n\n@interface PHSaveAssetFileRequest : NSObject\n@property (strong, nonatomic) NSURLRequest *uri;\n@property (strong, nonatomic) NSString *uriString;\n\n@property (strong, nonatomic) NSString *localIdentifier;\n@property (strong, nonatomic) NSString *mediaType;\n\n@property (strong, nonatomic) NSString *fileName;\n@property (strong, nonatomic) NSString *dir;\n\n@property (strong, nonatomic) NSDictionary *loadOptions;\n@property (strong, nonatomic) NSDictionary *postProcessOptions;\n\n\n\n//Only used for videos:\n@property (strong, nonatomic) PHVideoRequestOptions* videoRequestOptions;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAssetFileRequest.m",
    "content": "#import \"PHSaveAssetFileRequest.h\"\n\n@implementation PHSaveAssetFileRequest\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAssetRequest.h",
    "content": "#import <Foundation/Foundation.h>\n#import \"PHSaveAsset.h\"\n@interface PHSaveAssetRequest : NSObject\n@property (strong, nonatomic) NSString *type;\n@property (strong, nonatomic) PHSaveAsset *source;\n@end\n\n\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAssetRequest.m",
    "content": "#import \"PHSaveAssetRequest.h\"\n\n@implementation PHSaveAssetRequest\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAssetToFileOperationResult.h",
    "content": "#import <Foundation/Foundation.h>\n#import \"PHOperationResult.h\"\n\n@interface PHSaveAssetToFileOperationResult : PHOperationResult\n\n- (instancetype)initWithLocalIdentifier:(NSString *)localIdentifier fileUrl:(NSString *)fileUrl andSuccess:(BOOL)success andError:(NSError *)error;\n\n@property (strong, nonatomic) NSString *fileUrl;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHSaveAssetToFileOperationResult.m",
    "content": "#import \"PHSaveAssetToFileOperationResult.h\"\n\n@implementation PHSaveAssetToFileOperationResult\n\n- (instancetype)initWithLocalIdentifier:(NSString *)localIdentifier fileUrl:(NSString *)fileUrl andSuccess:(BOOL)success andError:(NSError *)error\n{\n    self = [super initWithLocalIdentifier:localIdentifier andSuccess:success andError:error];\n    if (self) {\n        self.fileUrl = fileUrl;\n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHVideoExporter.h",
    "content": "#import <Foundation/Foundation.h>\n#import \"SDAVAssetExportSession.h\"\n\n@interface PHVideoExporter : NSObject\n\ntypedef void (^videoExporterCompleteBlock)(BOOL success, NSError *__nullable error, NSURL  * __nullable fileUrl);\ntypedef void (^videoExporterProgressBlock)(float progress);\n\n-(void (^_Nonnull)()) exportVideoWithAsset:(AVAsset *_Nonnull)avasset andDir:(NSString *_Nonnull)dir andFileName:(NSString *_Nonnull)fileName andPostProcessParams:(NSDictionary *_Nullable)params andProgressBlock:(videoExporterProgressBlock _Nonnull )progressBlock andCompletionBlock:(videoExporterCompleteBlock _Nonnull )completeBlock;\n\n@property (nonatomic, copy) videoExporterProgressBlock _Nonnull progressBlock;\n@property (strong, nonatomic) SDAVAssetExportSession * _Nullable encoder;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/PHVideoExporter.m",
    "content": "#import \"PHVideoExporter.h\"\n#import <React/RCTConvert.h>\n@implementation PHVideoExporter\n\n-(void (^_Nonnull)()) exportVideoWithAsset:(AVAsset *_Nonnull)avasset andDir:(NSString *)dir andFileName:(NSString *_Nonnull)fileName andPostProcessParams:(NSDictionary *_Nullable)params andProgressBlock:(videoExporterProgressBlock _Nonnull )progressBlock andCompletionBlock:(videoExporterCompleteBlock _Nonnull )completeBlock {\n    \n    __block NSString *fullFileName = [dir stringByAppendingPathComponent:fileName];\n    __block NSString *tempFileName = [dir stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]];\n    __block NSURL *tempUrl = [NSURL fileURLWithPath:tempFileName];\n\n    if(params == nil) {\n        params = [NSDictionary new];\n    }\n    self.progressBlock = progressBlock;\n    \n    NSString *outputFileType = [RCTConvert NSString:params[@\"outputFileType\"]];\n    if(outputFileType == nil) {\n        outputFileType = AVFileTypeMPEG4;\n    }\n    \n    NSString *codecKey = [RCTConvert NSString:params[@\"codecKey\"]];\n    if(codecKey == nil) {\n        codecKey = AVVideoCodecH264;\n    }\n    \n    NSString *profileLevelKey = [RCTConvert NSString:params[@\"profileLevelKey\"]];\n    if(profileLevelKey == nil) {\n        profileLevelKey = AVVideoProfileLevelH264HighAutoLevel;\n    }\n    \n    \n    AVAssetTrack *track = [[avasset tracksWithMediaType:AVMediaTypeVideo] firstObject];\n\n    int width = [RCTConvert int:params[@\"width\"]];\n    int height = [RCTConvert int:params[@\"height\"]];\n\n    if(width < 0.1 || height < 0.1) {\n        CGSize dimensions = CGSizeApplyAffineTransform(track.naturalSize, track.preferredTransform);\n        width = (int)dimensions.width;\n        height = (int)dimensions.height;\n    }\n    \n    \n    float bitrateMultiplier = [RCTConvert float:params[@\"bitrateMultiplier\"]];\n    float minimumBitrate = [RCTConvert float:params[@\"minimumBitrate\"]];\n\n    if(bitrateMultiplier < 0.01) {\n        bitrateMultiplier = 1;\n    }\n    float bps = track.estimatedDataRate;\n\n    float averageBitrate = bps / bitrateMultiplier;\n    if (minimumBitrate > 0.01) {\n        if (averageBitrate < minimumBitrate) {\n            averageBitrate = minimumBitrate;\n        }\n        if (bps < minimumBitrate) {\n            averageBitrate = bps;\n        }\n    }\n\n    self.encoder = [SDAVAssetExportSession.alloc initWithAsset:avasset];\n    \n    [_encoder addObserver:self forKeyPath:@\"progress\" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];\n    \n    \n    _encoder.outputFileType = outputFileType;\n    _encoder.outputURL = tempUrl;\n    _encoder.shouldOptimizeForNetworkUse = YES;\n\n    _encoder.videoSettings = @\n    {\n    AVVideoCodecKey: codecKey,\n    AVVideoWidthKey: @(width),\n    AVVideoHeightKey: @(height),\n    AVVideoCompressionPropertiesKey: @\n        {\n        AVVideoAverageBitRateKey: @(averageBitrate),\n        AVVideoProfileLevelKey: profileLevelKey,\n        },\n    };\n    _encoder.audioSettings = @\n    {\n    AVFormatIDKey: @(kAudioFormatMPEG4AAC),\n    AVNumberOfChannelsKey: @2,\n    AVSampleRateKey: @44100,\n    AVEncoderBitRateKey: @128000,\n    };\n    \n    @try {\n        [_encoder exportAsynchronouslyWithCompletionHandler:^\n         {\n             if (_encoder.status == AVAssetExportSessionStatusCompleted)\n             {\n                 NSError *error;\n                 if ([[NSFileManager defaultManager] fileExistsAtPath:fullFileName] && [[NSFileManager defaultManager] isDeletableFileAtPath:fullFileName]) {\n                     BOOL success = [[NSFileManager defaultManager] removeItemAtPath:fullFileName error:&error];\n                     if (!success) {\n                         NSLog(@\"Error removing file at path: %@\", error.localizedDescription);\n                     }\n                 }\n                 \n                 [[NSFileManager defaultManager] moveItemAtPath:tempFileName toPath:fullFileName error:&error];\n                 \n                 if(error != nil) {\n                    completeBlock(NO, error, nil);\n\n                 }else {\n                     completeBlock(YES, nil, [NSURL URLWithString:fullFileName]);\n                 }\n             }\n             else if (_encoder.status == AVAssetExportSessionStatusCancelled)\n             {\n                 completeBlock(NO, nil, nil);\n             }\n             else\n             {\n                 completeBlock(NO, _encoder.error, nil);\n             }\n             [_encoder removeObserver:self forKeyPath:@\"progress\"];\n\n    }];\n    } @catch (NSException *exception) {\n        completeBlock(NO, nil, nil);\n        [_encoder removeObserver:self forKeyPath:@\"progress\"];\n\n    }\n\n    return ^{\n        [_encoder cancelExport];\n    };\n}\n\n-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context\n{\n    if([keyPath isEqualToString:@\"progress\"]){\n        NSNumber * newValue = [change objectForKey:NSKeyValueChangeNewKey];\n        if(self.progressBlock) {\n            self.progressBlock(newValue.floatValue);\n        }\n    }\n}\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RCTConvert+RNPhotosFramework.h",
    "content": "#import <Foundation/Foundation.h>\n#import \"PHSaveAssetRequest.h\"\n#import \"RNPFHelpers.h\"\n#import \"PHSaveAssetFileRequest.h\"\n\n@import Photos;\n\ntypedef NS_ENUM(NSInteger, RNPFAssetCountType) {\n    RNPFAssetCountTypeEstimated = 1,\n    RNPFAssetCountTypeExact = 2,\n};\n\n@interface RCTConvert(ReactNativePhotosFramework)\n\n+ (RNPFAssetCountType)RNPFAssetCountType:(id)json;\n+ (PHAssetMediaType)PHAssetMediaType:(id)json;\n+ (PHAssetMediaSubtype)PHAssetMediaSubtype:(id)json;\n+ (PHAssetCollectionType)PHAssetCollectionType:(id)json;\n+ (PHAssetCollectionSubtype)PHAssetCollectionSubtype:(id)json;\n+ (PHAssetSourceType)PHAssetSourceType:(id)json;\n+ (PHAuthorizationStatus)PHAuthorizationStatus:(id)json;\n+ (PHAssetResourceType)PHAssetResourceType:(id)json;\n\n\n+ (NSArray<NSNumber *> *)PHAssetMediaTypes:(NSArray<NSString *> *)arrayWithMediaTypeStrings;\n+ (NSMutableArray * ) PHAssetMediaSubtypes:(NSArray<NSString *> *)arrayWithSubMediaTypeStrings;\n+ (int) PHAssetSourceTypes:(NSArray<NSString *> *)arrayWithSourceTypeStrings;\n\n+ (PHSaveAssetRequest *)PHSaveAssetRequest:(id)json;\n+ (NSArray<PHSaveAssetRequest *> *)PHSaveAssetRequestArray:(id)json;\n\n+ (PHSaveAssetFileRequest *)PHSaveAssetFileRequest:(id)json;\n+ (NSArray<PHSaveAssetFileRequest *> *)PHSaveAssetFileRequestArray:(id)json;\n\n+ (NSDictionary *)RNPFAssetCountTypeValuesReversed;\n+ (NSDictionary *)PHAssetMediaTypeValuesReversed;\n+ (NSDictionary *)PHAssetMediaSubtypeValuesReversed;\n+ (NSDictionary *)PHAssetBurstSelectionTypeValuesReversed;\n+ (NSDictionary *)PHAssetSourceTypeValuesReversed;\n+ (NSDictionary *)PHAssetCollectionTypeValuesReversed;\n+ (NSDictionary *)PHAssetCollectionSubtypeValuesReversed;\n+ (NSDictionary *)PHAuthorizationStatusValuesReversed;\n+ (NSDictionary *)PHAssetResourceTypeValuesReversed;\n\n+ (CLLocation *)CLLocation:(id)json;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RCTConvert+RNPhotosFramework.m",
    "content": "#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n\n@import Photos;\n@implementation RCTConvert(ReactNativePhotosFramework)\n\n//We want to be able to reverse the enum. From ENUM => String.\n//So we extend the built in RCT_ENUM_CONVERTER-macro\n#define RCT_ENUM_CONVERTER_WITH_REVERSED(type, values, default, getter) \\\n+ (type)type:(id)json                                     \\\n{                                                         \\\nstatic NSDictionary *mapping;                           \\\nstatic dispatch_once_t onceToken;                       \\\ndispatch_once(&onceToken, ^{                            \\\nmapping = values;                                     \\\n});                                                     \\\nreturn [RCTConvertEnumValue(#type, mapping, @(default), json) getter]; \\\n}                                                        \\\n+ (NSDictionary *)type##ValuesReversed                        \\\n{                                                         \\\n    static NSDictionary *mapping;                           \\\n    static dispatch_once_t onceToken;                       \\\n    dispatch_once(&onceToken, ^{                            \\\n        NSArray *keys = values.allKeys;                     \\\n        NSArray *valuesArray = [values objectsForKeys:keys notFoundMarker:[NSNull null]];    \\\n        mapping = [NSDictionary dictionaryWithObjects:keys forKeys:valuesArray];\\\n    });                                                     \\\n    return mapping;                                         \\\n}\n\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAuthorizationStatus, (@{\n                                                           @\"notDetermined\" : @(PHAuthorizationStatusNotDetermined),\n                                                           @\"restricted\" : @(PHAuthorizationStatusRestricted),\n                                                           @\"denied\" : @(PHAuthorizationStatusDenied),\n                                                           @\"authorized\" : @(PHAuthorizationStatusAuthorized)\n                                                        }), PHAuthorizationStatusNotDetermined, integerValue)\n\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(RNPFAssetCountType, (@{\n                                                        @\"estimated\": @(RNPFAssetCountTypeEstimated),\n                                                        @\"exact\": @(RNPFAssetCountTypeExact)\n                                                        }), RNPFAssetCountTypeEstimated, integerValue)\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetBurstSelectionType, (@{\n                                                        @\"none\": @(PHAssetBurstSelectionTypeNone),\n                                                        @\"autoPick\": @(PHAssetBurstSelectionTypeAutoPick),\n                                                        @\"userPick\": @(PHAssetBurstSelectionTypeUserPick)\n                                                        }), PHAssetBurstSelectionTypeNone, integerValue)\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetMediaType, (@{\n                                        @\"image\": @(PHAssetMediaTypeImage),\n                                        @\"video\": @(PHAssetMediaTypeVideo),\n                                        @\"audio\": @(PHAssetMediaTypeAudio),\n                                        @\"unknown\": @(PHAssetMediaTypeUnknown)\n                                        \n                                        }), PHAssetMediaTypeImage, integerValue)\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetMediaSubtype, (@{\n                                           @\"none\": @(PHAssetMediaSubtypeNone),\n                                           @\"photoPanorama\": @(PHAssetMediaSubtypePhotoPanorama),\n                                           @\"photoHDR\": @(PHAssetMediaSubtypePhotoHDR),\n                                           @\"photoScreenshot\": @(PHAssetMediaSubtypePhotoScreenshot),\n                                           @\"photoLive\": @(PHAssetMediaSubtypePhotoLive),\n                                           @\"videoStreamed\": @(PHAssetMediaSubtypeVideoStreamed),\n                                           @\"videoHighFrameRate\": @(PHAssetMediaSubtypeVideoHighFrameRate),\n                                           @\"videoTimeLapse\": @(PHAssetMediaSubtypeVideoTimelapse),\n                                           @\"photoDepthEffect\": @(PHAssetMediaSubtypePhotoDepthEffect),\n                                           }), PHAssetMediaSubtypeNone, integerValue)\n\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetCollectionType, (@{\n                                             @\"album\": @(PHAssetCollectionTypeAlbum),\n                                             @\"smartAlbum\": @(PHAssetCollectionTypeSmartAlbum),\n                                             @\"moment\": @(PHAssetCollectionTypeMoment)\n                                             \n                                             }), PHAssetCollectionTypeAlbum, integerValue)\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetCollectionSubtype, (@{\n                                                @\"any\" : @(PHCollectionListSubtypeAny),\n                                                @\"albumRegular\": @(PHAssetCollectionSubtypeAlbumRegular),\n                                                @\"syncedEvent\": @(PHAssetCollectionSubtypeAlbumSyncedEvent),\n                                                @\"syncedFaces\": @(PHAssetCollectionSubtypeAlbumSyncedFaces),\n                                                @\"syncedAlbum\": @(PHAssetCollectionSubtypeAlbumSyncedAlbum),\n                                                @\"imported\": @(PHAssetCollectionSubtypeAlbumImported),\n                                                \n                                                @\"albumMyPhotoStream\": @(PHAssetCollectionSubtypeAlbumMyPhotoStream),\n                                                @\"albumCloudShared\": @(PHAssetCollectionSubtypeAlbumCloudShared),\n                                                \n                                                @\"smartAlbumGeneric\": @(PHAssetCollectionSubtypeSmartAlbumGeneric),\n                                                @\"smartAlbumPanoramas\": @(PHAssetCollectionSubtypeSmartAlbumPanoramas),\n                                                @\"smartAlbumVideos\": @(PHAssetCollectionSubtypeSmartAlbumVideos),\n                                                @\"smartAlbumFavorites\": @(PHAssetCollectionSubtypeSmartAlbumFavorites),\n                                                @\"smartAlbumTimelapses\": @(PHAssetCollectionSubtypeSmartAlbumTimelapses),\n                                                @\"smartAlbumAllHidden\": @(PHAssetCollectionSubtypeSmartAlbumAllHidden),\n                                                @\"smartAlbumRecentlyAdded\": @(PHAssetCollectionSubtypeSmartAlbumRecentlyAdded),\n                                                @\"smartAlbumBursts\": @(PHAssetCollectionSubtypeSmartAlbumBursts),\n                                                @\"smartAlbumSlomoVideos\": @(PHAssetCollectionSubtypeSmartAlbumSlomoVideos),\n                                                @\"smartAlbumUserLibrary\": @(PHAssetCollectionSubtypeSmartAlbumUserLibrary),\n                                                @\"smartAlbumSelfPortraits\": @(PHAssetCollectionSubtypeSmartAlbumSelfPortraits),\n                                                @\"smartAlbumScreenshots\": @(PHAssetCollectionSubtypeSmartAlbumScreenshots),\n                                                @\"smartAlbumDepthEffect\" : @(PHAssetCollectionSubtypeSmartAlbumDepthEffect),\n                                                @\"smartAlbumLivePhotos\" : @(PHAssetCollectionSubtypeSmartAlbumLivePhotos)\n                                                \n                                                }), PHCollectionListSubtypeAny, integerValue)\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetSourceType, (@{\n                                         @\"none\": @(PHAssetSourceTypeNone),\n                                         @\"userLibrary\": @(PHAssetSourceTypeUserLibrary),\n                                         @\"cloudShared\": @(PHAssetSourceTypeCloudShared),\n                                         @\"itunesSynced\": @(PHAssetSourceTypeiTunesSynced)\n                                         \n                                         }), PHAssetSourceTypeNone, integerValue)\n\nRCT_ENUM_CONVERTER_WITH_REVERSED(PHAssetResourceType, (@{\n                                                       @\"photo\": @(PHAssetResourceTypePhoto),\n                                                       @\"video\": @(PHAssetResourceTypeVideo),\n                                                       @\"audio\": @(PHAssetResourceTypeAudio),\n                                                       @\"alternatePhoto\": @(PHAssetResourceTypeAlternatePhoto),\n                                                       @\"fullSizePhoto\": @(PHAssetResourceTypeFullSizePhoto),\n                                                       @\"fullSizeVideo\": @(PHAssetResourceTypeFullSizeVideo),\n                                                       @\"adjustmentData\": @(PHAssetResourceTypeAdjustmentData),\n                                                       @\"adjustmentBasePhoto\": @(PHAssetResourceTypeAdjustmentBasePhoto),\n                                                       @\"pairedVideo\": @(PHAssetResourceTypePairedVideo),\n                                                       @\"fullSizePairedVideo\": @(PHAssetResourceTypeFullSizePairedVideo),\n                                                       @\"adjustmentBasePairedVideo\": @(PHAssetResourceTypeAdjustmentBasePairedVideo)\n                                                       \n                                                       }), PHAssetResourceTypePhoto, integerValue)\n\n+ (NSArray<NSNumber *> *)PHAssetMediaTypes:(NSArray<NSString *> *)arrayWithMediaTypeStrings\n{\n    if(arrayWithMediaTypeStrings.count == 0){\n        return nil;\n    }\n    NSMutableArray *arrayWithMediaTypeEnums = [NSMutableArray arrayWithCapacity:arrayWithMediaTypeStrings.count];\n    for(int i = 0; i < arrayWithMediaTypeStrings.count;i++) {\n        PHAssetMediaType mediaType = [RCTConvert PHAssetMediaType:[arrayWithMediaTypeStrings objectAtIndex:i]];\n        [arrayWithMediaTypeEnums addObject:@(mediaType)];\n    }\n    return arrayWithMediaTypeEnums;\n}\n\n+(NSMutableArray * ) PHAssetMediaSubtypes:(NSArray<NSString *> *)arrayWithSubMediaTypeStrings {\n    if(arrayWithSubMediaTypeStrings.count == 0){\n        return nil;\n    }\n    NSMutableArray *arrayWithSubMediaTypes = [NSMutableArray array];\n    for(int i = 0; i < arrayWithSubMediaTypeStrings.count;i++) {\n        PHAssetMediaSubtype mediaSubTyp = [RCTConvert PHAssetMediaSubtype:[arrayWithSubMediaTypeStrings objectAtIndex:i]];\n        [arrayWithSubMediaTypes addObject:[NSNumber numberWithInt:mediaSubTyp]];\n    }\n    return arrayWithSubMediaTypes;\n}\n\n+(int) PHAssetSourceTypes:(NSArray<NSString *> *)arrayWithSourceTypeStrings {\n    if(arrayWithSourceTypeStrings.count == 0){\n        return PHAssetSourceTypeNone;\n    }\n    int sourceTypes = 0;\n    for(int i = 0; i < arrayWithSourceTypeStrings.count;i++) {\n        PHAssetSourceType sourceType = [RCTConvert PHAssetSourceType:[arrayWithSourceTypeStrings objectAtIndex:i]];\n        sourceTypes = sourceTypes | sourceType;\n    }\n    return sourceTypes;\n}\n\n+(PHSaveAsset *)PHSaveAsset:(id)json {\n    PHSaveAsset *asset = [PHSaveAsset new];\n    asset.uri = [RCTConvert NSString:json[@\"uri\"]];\n    asset.type = [RCTConvert NSString:json[@\"type\"]];\n    asset.isNetwork = [RCTConvert BOOL:json[@\"isNetwork\"]];\n    asset.isAsset = [RCTConvert BOOL:json[@\"isAsset\"]];\n    return asset;\n}\n\n+(PHSaveAssetRequest *)PHSaveAssetRequest:(id)json {\n    PHSaveAssetRequest *assetRequest = [PHSaveAssetRequest new];\n    assetRequest.type = [RCTConvert NSString:json[@\"type\"]];\n    assetRequest.source = [RCTConvert PHSaveAsset:json[@\"source\"]];\n    return assetRequest;\n}\n\n+(NSArray<PHSaveAssetRequest *> *)PHSaveAssetRequestArray:(id)json {\n    NSArray *inputArray = [RCTConvert NSArray:json];\n    NSMutableArray *outputArray = [NSMutableArray arrayWithCapacity:inputArray.count];\n    for(int i = 0; i < inputArray.count; i++) {\n        [outputArray addObject:[self PHSaveAssetRequest:[inputArray objectAtIndex:i]]];\n    }\n    return outputArray;\n}\n\n\n+(PHSaveAssetFileRequest *)PHSaveAssetFileRequest:(id)json {\n    PHSaveAssetFileRequest *assetRequest = [PHSaveAssetFileRequest new];\n    assetRequest.uriString = [RCTConvert NSString:json[@\"uri\"]];\n    assetRequest.uri = [RCTConvert NSURLRequest:json[@\"uri\"]];\n    assetRequest.localIdentifier = [RCTConvert NSString:json[@\"localIdentifier\"]];\n    assetRequest.mediaType = [RCTConvert NSString:json[@\"mediaType\"]];\n    assetRequest.fileName = [RCTConvert NSString:json[@\"fileName\"]];\n    assetRequest.dir = [RCTConvert NSString:json[@\"dir\"]];\n    assetRequest.loadOptions = [RCTConvert NSDictionary:json[@\"loadOptions\"]];\n    assetRequest.postProcessOptions = [RCTConvert NSDictionary:json[@\"postProcessOptions\"]];\n\n\n    if(assetRequest.dir == nil) {\n        NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);\n        NSString * basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;\n        assetRequest.dir = basePath;\n    }\n    \n    if([assetRequest.mediaType isEqualToString:@\"video\"]) {\n        assetRequest.videoRequestOptions = [RNPFHelpers getVideoRequestOptionsFromParams:assetRequest.loadOptions];\n    }\n\n    return assetRequest;\n}\n\n+(NSArray<PHSaveAssetFileRequest *> *)PHSaveAssetFileRequestArray:(id)json {\n    NSArray *inputArray = [RCTConvert NSArray:json];\n    NSMutableArray *outputArray = [NSMutableArray arrayWithCapacity:inputArray.count];\n    for(int i = 0; i < inputArray.count; i++) {\n        [outputArray addObject:[self PHSaveAssetFileRequest:[inputArray objectAtIndex:i]]];\n    }\n    return outputArray;\n}\n\n+ (CLLocation *)CLLocation:(id)json {\n    json = [self NSDictionary:json];\n    //Required:\n    double lat = [RCTConvert double:json[@\"lat\"]];\n    double lng = [RCTConvert double:json[@\"lng\"]];\n    \n    //Optional:\n    double altitude = 0;\n    NSString *altitudeValue = json[@\"altitude\"];\n    if(altitudeValue != nil) {\n        altitude = [RCTConvert double:altitudeValue];\n    }\n    \n    double course = 0;\n    NSString *courseValue = json[@\"heading\"];\n    if(courseValue != nil) {\n        course = [RCTConvert double:courseValue];\n    }\n    \n    double speed = 0;\n    NSString *speedValue = json[@\"speed\"];\n    if(speedValue != nil) {\n        speed = [RCTConvert double:speedValue];\n    }\n    \n    NSDate *timeStamp = [NSDate date];\n    NSString *timeStampValue = json[@\"timeStamp\"];\n    if(timeStampValue) {\n        timeStamp = [RCTConvert NSDate:timeStampValue];\n    }\n    \n    return [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(lat, lng) altitude:altitude horizontalAccuracy:0 verticalAccuracy:0 course:course speed:speed timestamp:timeStamp];\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RCTImageResizer.h",
    "content": "#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n@interface RNPFImageResizer : NSObject\n+(void) createResizedImage:(UIImage *)image\n                     width:(float)width\n                    height:(float)height\n                    format:(NSString *)format\n                   quality:(float)quality\n                  rotation:(float)rotation\n                outputPath:(NSString *)outputPath\n                  fileName:(NSString *)fileName\n          andCompleteBLock:(void(^)(NSString *error, NSString *path))completeBlock;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RCTImageResizer.m",
    "content": "#include \"RCTImageResizer.h\"\n#include \"ImageHelpers.h\"\n#import <React/RCTImageLoader.h>\n\n@implementation RNPFImageResizer\n\n\nbool RNPFsaveImage(NSString * fullPath, UIImage * image, NSString * format, float quality)\n{\n    NSData* data = nil;\n    if ([format isEqualToString:@\"JPEG\"]) {\n        data = UIImageJPEGRepresentation(image, quality / 100.0);\n    } else if ([format isEqualToString:@\"PNG\"]) {\n        data = UIImagePNGRepresentation(image);\n    }\n    \n    if (data == nil) {\n        return NO;\n    }\n    \n    [data writeToFile:fullPath atomically:YES];\n    return YES;\n}\n\nNSString * RNPFgenerateFilePath(NSString * ext, NSString *name, NSString * outputPath)\n{\n    NSString* directory;\n\n    if ([outputPath length] == 0) {\n        NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);\n        directory = [paths firstObject];\n    } else {\n        directory = outputPath;\n    }\n    if(name == nil) {\n        name = [[NSUUID UUID] UUIDString];\n    }\n    name = [[name lastPathComponent] stringByDeletingPathExtension];\n    NSString* fullName = [NSString stringWithFormat:@\"%@.%@\", name, ext];\n    NSString* fullPath = [directory stringByAppendingPathComponent:fullName];\n\n    return fullPath;\n}\n\nUIImage * RNPFrotateImage(UIImage *inputImage, float rotationDegrees)\n{\n\n    // We want only fixed 0, 90, 180, 270 degree rotations.\n    const int rotDiv90 = (int)round(rotationDegrees / 90);\n    const int rotQuadrant = rotDiv90 % 4;\n    const int rotQuadrantAbs = (rotQuadrant < 0) ? rotQuadrant + 4 : rotQuadrant;\n    \n    // Return the input image if no rotation specified.\n    if (0 == rotQuadrantAbs) {\n        return inputImage;\n    } else {\n        // Rotate the image by 80, 180, 270.\n        UIImageOrientation orientation = UIImageOrientationUp;\n        \n        switch(rotQuadrantAbs) {\n            case 1:\n                orientation = UIImageOrientationRight; // 90 deg CW\n                break;\n            case 2:\n                orientation = UIImageOrientationDown; // 180 deg rotation\n                break;\n            default:\n                orientation = UIImageOrientationLeft; // 90 deg CCW\n                break;\n        }\n        \n        return [[UIImage alloc] initWithCGImage: inputImage.CGImage\n                                                  scale: 1.0\n                                                  orientation: orientation];\n    }\n}\n\n+(void) createResizedImage:(UIImage *)image\n                  width:(float)width\n                  height:(float)height\n                  format:(NSString *)format\n                  quality:(float)quality\n                  rotation:(float)rotation\n                  outputPath:(NSString *)outputPath\n                  fileName:(NSString *)fileName\n                  andCompleteBLock:(void(^)(NSString *error, NSString *path))completeBlock\n\n{\n    CGSize newSize = CGSizeMake(width, height);\n    NSString* fullPath = RNPFgenerateFilePath(@\"jpg\", fileName, outputPath);\n\n        // Rotate image if rotation is specified.\n        if (0 != (int)rotation) {\n            image = RNPFrotateImage(image, rotation);\n            if (image == nil) {\n                completeBlock(@\"Can't rotate the image.\", @\"\");\n                return;\n            }\n        }\n\n        // Do the resizing\n        UIImage * scaledImage = [image scaleToSize:newSize];\n        if (scaledImage == nil) {\n            completeBlock(@\"Can't resize the image.\", @\"\");\n            return;\n        }\n\n        // Compress and save the image\n        if (!RNPFsaveImage(fullPath, scaledImage, format, quality)) {\n            completeBlock(@\"Can't save the image. Check your compression format.\", @\"\");\n            return;\n        }\n        \n        completeBlock(nil, fullPath);\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFFileDownloader.h",
    "content": "#import <Foundation/Foundation.h>\n\n@interface RNPFFileDownloader : NSObject<NSURLSessionDownloadDelegate>\n\ntypedef void (^fileDownloadCompleteBlock)(NSURL *downloadUrl);\ntypedef void (^fileDownloadProgressBlock)(int64_t progress, int64_t total);\ntypedef void (^fileDownloadProgressBlockSimple)(float progress);\n\ntypedef void (^fileDownloadErrorBlock)(NSError *error);\n\n- (void)startDownload:(NSURL *)url andSaveWithExtension:(NSString *)extension andProgressBlock:(fileDownloadProgressBlock)progressBlock andCompletionBlock:(fileDownloadCompleteBlock)completeBlock andErrorBlock:(fileDownloadErrorBlock)errorBlock;\n\n@property (nonatomic, copy) fileDownloadCompleteBlock completeBlock;\n@property (nonatomic, copy) fileDownloadProgressBlock progressBlock;\n@property (nonatomic, copy) fileDownloadErrorBlock errorBlock;\n@property (nonatomic, strong) NSString *extension;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFFileDownloader.m",
    "content": "#import \"RNPFFileDownloader.h\"\n\n@implementation RNPFFileDownloader\n\n- (void)startDownload:(NSURL *)url andSaveWithExtension:(NSString *)extension andProgressBlock:(fileDownloadProgressBlock)progressBlock andCompletionBlock:(fileDownloadCompleteBlock)completeBlock andErrorBlock:(fileDownloadErrorBlock)errorBlock\n{\n    self.extension = extension;\n    self.progressBlock = progressBlock;\n    self.completeBlock = completeBlock;\n    self.errorBlock = errorBlock;\n    NSURLSession *session = [self configureSession];\n    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];\n    [task resume];\n}\n\n- (NSURLSession *) configureSession {\n    NSURLSessionConfiguration *config =\n    [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:[@\"react-native-photos-framework-\" stringByAppendingString:[[NSUUID UUID] UUIDString]]];\n    config.allowsCellularAccess = YES;\n    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];\n    return session;\n}\n\n-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {\n    if(self.progressBlock) {\n        self.progressBlock(totalBytesWritten, totalBytesExpectedToWrite);\n    }\n    \n}\n\n-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {\n    if(self.completeBlock) {\n        if(self.extension) {\n            NSFileManager *fileMan = [NSFileManager defaultManager];\n            NSError *errorMov = nil;\n            NSString *documentDir = NSTemporaryDirectory();\n            NSString *newFilePath = [documentDir stringByAppendingPathComponent:[[[NSUUID UUID] UUIDString] stringByAppendingString:self.extension]];\n            if (![fileMan moveItemAtPath:location.path toPath:newFilePath error:&errorMov])\n            {\n                if(self.errorBlock) {\n                    return self.errorBlock(errorMov);\n                }\n            }\n            return self.completeBlock([NSURL URLWithString:newFilePath]);\n        }else {\n            self.completeBlock(location);\n        }\n    }\n}\n\n-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {\n    if(error != nil && self.errorBlock) {\n        self.errorBlock(error);\n    }\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFGlobals.h",
    "content": "#import <Foundation/Foundation.h>\n#define PHOTOS_SCHEME_IDENTIFIER @\"photos\"\n#define PHOTOS_SCHEME_IDENTIFIER_WITHSIGNS @\"photos://\"\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFHelpers.h",
    "content": "#import <Foundation/Foundation.h>\n#import <CoreLocation/CLLocation.h>\n@import Photos;\n\n@interface RNPFHelpers : NSObject\n+(NSDateFormatter *)getISODateFormatter;\n+(NSString *)NSDateToJsonString:(NSDate *)date andDateFormatter:(NSDateFormatter *)dateFormatter;\n+(NSTimeInterval)getTimeSince1970:(NSDate *)date;\n+(NSDictionary *)CLLocationToJson:(CLLocation *)loc;\n+(NSString *)convertEnumToStringValue:(int)type andValues:(NSDictionary *)values;\n+(NSArray*) nsOptionsToArray:(int)option andBitSize:(int)bitSize andReversedEnumDict:(NSDictionary *)dict;\n+(NSString*) nsOptionsToValue:(int)option andBitSize:(int)bitSize andReversedEnumDict:(NSDictionary *)dict;\n+(PHVideoRequestOptions *)getVideoRequestOptionsFromParams:(NSDictionary *)params;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFHelpers.m",
    "content": "#import \"RNPFHelpers.h\"\n#import <CoreLocation/CLLocation.h>\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n\n@implementation RNPFHelpers\n\n+(NSDateFormatter *)getISODateFormatter {\n    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];\n    NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@\"en_US_POSIX\"];\n    [dateFormatter setLocale:enUSPOSIXLocale];\n    [dateFormatter setDateFormat:@\"yyyy-MM-dd'T'HH:mm:ssZZZZZ\"];\n    return dateFormatter;\n}\n\n+(NSString *)NSDateToJsonString:(NSDate *)date andDateFormatter:(NSDateFormatter *)dateFormatter {\n    if(date == nil) {\n        return (NSString *)[NSNull null];\n    }\n    NSString *iso8601String = [dateFormatter stringFromDate:date];\n    return iso8601String;\n}\n\n+(NSTimeInterval)getTimeSince1970:(NSDate *)date {\n    if(date == nil) {\n        return 0;\n    }\n    return date.timeIntervalSince1970;\n}\n\n+(NSDictionary *)CLLocationToJson:(CLLocation *)loc {\n    return loc ? @{\n                       @\"latitude\": @(loc.coordinate.latitude),\n                       @\"longitude\": @(loc.coordinate.longitude),\n                       @\"altitude\": @(loc.altitude),\n                       @\"heading\": @(loc.course),\n                       @\"speed\": @(loc.speed),\n                       } : @{};\n}\n\n+(NSString *)convertEnumToStringValue:(int)type andValues:(NSDictionary *)values {\n    return [[values allKeysForObject:[NSNumber numberWithInt:type]] firstObject];\n}\n\n+(NSArray*) nsOptionsToArray:(int)option andBitSize:(int)bitSize andReversedEnumDict:(NSDictionary *)dict\n{\n    if(option == 0){\n        NSString *zeroValue = [dict objectForKey:@(0)];\n        return zeroValue ? [NSArray arrayWithObject:zeroValue] : (NSMutableArray*)[NSNull null];\n    }\n    NSMutableArray * nsOptions = [[NSMutableArray alloc] init];\n        for (NSUInteger i=0; i < bitSize; i++) {\n        NSUInteger enumBitValueToCheck = 1UL << i;\n        if ((option & enumBitValueToCheck)) {\n            NSObject *option = dict[@(enumBitValueToCheck)];\n            if (option) {\n                [nsOptions addObject:option];\n            }\n        }\n    }\n    \n    return nsOptions;\n}\n\n+(NSString*) nsOptionsToValue:(int)option andBitSize:(int)bitSize andReversedEnumDict:(NSDictionary *)dict\n{\n    if(option == 0){\n        NSString *zeroValue = [dict objectForKey:@(0)];\n        return zeroValue ? zeroValue : (NSString*)[NSNull null];\n    }\n    for (NSUInteger i=0; i < bitSize; i++) {\n        NSUInteger enumBitValueToCheck = 1UL << i;\n        if (option & enumBitValueToCheck) {\n            return [dict objectForKey:@(enumBitValueToCheck)];\n            \n        }\n    }\n    \n    return (NSString*)[NSNull null];\n}\n\n+(PHVideoRequestOptions *)getVideoRequestOptionsFromParams:(NSDictionary *)params {\n    \n    PHVideoRequestOptions *videoRequestOptions = [PHVideoRequestOptions new];\n    videoRequestOptions.networkAccessAllowed = YES;\n    \n    PHVideoRequestOptionsVersion version = PHVideoRequestOptionsVersionCurrent;\n    PHVideoRequestOptionsDeliveryMode deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;\n\n    if(params != nil) {\n        NSString *deliveryModeQuery = [RCTConvert NSString:params[@\"deliveryMode\"]];\n        NSString *versionQuery = [RCTConvert NSString:params[@\"version\"]];\n        if(versionQuery) {\n            if([versionQuery isEqualToString:@\"original\"]) {\n                version = PHVideoRequestOptionsVersionOriginal;\n            }\n        }\n        \n        if(deliveryModeQuery != nil) {\n            if([deliveryModeQuery isEqualToString:@\"mediumQuality\"]) {\n                deliveryMode = PHVideoRequestOptionsDeliveryModeMediumQualityFormat;\n            }\n            else if([deliveryModeQuery isEqualToString:@\"highQuality\"]) {\n                deliveryMode = PHVideoRequestOptionsDeliveryModeHighQualityFormat;\n            }\n            else if([deliveryModeQuery isEqualToString:@\"fast\"]) {\n                deliveryMode = PHVideoRequestOptionsDeliveryModeFastFormat;\n            }\n        }\n    }\n\n    videoRequestOptions.deliveryMode = deliveryMode;\n    videoRequestOptions.version = version;\n    \n    return videoRequestOptions;\n}\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFImageLoader.h",
    "content": "#import <React/RCTImageLoader.h>\n#import \"PHCachingImageManagerInstance.h\"\n\ntypedef void (^RNPFDataLoaderCompletionBlock)(NSError *error, NSData *data);\n\n@interface RNPFImageLoader : NSObject <RCTImageURLLoader>\n\n-(RCTImageLoaderCancellationBlock) loadAssetAsData:(NSURL *)imageURL                                  completionHandler:(RNPFDataLoaderCompletionBlock)completionHandler;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFImageLoader.m",
    "content": "#import \"RNPFImageLoader.h\"\n#import <Photos/Photos.h>\n#import <React/RCTUtils.h>\n#import \"RNPFGlobals.h\"\n@implementation RNPFImageLoader\n\nRCT_EXPORT_MODULE()\n\n@synthesize bridge = _bridge;\n\n- (BOOL)canLoadImageURL:(NSURL *)requestURL\n{\n    if (![PHAsset class]) {\n        return NO;\n    }\n    return [requestURL.scheme caseInsensitiveCompare:PHOTOS_SCHEME_IDENTIFIER] == NSOrderedSame;\n}\n\n-(PHAsset *)getAssetFromNSUrl:(NSURL *)url {\n    \n    static PHFetchOptions *fetchOptions = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        fetchOptions = [[PHFetchOptions alloc] init];\n        [fetchOptions setIncludeHiddenAssets:YES];\n        [fetchOptions setIncludeAllBurstAssets:YES];\n        [fetchOptions setWantsIncrementalChangeDetails:NO];\n    });\n    \n    NSString *localIdentifier = [url.absoluteString substringFromIndex:PHOTOS_SCHEME_IDENTIFIER_WITHSIGNS.length];\n    PHFetchResult *results = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:fetchOptions];\n\n    if([results count] == 0) {\n        return nil;\n    }\n    return [results firstObject];\n}\n\n-(RCTImageLoaderCancellationBlock) loadAssetAsData:(NSURL *)imageURL                                  completionHandler:(RNPFDataLoaderCompletionBlock)completionHandler {\n    PHAsset *asset = [self getAssetFromNSUrl:imageURL];\n    if(asset.mediaType == PHAssetMediaTypeImage) {\n        return [self loadImageAssetAsData:asset completionHandler:completionHandler];\n    }else if(asset.mediaType == PHAssetMediaTypeVideo) {\n        return [self loadVideoAssetAsData:asset completionHandler:completionHandler];\n    }\n    return ^{};\n}\n\n-(RCTImageLoaderCancellationBlock) loadImageAssetAsData:(PHAsset *)asset                                 completionHandler:(RNPFDataLoaderCompletionBlock)completionHandler\n {\n    if (asset == nil) {\n        NSString *errorText = [NSString stringWithFormat:@\"Failed to fetch localIdentifier with url %@ with no error message.\", asset.localIdentifier];\n        completionHandler(RCTErrorWithMessage(errorText), nil);\n        return ^{};\n    }\n     \n    PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];\n    imageOptions.networkAccessAllowed = YES;\n    imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;\n    imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;\n    \n    PHImageRequestID requestID =\n    [[PHCachingImageManagerInstance sharedCachingManager] requestImageDataForAsset:asset options:imageOptions resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {\n        completionHandler(nil, imageData);\n    }];\n    return ^{\n        [[PHCachingImageManagerInstance sharedCachingManager] cancelImageRequest:requestID];\n    };\n}\n\n-(RCTImageLoaderCancellationBlock) loadVideoAssetAsData:(PHAsset *)asset                                 completionHandler:(RNPFDataLoaderCompletionBlock)completionHandler\n{\n    if (asset == nil) {\n        NSString *errorText = [NSString stringWithFormat:@\"Failed to fetch localIdentifier with url %@ with no error message.\", asset.localIdentifier];\n        completionHandler(RCTErrorWithMessage(errorText), nil);\n        return ^{};\n    }\n    \n    PHVideoRequestOptions *videoOptions = [PHVideoRequestOptions new];\n    videoOptions.networkAccessAllowed = YES;\n    videoOptions.version=PHVideoRequestOptionsVersionOriginal;\n    \n    PHImageRequestID requestID = [[PHCachingImageManagerInstance sharedCachingManager] requestAVAssetForVideo:asset options:videoOptions resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info)\n     {\n         if ([asset isKindOfClass:[AVURLAsset class]])\n         {\n             NSURL *URL = [(AVURLAsset *)asset URL];\n             NSData *videoData=[NSData dataWithContentsOfURL:URL];\n             completionHandler(nil, videoData);\n         }\n     }];\n    \n    \n    return ^{\n        [[PHCachingImageManagerInstance sharedCachingManager] cancelImageRequest:requestID];\n    };\n}\n\n\n- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL\n                                              size:(CGSize)size\n                                             scale:(CGFloat)scale\n                                        resizeMode:(RCTResizeMode)resizeMode\n                                   progressHandler:(RCTImageLoaderProgressBlock)progressHandler\n                                partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler\n                                 completionHandler:(RCTImageLoaderCompletionBlock)completionHandler\n{\n\n    PHAsset *asset = [self getAssetFromNSUrl:imageURL];\n    \n    if (asset == nil) {\n        NSString *errorText = [NSString stringWithFormat:@\"Failed to fetch PHAsset with url %@ with no error message.\", [imageURL absoluteString]];\n        completionHandler(RCTErrorWithMessage(errorText), nil);\n        return ^{};\n    }\n    \n    PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];\n    imageOptions.networkAccessAllowed = YES;\n    \n    if (progressHandler) {\n        imageOptions.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary<NSString *, id> *info) {\n            static const double multiplier = 1e6;\n            progressHandler(progress * multiplier, multiplier);\n        };\n    }\n\n    BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);\n    CGSize targetSize;\n    if (useMaximumSize) {\n        targetSize = PHImageManagerMaximumSize;\n        imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;\n    } else {\n        targetSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));\n        imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;\n    }\n    \n    PHImageContentMode contentMode = PHImageContentModeAspectFill;\n    if (resizeMode == RCTResizeModeContain) {\n        contentMode = PHImageContentModeAspectFit;\n    }\n    \n    PHImageRequestOptionsVersion version = PHImageRequestOptionsVersionCurrent;\n    __block PHImageRequestOptionsDeliveryMode deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;\n    imageOptions.deliveryMode = deliveryMode;\n    imageOptions.version = version;\n    \n    if(imageURL.query != nil) {\n        NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:imageURL\n                                                    resolvingAgainstBaseURL:NO];\n        NSArray *queryItems = urlComponents.queryItems;\n        \n        //DeliveryMode\n        NSString *deliveryModeQuery = [self valueForKey:@\"deliveryMode\"\n                                         fromQueryItems:queryItems];\n        if(deliveryModeQuery != nil) {\n            if([deliveryModeQuery isEqualToString:@\"opportunistic\"]) {\n                imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;\n            }\n            else if([deliveryModeQuery isEqualToString:@\"highQuality\"]) {\n                imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;\n            }\n            else if([deliveryModeQuery isEqualToString:@\"fast\"]) {\n                imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;\n            }\n        }\n        \n        \n        //Version\n        NSString *versionQuery = [self valueForKey:@\"version\"\n                                         fromQueryItems:queryItems];\n        if(versionQuery != nil) {\n            if([versionQuery isEqualToString:@\"original\"]) {\n                imageOptions.version = PHImageRequestOptionsVersionOriginal;\n            }\n            if([versionQuery isEqualToString:@\"unadjusted\"]) {\n                imageOptions.version = PHImageRequestOptionsVersionUnadjusted;\n            }\n        }\n        \n        //ResizeMode\n        NSString *resizeModeQuery = [self valueForKey:@\"resizeMode\"\n                                        fromQueryItems:queryItems];\n        if(resizeModeQuery != nil) {\n            if([resizeModeQuery isEqualToString:@\"none\"]) {\n                imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;\n            }\n            if([resizeModeQuery isEqualToString:@\"fast\"]) {\n                imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;\n            }\n            if([resizeModeQuery isEqualToString:@\"exact\"]) {\n                imageOptions.resizeMode = PHImageRequestOptionsResizeModeExact;\n            }\n        }\n        \n        //ResizeMode\n        NSString *normalizedCropRectQuery = [self valueForKey:@\"cropRect\"\n                                       fromQueryItems:queryItems];\n        if(normalizedCropRectQuery != nil) {\n            NSArray<NSString *> * splittedRect = [normalizedCropRectQuery componentsSeparatedByString:@\"|\"];\n            float x = [splittedRect[0] floatValue];\n            float y = [splittedRect[1] floatValue];\n            float width = [splittedRect[2] floatValue];\n            float height = [splittedRect[3] floatValue];\n            \n            CGRect cropRect = CGRectMake(x, y, width, height);\n            CGRect normalizedRect = CGRectApplyAffineTransform(cropRect,\n                                                               CGAffineTransformMakeScale(1.0 / asset.pixelWidth,\n                                                                                          1.0 / asset.pixelHeight));\n            imageOptions.normalizedCropRect = normalizedRect;\n            imageOptions.resizeMode = PHImageRequestOptionsResizeModeExact;\n            targetSize = CGSizeApplyAffineTransform(CGSizeMake(width, height), CGAffineTransformMakeScale(scale, scale));\n        }\n        \n        //ContentMode\n        NSString *contentModeQuery = [self valueForKey:@\"contentMode\"\n                                        fromQueryItems:queryItems];\n        if(contentModeQuery != nil) {\n            if([contentModeQuery isEqualToString:@\"fit\"]) {\n                contentMode = PHImageContentModeAspectFit;\n            }\n            if([contentModeQuery isEqualToString:@\"fill\"]) {\n                contentMode = PHImageContentModeAspectFill;\n            }\n        }\n    }\n\n\n    \n    PHImageRequestID requestID =\n    [[PHCachingImageManagerInstance sharedCachingManager] requestImageForAsset:asset\n                                                                    targetSize:targetSize\n                                                                   contentMode:contentMode\n                                                                       options:imageOptions\n                                                                 resultHandler:^(UIImage *result, NSDictionary<NSString *, id> *info) {\n                                                                     if (result) {\n                                                                         if(deliveryMode == PHImageRequestOptionsDeliveryModeOpportunistic && [info[@\"PHImageResultIsDegradedKey\"] boolValue] == YES) {\n                                                                             if (partialLoadHandler) {\n                                                                                 partialLoadHandler(result);\n                                                                             }\n                                                                         }else {\n                                                                             completionHandler(nil, result);\n                                                                         }\n                                                                     } else {\n                                                                         completionHandler(info[PHImageErrorKey], nil);\n                                                                     }\n                                                                 }];\n    \n    return ^{\n        [[PHCachingImageManagerInstance sharedCachingManager] cancelImageRequest:requestID];\n    };\n}\n\n-(NSDictionary*)splitQuery:(NSString*)url {\n    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];\n    for (NSString *param in [url componentsSeparatedByString:@\"&\"]) {\n        NSArray *elts = [param componentsSeparatedByString:@\"=\"];\n        if([elts count] < 2) continue;\n        [params setObject:[elts lastObject] forKey:[elts firstObject]];\n    }\n    return params;\n}\n\n- (NSString *)valueForKey:(NSString *)key\n           fromQueryItems:(NSArray *)queryItems\n{\n    NSPredicate *predicate = [NSPredicate predicateWithFormat:@\"name=%@\", key];\n    NSURLQueryItem *queryItem = [[queryItems\n                                  filteredArrayUsingPredicate:predicate]\n                                 firstObject];\n    return queryItem.value;\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFManager.h",
    "content": "#import <AssetsLibrary/AssetsLibrary.h>\n#import <React/RCTBridgeModule.h>\n#import <React/RCTConvert.h>\n#import <React/RCTBridge.h>\n#import <React/RCTEventDispatcher.h> \n#import <React/RCTEventEmitter.h>\n#import \"PHOperationResult.h\"\n#import \"PHChangeObserver.h\"\n#import \"PHSaveAssetToFileOperationResult.h\"\n\n@import UIKit;\n@import Photos;\n\ntypedef void (^assetFileSaveOperationBlock)(BOOL success, NSError *__nullable error, NSString  * __nullable localIdentifier, NSString  * __nullable fileUrl);\ntypedef void(^assetsFileSaveCompleteBlock)( NSMutableArray<PHSaveAssetToFileOperationResult *> * _Nonnull  result);\n\n\ntypedef void (^assetOperationBlock)(BOOL success, NSError *__nullable error, NSString  * __nullable localIdentifier);\ntypedef void (^fileDownloadExtendedPrograessBlock)(NSString * _Nonnull uri, int index, int64_t progress, int64_t total);\ntypedef void (^fileDownloadExtendedPrograessBlockSimple)(NSString * _Nonnull uri, int index, float progress);\n\ntypedef void(^createAssetsCompleteBlock)( NSMutableArray<PHOperationResult *> * _Nonnull  result);\n\n@interface RNPFManager : RCTEventEmitter <RCTBridgeModule> {\n    bool hasListeners;\n}\n@property (nonatomic, strong) __nonnull dispatch_queue_t currentQueue;\n@property (nonatomic, strong)  PHChangeObserver * __nullable changeObserver;\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFManager.m",
    "content": "#import <React/RCTConvert.h>\n#import <React/RCTImageLoader.h>\n#import <React/RCTLog.h>\n#import <React/RCTUtils.h>\n#import <React/RCTProfile.h>\n#import \"RNPFManager.h\"\n#import \"PHCachingImageManagerInstance.h\"\n#import \"RCTConvert+RNPhotosFramework.h\"\n#import \"PHChangeObserver.h\"\n#import \"PHFetchOptionsService.h\"\n#import \"PHAssetsService.h\"\n#import \"PHCollectionService.h\"\n#import \"PHCachedFetchResult.h\"\n#import \"PHSaveAssetRequest.h\"\n#import \"RNPFHelpers.h\"\n#import \"RNPFFileDownloader.h\"\n#import \"PHOperationResult.h\"\n#import \"PHSaveAssetToFileOperationResult.h\"\n#import \"iDebounce.h\"\n#import \"PHCache.h\"\n#import \"RCTImageResizer.h\"\n#import \"PHVideoExporter.h\"\n\n@import Photos;\n\n@implementation RNPFManager\nRCT_EXPORT_MODULE()\n\nNSString *const RNPHotoFrameworkErrorUnableToLoad = @\"RNPHOTOSFRAMEWORK_UNABLE_TO_LOAD\";\nNSString *const RNPHotoFrameworkErrorUnableToSave = @\"RNPHOTOSFRAMEWORK_UNABLE_TO_SAVE\";\n\n\n/*\n Startup And Globals\n */\n\n#pragma mark - Startup And Globals\n\n- (void)dealloc\n{\n    if(self.changeObserver) {\n        [self.changeObserver removeChangeObserver];\n    }\n}\n\n\n\n- (dispatch_queue_t)methodQueue\n{\n    self.currentQueue = dispatch_queue_create(\"com.dahlbom.React.ReactNaticePhotosFramework\", DISPATCH_QUEUE_SERIAL);\n    return self.currentQueue;\n}\n\n- (NSArray<NSString *> *)supportedEvents {\n    return @[@\"onCreateAssetsProgress\", @\"onSaveAssetsToFileProgress\", @\"onLibraryChange\", @\"onObjectChange\"];\n}\n\n// Will be called when this module's first listener is added.\n-(void)startObserving {\n    hasListeners = YES;\n}\n\n// Will be called when this module's last listener is removed, or on dealloc.\n-(void)stopObserving {\n    hasListeners = NO;\n}\n\nRCT_EXPORT_METHOD(setAllowsCachingHighQualityImages:(BOOL)allowed)\n{\n    [[PHCachingImageManagerInstance sharedCachingManager] setAllowsCachingHighQualityImages:allowed];\n}\n\n\nRCT_EXPORT_METHOD(libraryStartup:(BOOL)useCacheAndChangeTracking\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    [[PHCache sharedPHCache] cleanCache];\n    if(useCacheAndChangeTracking && self.changeObserver == nil) {\n        self.changeObserver = [[PHChangeObserver alloc] initWithEventEmitter:self];\n    }\n    resolve(@{ @\"success\" : @((BOOL)YES) });\n}\n\n\nRCT_EXPORT_METHOD(startChangeObserving:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    self.changeObserver = [[PHChangeObserver alloc] initWithEventEmitter:self];\n}\n\n/*\n LibraryAuthorization\n */\n\n#pragma mark - LibraryAuthorization\n\nRCT_EXPORT_METHOD(authorizationStatus:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];\n    resolve(@{\n              @\"status\" : [[RCTConvert PHAuthorizationStatusValuesReversed] objectForKey:@(status)],\n              @\"isAuthorized\" : @((BOOL)(status == PHAuthorizationStatusAuthorized))\n              });\n}\n\nRCT_EXPORT_METHOD(requestAuthorization:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {\n        \n        resolve(@{\n                  @\"status\" : [[RCTConvert PHAuthorizationStatusValuesReversed] objectForKey:@(status)],\n                  @\"isAuthorized\" : @((BOOL)(status == PHAuthorizationStatusAuthorized))\n                  });\n    }];\n}\n\n\n/*\n GetAssets\n */\n\n#pragma mark - GetAssets\n\n\nRCT_EXPORT_METHOD(getAssets:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    RCT_PROFILE_BEGIN_EVENT(0, @\"-[RNPFManager getAssets\", nil);\n    \n    PHFetchResult<PHAsset *> *assetsFetchResult = [PHAssetsService getAssetsForParams:params];\n    \n    NSString *startIndexParam = params[@\"startIndex\"];\n    NSString *endIndexParam = params[@\"endIndex\"];\n    BOOL includeMetadata = [RCTConvert BOOL:params[@\"includeMetadata\"]];\n    BOOL includeResourcesMetadata = [RCTConvert BOOL:params[@\"includeResourcesMetadata\"]];\n    \n    \n    int startIndex = [RCTConvert int:startIndexParam];\n    int endIndex = endIndexParam != nil ? [RCTConvert int:endIndexParam] : (int)(assetsFetchResult.count -1);\n    \n    BOOL assetDisplayStartToEnd = [RCTConvert BOOL:params[@\"assetDisplayStartToEnd\"]];\n    BOOL assetDisplayBottomUp = [RCTConvert BOOL:params[@\"assetDisplayBottomUp\"]];\n    NSArray<PHAssetWithCollectionIndex *> *assets = [PHAssetsService getAssetsForFetchResult:assetsFetchResult startIndex:startIndex endIndex:endIndex assetDisplayStartToEnd:assetDisplayStartToEnd andAssetDisplayBottomUp:assetDisplayBottomUp];\n    [self prepareAssetsForDisplayWithParams:params andAssets:assets];\n    NSInteger assetCount = assetsFetchResult.count;\n    BOOL includesLastAsset = assetCount == 0 || endIndex >= (assetCount -1);\n    return resolve(@{\n                     @\"assets\" : [PHAssetsService assetsArrayToUriArray:assets andincludeMetadata:includeMetadata andIncludeAssetResourcesMetadata:includeResourcesMetadata],\n                     @\"includesLastAsset\" : @(includesLastAsset)\n                     });\n    RCT_PROFILE_END_EVENT(RCTProfileTagAlways, @\"\");\n}\n\nRCT_EXPORT_METHOD(getAssetsWithIndecies:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    BOOL includeMetadata = [RCTConvert BOOL:params[@\"includeMetadata\"]];\n    BOOL includeResourcesMetadata = [RCTConvert BOOL:params[@\"includeResourcesMetadata\"]];\n    \n    PHFetchResult<PHAsset *> *assetsFetchResult = [PHAssetsService getAssetsForParams:params];\n    NSArray<PHAssetWithCollectionIndex *> *assets = [PHAssetsService getAssetsForFetchResult:assetsFetchResult atIndecies:[RCTConvert NSArray:params[@\"indecies\"]]];\n    [self prepareAssetsForDisplayWithParams:params andAssets:assets];\n    resolve(@{\n              @\"assets\" : [PHAssetsService assetsArrayToUriArray:assets andincludeMetadata:includeMetadata andIncludeAssetResourcesMetadata:includeResourcesMetadata],\n              });\n}\n\n/*\n DeleteAssets\n */\n\n#pragma mark - DeleteAssets\n\n\nRCT_EXPORT_METHOD(deleteAssets:(NSArray *)localIdentifiers\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    if(localIdentifiers == nil || localIdentifiers.count == 0) {\n        return resolve(@{@\"localIdentifiers\" : @[], @\"success\" : @((BOOL)true)});\n    }\n    PHFetchResult<PHAsset *> * assets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:localIdentifiers];\n    [PHAssetsService deleteAssets:assets andCompleteBLock:^(BOOL success, NSError * _Nullable error, NSArray<NSString *> *localIdentifiers) {\n        if(localIdentifiers && localIdentifiers.count != 0) {\n            return resolve(@{@\"localIdentifiers\" : localIdentifiers, @\"success\" : @(success) });\n        }\n        return reject(@\"Error removing assets\", nil, error);\n    }];\n    \n}\n\n\n/*\n GetAssetMetaData\n */\n\n#pragma mark - GetAssetMetaData\n\n\nRCT_EXPORT_METHOD(getAssetsMetadata:(NSArray<NSString *> *)arrayWithLocalIdentifiers\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHFetchResult<PHAsset *> * arrayWithAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:arrayWithLocalIdentifiers];\n    NSMutableDictionary<NSString *, NSDictionary *> *dictWithMetadataObjs = [NSMutableDictionary dictionaryWithCapacity:arrayWithAssets.count];\n    [arrayWithAssets enumerateObjectsUsingBlock:^(PHAsset * _Nonnull asset, NSUInteger idx, BOOL * _Nonnull stop) {\n        [dictWithMetadataObjs setObject:[PHAssetsService extendAssetDictWithAssetMetadata:[NSMutableDictionary new] andPHAsset:asset] forKey:asset.localIdentifier];\n        \n    }];\n    resolve(dictWithMetadataObjs);\n}\n\nRCT_EXPORT_METHOD(getAssetsResourcesMetadata:(NSArray<NSString *> *)arrayWithLocalIdentifiers\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHFetchResult<PHAsset *> * arrayWithAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:arrayWithLocalIdentifiers];\n    NSMutableDictionary<NSString *, NSDictionary *> *dictWithMetadataObjs = [NSMutableDictionary dictionaryWithCapacity:arrayWithAssets.count];\n    [arrayWithAssets enumerateObjectsUsingBlock:^(PHAsset * _Nonnull asset, NSUInteger idx, BOOL * _Nonnull stop) {\n        [dictWithMetadataObjs setObject:[PHAssetsService extendAssetDictWithAssetResourcesMetadata:[NSMutableDictionary new] andPHAsset:asset] forKey:asset.localIdentifier];\n    }];\n    resolve(dictWithMetadataObjs);\n}\n\n\nRCT_EXPORT_METHOD(getImageAssetsMetadata:(NSArray<NSString *> *)arrayWithLocalIdentifiers\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHFetchResult<PHAsset *> * arrayWithAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:arrayWithLocalIdentifiers];\n    NSMutableArray *mutableArrayWithAssets = [NSMutableArray arrayWithCapacity:arrayWithAssets.count];\n    NSMutableDictionary<NSString *, NSDictionary *> *dictWithMetadataObjs = [NSMutableDictionary dictionaryWithCapacity:arrayWithAssets.count];\n    \n    [arrayWithAssets enumerateObjectsUsingBlock:^(PHAsset * _Nonnull asset, NSUInteger idx, BOOL * _Nonnull stop) {\n        [mutableArrayWithAssets addObject:asset];\n    }];\n    [self getImageAssetsMetaData:mutableArrayWithAssets andResultDict:dictWithMetadataObjs andCompleteBLock:^(NSMutableDictionary<NSString *, NSDictionary *> *resultDict) {\n        resolve(resultDict);\n    }];\n}\n\n\n-(void) getImageAssetsMetaData:(NSMutableArray<PHAsset *> *)assets andResultDict:(NSMutableDictionary<NSString *, NSDictionary *> *)resultDict andCompleteBLock:(nullable void(^)(NSMutableDictionary<NSString *, NSDictionary *> * resultDict))completeBlock {\n    \n    if(assets.count == 0){\n        return completeBlock(resultDict);\n    }\n    PHAsset *currentAsset = [assets objectAtIndex:0];\n    [assets removeObject:currentAsset];\n    if(currentAsset != nil) {\n        __weak RNPFManager *weakSelf = self;\n        [PHAssetsService extendAssetDictWithPhotoAssetEditingMetadata:[NSMutableDictionary new] andPHAsset:currentAsset andCompletionBlock:^(NSMutableDictionary *dict) {\n            [resultDict setObject:dict forKey:currentAsset.localIdentifier];\n            return [weakSelf getImageAssetsMetaData:assets andResultDict:resultDict andCompleteBLock:completeBlock];\n        }];\n    }else {\n        return [self getImageAssetsMetaData:assets andResultDict:resultDict andCompleteBLock:completeBlock];\n    }\n}\n\n/*\n UPDATEASSETS\n */\n\n\n#pragma mark - UpdateAssets\n\nRCT_EXPORT_METHOD(updateAssets:(NSArray *)arrayWithLocalIdentifiers andUpdateObjs:(NSDictionary *)updateObjs\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHFetchResult<PHAsset *> * arrayWithAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:arrayWithLocalIdentifiers];\n    \n    if(arrayWithAssets == nil || arrayWithAssets.count == 0){\n        return resolve(@{});\n    }\n    NSMutableArray *mutableArrayWithAssets = [NSMutableArray arrayWithCapacity:arrayWithAssets.count];\n    [arrayWithAssets enumerateObjectsUsingBlock:^(PHAsset * _Nonnull asset, NSUInteger idx, BOOL * _Nonnull stop) {\n        [mutableArrayWithAssets addObject:asset];\n    }];\n    [self updateAssets:mutableArrayWithAssets andUpdateObjs:updateObjs andResultArray:[NSMutableDictionary new] andCompleteBLock:^(NSMutableDictionary *result) {\n        resolve(result);\n    }];\n}\n\n\n-(void) updateAssets:(NSMutableArray<PHAsset *> *)assets andUpdateObjs:(NSDictionary *)updateObjs andResultArray:(NSMutableDictionary *)result andCompleteBLock:(nullable void(^)(NSMutableDictionary * result))completeBlock {\n    \n    if(assets.count == 0){\n        return completeBlock(result);\n    }\n    PHAsset *currentAsset = [assets objectAtIndex:0];\n    [assets removeObject:currentAsset];\n    if(currentAsset != nil) {\n        __weak RNPFManager *weakSelf = self;\n        NSDictionary *assetUpdateParams = [updateObjs objectForKey:currentAsset.localIdentifier];\n        if(assetUpdateParams) {\n            [PHAssetsService updateAssetWithParams:assetUpdateParams completionBlock:^(BOOL success, NSError * _Nullable error, NSString * _Nullable localIdentifier) {\n                \n                [result setObject:@{\n                                    @\"success\" : @(success),\n                                    @\"error\" : (error != nil ? error.localizedDescription : @\"\")\n                                    } forKey:localIdentifier];\n                \n                return [weakSelf updateAssets:assets andUpdateObjs:updateObjs andResultArray:result andCompleteBLock:completeBlock];\n                \n            } andAsset:currentAsset];\n        }\n        \n    }else {\n        return [self updateAssets:assets andUpdateObjs:updateObjs andResultArray:result andCompleteBLock:completeBlock];\n    }\n}\n\n/*\n SAVEASSETSTOFILE\n */\n\n\n#pragma mark - SaveAssetsToFile\n\nRCT_EXPORT_METHOD(saveAssetsToDisk:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    \n    NSArray<PHSaveAssetFileRequest *> *media = [RCTConvert PHSaveAssetFileRequestArray:params[@\"media\"]];\n    if(media == nil || media.count == 0) {\n        return resolve(@{@\"files\" : @[], @\"success\" : @((BOOL)true)});\n    }\n    \n    NSMutableArray *arrayWithProgress;\n    \n    NSDictionary *events= [RCTConvert NSDictionary:params[@\"events\"]];\n    \n    NSString *progressEventId = [RCTConvert NSString:events[@\"onSaveAssetsToFileProgress\"]];\n    NSString *cancellationEventId = [RCTConvert NSString:events[@\"onCancellationTokenCreated\"]];\n    \n   // [self sendEventWithName:@\"onCancellationTokenCreated\" body:@{@\"id\" : cancellationEventId, @\"data\" : arrayWithProgress}];\n\n    if(progressEventId != nil) {\n        arrayWithProgress = [NSMutableArray arrayWithCapacity:media.count];\n        for(int i = 0; i < media.count;i++) {\n            PHSaveAssetFileRequest *m = [media objectAtIndex:i];\n            [arrayWithProgress addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), m.uriString, nil]];\n        }\n    }\n    \n    [self saveAssetsToFileMany:media andCompleteBLock:^(NSMutableArray<PHSaveAssetToFileOperationResult *> * _Nonnull results) {\n        if(results == nil) {\n            return reject(@\"Something went wrong, result was nil\", nil, nil);\n        }\n        NSMutableArray *arrayResponse = [[NSMutableArray alloc] initWithCapacity:results.count];\n        for(int i = 0; i < results.count; i ++) {\n            PHSaveAssetToFileOperationResult *fileResult = [results objectAtIndex:i];\n            [arrayResponse addObject:@{\n                                       @\"localIdentifier\" :fileResult.localIdentifier,\n                                       @\"fileUrl\" : fileResult.fileUrl,\n                                       @\"success\" : @(fileResult.success),\n                                       @\"error\" : fileResult.error != nil ? [fileResult.error localizedDescription] : [NSNull null]\n                                       }];\n        }\n        return resolve(arrayResponse);\n        \n        \n    } andProgressBlock:^(NSString * _Nonnull uri, int index, float progress) {\n        if(hasListeners) {\n            @synchronized(arrayWithProgress)\n            {\n                NSMutableDictionary *dictForEntry = [arrayWithProgress objectAtIndex:index];\n                int64_t currentProgress = [[dictForEntry objectForKey:uri] integerValue];\n                currentProgress = progress;\n                [dictForEntry setObject:@(currentProgress) forKey:uri];\n            }\n            if(progressEventId != nil) {\n                [iDebounce debounce:^{\n                    dispatch_async(self.currentQueue, ^{\n                        [self sendEventWithName:@\"onSaveAssetsToFileProgress\" body:@{@\"id\" : progressEventId, @\"data\" : arrayWithProgress}];\n                    });\n                } withIdentifier:progressEventId wait:0.050];\n            }\n        }\n        \n    }];\n}\n\n-(void) saveAssetsToFileMany:(NSArray<PHSaveAssetFileRequest *> *)saveFileRequests\n            andCompleteBLock:(assetsFileSaveCompleteBlock)completeBlock andProgressBlock:(fileDownloadExtendedPrograessBlockSimple)progressBlock {\n    \n    __block NSMutableArray<PHSaveAssetToFileOperationResult *> *resultArray = [[NSMutableArray alloc] initWithCapacity:saveFileRequests.count];\n    NSOperationQueue *myOQ = [[NSOperationQueue alloc] init];\n    [myOQ setMaxConcurrentOperationCount:5];\n    assetFileSaveOperationBlock onTaskFinnished = ^void(BOOL success, NSError *__nullable error, NSString  * __nullable localIdentifier, NSString  * __nullable fileUrl) {\n        if(!myOQ.isSuspended) {\n            @synchronized(resultArray)\n            {\n                [resultArray addObject:[[PHSaveAssetToFileOperationResult alloc] initWithLocalIdentifier:localIdentifier fileUrl:fileUrl andSuccess:success andError:error]];\n                if(resultArray.count == saveFileRequests.count) {\n                    [myOQ setSuspended:YES];\n                    [myOQ cancelAllOperations];\n                    completeBlock(resultArray);\n                }\n            }\n        }\n    };\n    for(int i = 0; i < saveFileRequests.count;i++) {\n        __block PHSaveAssetFileRequest *currentRequest = [saveFileRequests objectAtIndex:i];\n        [myOQ addOperationWithBlock:^(void){\n            if([currentRequest.mediaType isEqualToString:@\"image\"]) {\n                [self writeImageToFile:currentRequest andCompleteBLock:onTaskFinnished andProgressBlock:^(int64_t progress, int64_t total) {\n                    progressBlock(currentRequest.uriString, i, ((float)progress / total) * 100);\n                }];\n            }else if([currentRequest.mediaType isEqualToString:@\"video\"]) {\n                [self writeVideoToFile:currentRequest andCompleteBLock:onTaskFinnished andProgressBlock:^(float progress) {\n                    progressBlock(currentRequest.uriString, i, progress);\n                }];\n            }\n        }];\n    }\n}\n\n-(void) writeImageToFile:(PHSaveAssetFileRequest *)fileRequest andCompleteBLock:(assetFileSaveOperationBlock)completeBlock andProgressBlock:(fileDownloadProgressBlock)progressBlock {\n    [self loadImageWithURLRequest:fileRequest.uri\n                                             clipped:YES\n                                          resizeMode:RCTResizeModeStretch\n                                    progressBlock:^(int64_t progress, int64_t total) {\n                                           return progressBlock(progress, total);\n                                       }\n                                     partialLoadBlock:nil\n                                     completionBlock:^(NSError *error, UIImage *loadedImage) {\n                                         if (error) {\n                                             return completeBlock(NO, error, fileRequest.localIdentifier, nil);\n                                         }\n                                         \n                                         if(fileRequest.postProcessOptions != nil) {\n                                             float width = [RCTConvert float:fileRequest.postProcessOptions[@\"width\"]];\n                                             float height = [RCTConvert float:fileRequest.postProcessOptions[@\"height\"]];\n                                             float quality = [RCTConvert float:fileRequest.postProcessOptions[@\"quality\"]];\n                                             float rotation = [RCTConvert float:fileRequest.postProcessOptions[@\"rotation\"]];\n                                             \n                                             if(width < 0.1) {\n                                                 width = loadedImage.size.width;\n                                             }\n                                             if(height < 0.1) {\n                                                 height = loadedImage.size.height;\n                                             }\n                                             if(quality < 0.1) {\n                                                 quality = 100;\n                                             }\n                                             \n                                             NSString *format = [RCTConvert NSString:fileRequest.postProcessOptions[@\"format\"]];\n                                             if(![format isEqualToString:@\"JPEG\"] || ![format isEqualToString:@\"PNG\"]) {\n                                                 format = @\"JPEG\";\n                                             }\n                                             return [RNPFImageResizer createResizedImage:loadedImage width:width height:height format:format quality:quality rotation:rotation outputPath:fileRequest.dir fileName:fileRequest.fileName andCompleteBLock:^(NSString *error, NSString *path) {\n                                                 if(error != nil) {\n                                                     return completeBlock(NO, nil, fileRequest.localIdentifier, nil);\n                                                 }\n                                                 progressBlock(100, 100);\n                                                 return completeBlock(YES, nil,fileRequest.localIdentifier, path);\n                                             }];\n                                         }\n                                         \n                                         \n                                         NSString *fullFileName = [fileRequest.dir stringByAppendingPathComponent:fileRequest.fileName];\n                                         \n                                         NSData * binaryImageData = UIImagePNGRepresentation(loadedImage);\n                                         \n                                         BOOL success = [binaryImageData writeToFile:fullFileName atomically:YES];\n                                         if(success) {\n                                             return completeBlock(YES, nil, fileRequest.localIdentifier, fullFileName);\n                                         }\n                                         \n                                     } andOptions:[RCTConvert NSDictionary:fileRequest.loadOptions]];\n}\n\n-(void) writeVideoToFile:(PHSaveAssetFileRequest *)fileRequest andCompleteBLock:(assetFileSaveOperationBlock)completeBlock andProgressBlock:(fileDownloadProgressBlockSimple)progressBlock {\n    __block PHVideoExporter *videoExporter;\n    PHAsset* asset = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:@[fileRequest.localIdentifier]].firstObject;\n    \n    fileRequest.videoRequestOptions.progressHandler = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) {\n        progressBlock((progress * 100) / 2);\n    };\n    \n    [[PHImageManager defaultManager] requestAVAssetForVideo:asset\n                                                    options:fileRequest.videoRequestOptions\n                                              resultHandler:\n     ^(AVAsset * _Nullable avasset,\n       AVAudioMix * _Nullable audioMix,\n       NSDictionary * _Nullable info)\n     {\n         progressBlock(50);\n         \n         if(fileRequest.postProcessOptions != nil) {\n             videoExporter = [PHVideoExporter new];\n             [videoExporter exportVideoWithAsset:avasset andDir:fileRequest.dir andFileName:fileRequest.fileName andPostProcessParams:fileRequest.postProcessOptions andProgressBlock:^(float progress) {\n                 progressBlock((progress * 100));\n                 \n             } andCompletionBlock:^(BOOL success, NSError * _Nullable error, NSURL * _Nullable fileUrl) {\n                 progressBlock(100);\n                 completeBlock(success, error, fileRequest.localIdentifier, [fileUrl absoluteString]);\n             }];\n         }else {\n             \n             NSError *error;\n             __block NSString *fullFileName = [fileRequest.dir stringByAppendingPathComponent:fileRequest.fileName];\n             \n             if ([[NSFileManager defaultManager] fileExistsAtPath:fullFileName] && [[NSFileManager defaultManager] isDeletableFileAtPath:fullFileName]) {\n                 BOOL success = [[NSFileManager defaultManager] removeItemAtPath:fullFileName error:&error];\n                 if (!success) {\n                     NSLog(@\"Error removing file at path: %@\", error.localizedDescription);\n                 }\n             }\n             NSURL *fileURL = [NSURL fileURLWithPath:fullFileName];\n\n             AVURLAsset *avurlasset = (AVURLAsset*) avasset;\n\n             if ([[NSFileManager defaultManager] copyItemAtURL:avurlasset.URL\n                                                         toURL:fileURL\n                                                         error:&error]) {\n                 if(error) {\n                     return completeBlock(NO, error, fileRequest.localIdentifier, nil);\n                 }else {\n                     progressBlock(100);\n                     return completeBlock(YES, nil, fileRequest.localIdentifier, fullFileName);\n                 }\n             }\n         }\n     }];\n}\n\n/*\n CREATEASSETS\n */\n\n\n#pragma mark - CreateAssets\nRCT_EXPORT_METHOD(createAssets:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    NSArray<PHSaveAssetRequest *> *media = [RCTConvert PHSaveAssetRequestArray:params[@\"media\"]];\n    if(media == nil || media.count == 0) {\n        return resolve(@{@\"localIdentifiers\" : @[], @\"success\" : @((BOOL)true)});\n    }\n    NSString *albumLocalIdentifier = [RCTConvert NSString:params[@\"albumLocalIdentifier\"]];\n    \n    NSMutableArray *arrayWithProgress;\n    \n    NSString *progressEventId = [RCTConvert NSString:params[@\"onCreateAssetsProgress\"]];\n    if(progressEventId != nil) {\n        arrayWithProgress = [NSMutableArray arrayWithCapacity:media.count];\n        for(int i = 0; i < media.count;i++) {\n            PHSaveAssetRequest *m = [media objectAtIndex:i];\n            [arrayWithProgress addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@(0), m.source.uri, nil]];\n        }\n    }\n    \n    \n    [self saveMediaMany:media andCollectionLocalIdentifier:albumLocalIdentifier andCompleteBLock:^(NSMutableArray<PHOperationResult *> *result) {\n        \n        NSMutableArray *arrayWithLocalIdentfiers = [[NSMutableArray alloc] initWithCapacity:result.count];\n        for(int i = 0; i < result.count;i++) {\n            PHOperationResult *operation = [result objectAtIndex:i];\n            if(operation.success) {\n                [arrayWithLocalIdentfiers addObject:operation.localIdentifier];\n            }\n        }\n        \n        BOOL includeMetadata = [RCTConvert BOOL:params[@\"includeMetadata\"]];\n        BOOL includeResourcesMetadata = [RCTConvert BOOL:params[@\"includeResourcesMetadata\"]];\n        \n        PHFetchResult<PHAsset *> *newAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:arrayWithLocalIdentfiers];\n        NSArray<NSDictionary *> *assetResponse = [PHAssetsService assetsArrayToUriArray:(NSArray<id> *)newAssets andincludeMetadata:includeMetadata andIncludeAssetResourcesMetadata:includeResourcesMetadata];\n        return resolve(@{@\"assets\" : assetResponse, @\"success\" : @(YES) });\n        \n    } andProgressBlock:^(NSString *uri, int index, int64_t progress, int64_t total) {\n        if(hasListeners && progressEventId != nil) {\n            @synchronized(arrayWithProgress)\n            {\n                NSMutableDictionary *dictForEntry = [arrayWithProgress objectAtIndex:index];\n                int64_t currentProgress = [[dictForEntry objectForKey:uri] integerValue];\n                currentProgress = ((float)progress / total) * 100;\n                [dictForEntry setObject:@(currentProgress) forKey:uri];\n            }\n            \n            [iDebounce debounce:^{\n                dispatch_async(self.currentQueue, ^{\n                    [self sendEventWithName:@\"onCreateAssetsProgress\" body:@{@\"id\" : progressEventId, @\"data\" : arrayWithProgress}];\n                });\n            } withIdentifier:progressEventId wait:0.050];\n        }\n    }];\n}\n\n-(void) saveMediaMany:(NSArray<PHSaveAssetRequest *> *)requests andCollectionLocalIdentifier:(NSString *)collectionLocalIdentifier andCompleteBLock:(createAssetsCompleteBlock)completeBlock andProgressBlock:(fileDownloadExtendedPrograessBlock)progressBlock {\n    \n    NSMutableArray<PHOperationResult *> *resultArray = [[NSMutableArray alloc] initWithCapacity:requests.count];\n    NSOperationQueue *myOQ = [[NSOperationQueue alloc] init];\n    [myOQ setMaxConcurrentOperationCount:5];\n    assetOperationBlock onTaskFinnished = ^void(BOOL success, NSError *__nullable error, NSString  * __nullable localIdentifier) {\n        if(!myOQ.isSuspended) {\n            @synchronized(resultArray)\n            {\n                [resultArray addObject:[[PHOperationResult alloc] initWithLocalIdentifier:localIdentifier andSuccess:success andError:error]];\n                if(resultArray.count == requests.count) {\n                    [myOQ setSuspended:YES];\n                    [myOQ cancelAllOperations];\n                    completeBlock(resultArray);\n                }\n            }\n        }\n    };\n    for(int i = 0; i < requests.count;i++) {\n        __block PHSaveAssetRequest *currentRequest = [requests objectAtIndex:i];\n        [myOQ addOperationWithBlock:^(void){\n            [self saveMedia:currentRequest toCollection:collectionLocalIdentifier andCompleteBLock:onTaskFinnished andProgressBlock:^(int64_t progress, int64_t total) {\n                progressBlock(currentRequest.source.uri, i, progress, total);\n            }];\n        }];\n    }\n}\n\n-(void)saveMedia:(PHSaveAssetRequest *)request\n    toCollection:(NSString *)collectionLocalIdentifier\nandCompleteBLock:(assetOperationBlock)completeBlock\nandProgressBlock:(fileDownloadProgressBlock)progressBlock {\n    if ([request.type isEqualToString:@\"video\"]) {\n        [self saveVideo:request.source toAlbum:collectionLocalIdentifier andCompleteBLock:completeBlock andProgressBlock:progressBlock];\n    } else if([request.type isEqualToString:@\"image\"]) {\n        NSURLRequest *url = [RCTConvert NSURLRequest:request.source.uri];\n        [self.bridge.imageLoader loadImageWithURLRequest:url\n                                                    size:CGSizeZero\n                                                   scale:1\n                                                 clipped:YES\n                                              resizeMode:RCTResizeModeStretch\n                                           progressBlock:^(int64_t progress, int64_t total) {\n                                               progressBlock(progress, total);\n                                           }\n                                        partialLoadBlock:nil\n                                         completionBlock:^(NSError *loadError, UIImage *loadedImage) {\n                                             if (loadError) {\n                                                 completeBlock(NO, loadError, nil);\n                                                 return;\n                                             }\n                                             [PHCollectionService saveImage:loadedImage toAlbum:collectionLocalIdentifier andCompleteBLock:completeBlock];\n                                         }];\n    }\n}\n\n-(void) saveVideo:(PHSaveAsset *)source toAlbum:(NSString *)albumLocalIdentifier andCompleteBLock:(assetOperationBlock)completeBlock andProgressBlock:(fileDownloadProgressBlock)progressBlock {\n    NSString *type = source.type != nil ? [@\".\" stringByAppendingString:source.type] : @\".mp4\";\n    NSURL *url = (source.isNetwork || source.isAsset) ?\n    [NSURL URLWithString:source.uri] :\n    [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:source.uri ofType:source.type]];\n    \n    if (source.isNetwork) {\n        RNPFFileDownloader *fileDownloader = [RNPFFileDownloader new];\n        [fileDownloader startDownload:url andSaveWithExtension:type andProgressBlock:^(int64_t progress, int64_t total) {\n            progressBlock(progress, total);\n        } andCompletionBlock:^(NSURL *downloadUrl) {\n            [self saveVideoAtURL:downloadUrl toAlbum:albumLocalIdentifier andCompleteBLock:completeBlock];\n        } andErrorBlock:^(NSError *error) {\n            completeBlock(NO, error, nil);\n        }];\n    }\n    else {\n        [self saveVideoAtURL:url toAlbum:albumLocalIdentifier andCompleteBLock:completeBlock];\n    }\n}\n\n-(void)saveVideoAtURL:(NSURL *)url toAlbum:(NSString *)albumLocalIdentifier andCompleteBLock:(assetOperationBlock)completeBlock {\n    __block PHObjectPlaceholder *placeholder;\n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        \n        PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:url];\n        placeholder = [assetRequest placeholderForCreatedAsset];\n        \n        if(albumLocalIdentifier != nil) {\n            PHAssetCollection *album = [PHCollectionService getAssetForLocalIdentifer:albumLocalIdentifier];\n            PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];\n            [albumChangeRequest addAssets:@[placeholder]];\n            \n        }\n    } completionHandler:^(BOOL success, NSError *error) {\n        completeBlock(success, error, placeholder.localIdentifier);\n    }];\n}\n\n/*\n GetAlbums\n */\n\n#pragma mark - GetAlbums\n\nRCT_EXPORT_METHOD(getAlbums:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    return resolve([PHCollectionService getAlbums:params]);\n}\n\nRCT_EXPORT_METHOD(stopTracking:(NSString *)cacheKey\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    if(cacheKey != nil) {\n        [[PHCache sharedPHCache] removeFetchResultFromCacheWithUUID:cacheKey];\n    }\n    return resolve(@{@\"success\" : @(YES)});\n}\n\nRCT_EXPORT_METHOD(getAlbumsMany:(NSArray *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    NSMutableArray *responseArray = [NSMutableArray new];\n    for(int i = 0; i < params.count;i++) {\n        NSDictionary *albumsQuery = [params objectAtIndex:i];\n        [responseArray addObject:[PHCollectionService getAlbums:albumsQuery]];\n    }\n    return resolve(responseArray);\n}\n\nRCT_EXPORT_METHOD(getAlbumsByTitles:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    NSArray * albumTitles = [RCTConvert NSArray:params[@\"albumTitles\"]];\n    if(albumTitles == nil) {\n        return reject(@\"albumTitles cannot be null\", nil, nil);\n    }\n    PHFetchResult<PHAssetCollection *> * collections = [PHCollectionService getUserAlbumsByTitles:albumTitles withParams:params];\n    resolve([PHCollectionService generateCollectionResponseWithCollections:(PHFetchResult<PHCollection *> *)collections andParams:params]);\n}\n\n/*\n CreateAlbums\n */\n\n#pragma mark - CreateAlbums\n\nRCT_EXPORT_METHOD(createAlbums:(NSArray *)albumTitles\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    if(albumTitles == nil) {\n        return reject(@\"input array with album-names array<string> cannot be null\", nil, nil);\n    }\n    \n    if(albumTitles.count == 0) {\n        return resolve(@[]);\n    }\n    \n    [PHCollectionService createAlbumsWithTitles:albumTitles andCompleteBLock:^(BOOL success, NSError * _Nullable error, NSArray<NSString *> *localIdentifiers) {\n        if(success) {\n            PHFetchResult<PHAssetCollection *> *collections = [PHCollectionService getAlbumsWithLocalIdentifiers:localIdentifiers andParams:nil];\n            \n            NSMutableDictionary *response = [PHCollectionService generateCollectionResponseWithCollections:(PHFetchResult<PHCollection *> *)collections andParams:[NSDictionary dictionaryWithObjectsAndKeys:@\"true\", @\"noCache\", nil]];\n            \n            return resolve([response objectForKey:@\"albums\"]);\n        }else{\n            return reject([NSString stringWithFormat:@\"Error creating albumTitles %@\", albumTitles], nil, error);\n        }\n    }];\n}\n\n/*\n DeleteAlbums\n */\n\n#pragma mark - DeleteAlbums\n\nRCT_EXPORT_METHOD(deleteAlbums:(NSArray *)albumsLocalIdentifiers\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    if(albumsLocalIdentifiers == nil) {\n        return reject(@\"input array with album-localIdentifiers array<string> cannot be null\", nil, nil);\n    }\n    \n    if(albumsLocalIdentifiers.count == 0) {\n        return resolve(@[]);\n    }\n    \n    [PHCollectionService deleteAlbumsWithLocalIdentifers:albumsLocalIdentifiers andCompleteBLock:^(BOOL success, NSError * _Nullable error) {\n        if(success) {\n            return resolve(@{@\"success\" : @(success)});\n        }else{\n            return reject(@\"Error deleting albums\", nil, error);\n        }\n    }];\n}\n\n/*\n UpdateAlbum\n */\n\n#pragma mark - UpdateAlbum\n\nRCT_EXPORT_METHOD(updateAlbumTitle:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHAssetCollection *collection = [PHCollectionService getAssetCollectionForParams:params];\n    NSString *newTitle = [RCTConvert NSString:params[@\"newTitle\"]];\n    if(newTitle == nil) {\n        return reject(@\"You have to provide newTitle-prop to rename album\", nil, nil);\n    }\n    if (![collection canPerformEditOperation:PHCollectionEditOperationRename]) {\n        return reject(@\"Can't PerformEditOperation\", nil, nil);\n    }\n    \n    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{\n        PHAssetCollectionChangeRequest *changeTitlerequest =[PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection];\n        changeTitlerequest.title = newTitle;\n        \n    } completionHandler:^(BOOL success, NSError *error) {\n        if(success) {\n            return resolve(@{ @\"success\" : @(success) });\n        }else {\n            return reject(@\"Error updating title\", nil, error);\n        }\n    }];\n}\n\nRCT_EXPORT_METHOD(addAssetsToAlbum:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHAssetCollection *assetCollection = [PHCollectionService getAssetCollectionForParams:params];\n    PHFetchResult<PHAsset *> *fetchedAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:[RCTConvert NSArray:params[@\"assets\"]]];\n    [PHCollectionService addAssets:fetchedAssets toAssetCollection:assetCollection andCompleteBLock:^(BOOL success, NSError * _Nullable error) {\n        if(success) {\n            return resolve(@{ @\"success\" : @(success) });\n        }else {\n            return reject(@\"Error adding assets to album\", nil, error);\n        }\n        \n    }];\n}\n\nRCT_EXPORT_METHOD(removeAssetsFromAlbum:(NSDictionary *)params\n                  resolve:(RCTPromiseResolveBlock)resolve\n                  reject:(RCTPromiseRejectBlock)reject)\n{\n    PHAssetCollection *assetCollection = [PHCollectionService getAssetCollectionForParams:params];\n    PHFetchResult<PHAsset *> *fetchedAssets = [PHAssetsService getAssetsFromArrayOfLocalIdentifiers:[RCTConvert NSArray:params[@\"assets\"]]];\n    [PHCollectionService removeAssets:fetchedAssets fromAssetCollection:assetCollection andCompleteBLock:^(BOOL success, NSError * _Nullable error) {\n        if(success) {\n            return resolve(@{ @\"success\" : @(success) });\n        }else {\n            return reject(@\"Error removing assets from album\", nil, error);\n        }\n        \n    }];\n}\n\n#pragma mark - Helpers\n-(void) prepareAssetsForDisplayWithParams:(NSDictionary *)params andAssets:(NSArray<PHAssetWithCollectionIndex *> *)assets {\n    NSString *prepareProp = params[@\"prepareForSizeDisplay\"];\n    if(prepareProp != nil) {\n        CGSize prepareForSizeDisplay = [RCTConvert CGSize:params[@\"prepareForSizeDisplay\"]];\n        CGFloat prepareScale = [RCTConvert CGFloat:params[@\"prepareScale\"]];\n        PHCachingImageManager *cacheManager = [PHCachingImageManagerInstance sharedCachingManager];\n        \n        if(prepareForSizeDisplay.width != 0 && prepareForSizeDisplay.height != 0) {\n            if(prepareScale < 0.1) {\n                prepareScale = 2;\n            }\n            [cacheManager startCachingImagesForAssets:[PHAssetWithCollectionIndex toAssetsArray:assets] targetSize:CGSizeApplyAffineTransform(prepareForSizeDisplay, CGAffineTransformMakeScale(prepareScale, prepareScale)) contentMode:PHImageContentModeAspectFill options:nil];\n        }\n    }\n}\n\n-(RCTImageLoaderCancellationBlock) loadImageWithURLRequest:(NSURLRequest *)imageURLRequest\n                 clipped:(BOOL)clipped\n              resizeMode:(RCTResizeMode)resizeMode\n           progressBlock:(RCTImageLoaderProgressBlock)progressBlock\n        partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock\n         completionBlock:(RCTImageLoaderCompletionBlock)completionBlock\n      andOptions:(NSDictionary *)params {\n    \n    CGSize size = CGSizeZero;\n    float width = [RCTConvert float:params[@\"width\"]];\n    float height = [RCTConvert float:params[@\"height\"]];\n    if(width > 0 || height > 0) {\n        size = CGSizeMake(width, height);\n    }\n    \n    CGFloat scale = [RCTConvert CGFloat:params[@\"scale\"]];\n    if(scale < 0.1) {\n        scale = 1;\n    }\n    \n    NSURLComponents *components = [[NSURLComponents alloc] initWithURL:imageURLRequest.URL resolvingAgainstBaseURL:NO];\n    components.queryItems = [self parseParamsToImageLoaderQueryOptions:params];\n    \n    return [self.bridge.imageLoader loadImageWithURLRequest:[NSURLRequest requestWithURL:components.URL]\n                                                size:size\n                                               scale:scale\n                                             clipped:clipped\n                                          resizeMode:resizeMode\n                                       progressBlock:progressBlock\n                                    partialLoadBlock:partialLoadBlock\n                                     completionBlock:completionBlock];\n}\n\n-(NSArray<NSURLQueryItem *> *)parseParamsToImageLoaderQueryOptions:(NSDictionary *)params {\n    \n    NSArray *allowedQueryStringValues = [NSArray arrayWithObjects:@\"deliveryMode\", @\"version\", @\"resizeMode\", @\"cropRect\", @\"contentMode\", nil];\n    NSMutableArray *queryItems = [NSMutableArray array];\n    if(params != nil) {\n        for (NSString *key in params) {\n            BOOL isAllowed = [allowedQueryStringValues containsObject:key];\n            if(isAllowed) {\n                [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:params[key]]];\n            }\n        }\n    }\n    return queryItems;\n}\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFUrlRequestHandler.h",
    "content": "#import <Foundation/Foundation.h>\n#import <React/RCTBridge.h>\n#import <React/RCTURLRequestHandler.h>\n\n@interface RNPFUrlRequestHandler : NSObject<RCTBridgeModule, RCTURLRequestHandler>\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPFUrlRequestHandler.m",
    "content": "#import \"RNPFUrlRequestHandler.h\"\n#import <ImageIO/ImageIO.h>\n\n#import <React/RCTConvert.h>\n#import <React/RCTDefines.h>\n#import <React/RCTImageLoader.h>\n#import <React/RCTLog.h>\n#import <React/RCTNetworking.h>\n#import <React/RCTUtils.h>\n#import \"RNPFGlobals.h\"\n#import \"PHAssetsService.h\"\n#import \"RNPFImageLoader.h\"\n\n@implementation RNPFUrlRequestHandler\n@synthesize bridge = _bridge;\n\nRCT_EXPORT_MODULE()\n\n- (BOOL)canHandleRequest:(NSURLRequest *)request\n{\n    BOOL handleRequest = [request.URL.scheme caseInsensitiveCompare:PHOTOS_SCHEME_IDENTIFIER] == NSOrderedSame;\n    return handleRequest;\n}\n\n- (id)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate\n{\n    __block RCTImageLoaderCancellationBlock requestToken;\n    RNPFImageLoader *imageLoader = [[RNPFImageLoader alloc] init];\n    requestToken = [imageLoader loadAssetAsData:request.URL completionHandler:^(NSError *error, NSData *assetData) {\n        if (error) {\n            [delegate URLRequest:requestToken didCompleteWithError:error];\n            return;\n        }\n        [delegate URLRequest:requestToken didReceiveData:assetData];\n        [delegate URLRequest:requestToken didCompleteWithError:nil];\n    }];\n    return requestToken;\n}\n\n- (float) handlerPriority {\n    return 99;\n}\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPhotosFramework.h",
    "content": "//\n//  RNPhotosFramework.h\n//  RNPhotosFramework\n//\n//  Created by Olof Dahlbom on 2016-10-19.\n//  Copyright © 2016 Olof Dahlbom. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface RNPhotosFramework : NSObject\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/RNPhotosFramework.m",
    "content": "//\n//  RNPhotosFramework.m\n//  RNPhotosFramework\n//\n//  Created by Olof Dahlbom on 2016-10-19.\n//  Copyright © 2016 Olof Dahlbom. All rights reserved.\n//\n\n#import \"RNPhotosFramework.h\"\n\n@implementation RNPhotosFramework\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/SDAVAssetExportSession.h",
    "content": "//\n//  SDAVAssetExportSession.h\n//\n// This file is part of the SDAVAssetExportSession package.\n//\n// Created by Olivier Poitrey <rs@dailymotion.com> on 13/03/13.\n// Copyright 2013 Olivier Poitrey. All rights servered.\n//\n// For the full copyright and license information, please view the LICENSE\n// file that was distributed with this source code.\n//\n\n#import <Foundation/Foundation.h>\n#import <AVFoundation/AVFoundation.h>\n\n@protocol SDAVAssetExportSessionDelegate;\n\n\n/**\n * An `SDAVAssetExportSession` object transcodes the contents of an AVAsset source object to create an output\n * of the form described by specified video and audio settings. It implements most of the API of Apple provided\n * `AVAssetExportSession` but with the capability to provide you own video and audio settings instead of the\n * limited set of Apple provided presets.\n *\n * After you have initialized an export session with the asset that contains the source media, video and audio\n * settings, and the output file type (outputFileType), you can start the export running by invoking \n * `exportAsynchronouslyWithCompletionHandler:`. Because the export is performed asynchronously, this method\n * returns immediately — you can observe progress to check on the progress.\n *\n * The completion handler you supply to `exportAsynchronouslyWithCompletionHandler:` is called whether the export\n * fails, completes, or is cancelled. Upon completion, the status property indicates whether the export has\n * completed successfully. If it has failed, the value of the error property supplies additional information\n * about the reason for the failure.\n */\n\n@interface SDAVAssetExportSession : NSObject\n\n@property (nonatomic, weak) id<SDAVAssetExportSessionDelegate> delegate;\n\n/**\n * The asset with which the export session was initialized.\n */\n@property (nonatomic, strong, readonly) AVAsset *asset;\n\n/**\n * Indicates whether video composition is enabled for export, and supplies the instructions for video composition.\n *\n * You can observe this property using key-value observing.\n */\n@property (nonatomic, copy) AVVideoComposition *videoComposition;\n\n/**\n * Indicates whether non-default audio mixing is enabled for export, and supplies the parameters for audio mixing.\n */\n@property (nonatomic, copy) AVAudioMix *audioMix;\n\n/**\n * The type of file to be written by the session.\n *\n * The value is a UTI string corresponding to the file type to use when writing the asset.\n * For a list of constants specifying UTIs for standard file types, see `AV Foundation Constants Reference`.\n *\n * You can observe this property using key-value observing.\n */\n@property (nonatomic, copy) NSString *outputFileType;\n\n/**\n * The URL of the export session’s output.\n *\n * You can observe this property using key-value observing.\n */\n@property (nonatomic, copy) NSURL *outputURL;\n\n/**\n * The settings used for input video track.\n *\n * The dictionary’s keys are from <CoreVideo/CVPixelBuffer.h>.\n */\n@property (nonatomic, copy) NSDictionary *videoInputSettings;\n\n/**\n * The settings used for encoding the video track.\n *\n * A value of nil specifies that appended output should not be re-encoded.\n * The dictionary’s keys are from <AVFoundation/AVVideoSettings.h>.\n */\n@property (nonatomic, copy) NSDictionary *videoSettings;\n\n/**\n * The settings used for encoding the audio track.\n *\n * A value of nil specifies that appended output should not be re-encoded.\n * The dictionary’s keys are from <CoreVideo/CVPixelBuffer.h>.\n */\n@property (nonatomic, copy) NSDictionary *audioSettings;\n\n/**\n * The time range to be exported from the source.\n *\n * The default time range of an export session is `kCMTimeZero` to `kCMTimePositiveInfinity`,\n * meaning that (modulo a possible limit on file length) the full duration of the asset will be exported.\n *\n * You can observe this property using key-value observing.\n *\n */\n@property (nonatomic, assign) CMTimeRange timeRange;\n\n/**\n * Indicates whether the movie should be optimized for network use.\n *\n * You can observe this property using key-value observing.\n */\n@property (nonatomic, assign) BOOL shouldOptimizeForNetworkUse;\n\n/**\n * The metadata to be written to the output file by the export session.\n */\n@property (nonatomic, copy) NSArray *metadata;\n\n/**\n * Describes the error that occurred if the export status is `AVAssetExportSessionStatusFailed`\n * or `AVAssetExportSessionStatusCancelled`.\n *\n * If there is no error to report, the value of this property is nil.\n */\n@property (nonatomic, strong, readonly) NSError *error;\n\n/**\n * The progress of the export on a scale from 0 to 1.\n *\n *\n * A value of 0 means the export has not yet begun, 1 means the export is complete.\n *\n * Unlike Apple provided `AVAssetExportSession`, this property can be observed using key-value observing.\n */\n@property (nonatomic, assign, readonly) float progress;\n\n/**\n * The status of the export session.\n *\n * For possible values, see “AVAssetExportSessionStatus.”\n *\n * You can observe this property using key-value observing. (TODO)\n */\n@property (nonatomic, assign, readonly) AVAssetExportSessionStatus status;\n\n/**\n * Returns an asset export session configured with a specified asset.\n *\n * @param asset The asset you want to export\n * @return An asset export session initialized to export `asset`.\n */\n+ (id)exportSessionWithAsset:(AVAsset *)asset;\n\n/**\n * Initializes an asset export session with a specified asset.\n *\n * @param asset The asset you want to export\n * @return An asset export session initialized to export `asset`.\n */\n- (id)initWithAsset:(AVAsset *)asset;\n\n/**\n * Starts the asynchronous execution of an export session.\n *\n * This method starts an asynchronous export operation and returns immediately. status signals the terminal\n * state of the export session, and if a failure occurs, error describes the problem.\n *\n * If internal preparation for export fails, handler is invoked synchronously. The handler may also be called\n * asynchronously, after the method returns, in the following cases:\n *\n * 1. If a failure occurs during the export, including failures of loading, re-encoding, or writing media data to the output.\n * 2. If cancelExport is invoked.\n * 3. After the export session succeeds, having completely written its output to the outputURL.\n *\n * @param handler A block that is invoked when writing is complete or in the event of writing failure.\n */\n- (void)exportAsynchronouslyWithCompletionHandler:(void (^)())handler;\n\n/**\n * Cancels the execution of an export session.\n *\n * You can invoke this method when the export is running.\n */\n- (void)cancelExport;\n\n@end\n\n\n@protocol SDAVAssetExportSessionDelegate <NSObject>\n\n- (void)exportSession:(SDAVAssetExportSession *)exportSession renderFrame:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime toBuffer:(CVPixelBufferRef)renderBuffer;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/SDAVAssetExportSession.m",
    "content": "//\n//  SDAVAssetExportSession.m\n//\n// This file is part of the SDAVAssetExportSession package.\n//\n// Created by Olivier Poitrey <rs@dailymotion.com> on 13/03/13.\n// Copyright 2013 Olivier Poitrey. All rights servered.\n//\n// For the full copyright and license information, please view the LICENSE\n// file that was distributed with this source code.\n//\n\n\n#import \"SDAVAssetExportSession.h\"\n\n@interface SDAVAssetExportSession ()\n\n@property (nonatomic, assign, readwrite) float progress;\n\n@property (nonatomic, strong) AVAssetReader *reader;\n@property (nonatomic, strong) AVAssetReaderVideoCompositionOutput *videoOutput;\n@property (nonatomic, strong) AVAssetReaderAudioMixOutput *audioOutput;\n@property (nonatomic, strong) AVAssetWriter *writer;\n@property (nonatomic, strong) AVAssetWriterInput *videoInput;\n@property (nonatomic, strong) AVAssetWriterInputPixelBufferAdaptor *videoPixelBufferAdaptor;\n@property (nonatomic, strong) AVAssetWriterInput *audioInput;\n@property (nonatomic, strong) dispatch_queue_t inputQueue;\n@property (nonatomic, strong) void (^completionHandler)();\n\n@end\n\n@implementation SDAVAssetExportSession\n{\n    NSError *_error;\n    NSTimeInterval duration;\n    CMTime lastSamplePresentationTime;\n}\n\n+ (id)exportSessionWithAsset:(AVAsset *)asset\n{\n    return [SDAVAssetExportSession.alloc initWithAsset:asset];\n}\n\n- (id)initWithAsset:(AVAsset *)asset\n{\n    if ((self = [super init]))\n    {\n        _asset = asset;\n        _timeRange = CMTimeRangeMake(kCMTimeZero, kCMTimePositiveInfinity);\n    }\n\n    return self;\n}\n\n- (void)exportAsynchronouslyWithCompletionHandler:(void (^)())handler\n{\n    NSParameterAssert(handler != nil);\n    [self cancelExport];\n    self.completionHandler = handler;\n\n    if (!self.outputURL)\n    {\n        _error = [NSError errorWithDomain:AVFoundationErrorDomain code:AVErrorExportFailed userInfo:@\n        {\n            NSLocalizedDescriptionKey: @\"Output URL not set\"\n        }];\n        handler();\n        return;\n    }\n\n    NSError *readerError;\n    self.reader = [AVAssetReader.alloc initWithAsset:self.asset error:&readerError];\n    if (readerError)\n    {\n        _error = readerError;\n        handler();\n        return;\n    }\n\n    NSError *writerError;\n    self.writer = [AVAssetWriter assetWriterWithURL:self.outputURL fileType:self.outputFileType error:&writerError];\n    if (writerError)\n    {\n        _error = writerError;\n        handler();\n        return;\n    }\n\n    self.reader.timeRange = self.timeRange;\n    self.writer.shouldOptimizeForNetworkUse = self.shouldOptimizeForNetworkUse;\n    self.writer.metadata = self.metadata;\n\n    NSArray *videoTracks = [self.asset tracksWithMediaType:AVMediaTypeVideo];\n\n\n    if (CMTIME_IS_VALID(self.timeRange.duration) && !CMTIME_IS_POSITIVE_INFINITY(self.timeRange.duration))\n    {\n        duration = CMTimeGetSeconds(self.timeRange.duration);\n    }\n    else\n    {\n        duration = CMTimeGetSeconds(self.asset.duration);\n    }\n    //\n    // Video output\n    //\n    if (videoTracks.count > 0) {\n        self.videoOutput = [AVAssetReaderVideoCompositionOutput assetReaderVideoCompositionOutputWithVideoTracks:videoTracks videoSettings:self.videoInputSettings];\n        self.videoOutput.alwaysCopiesSampleData = NO;\n        if (self.videoComposition)\n        {\n            self.videoOutput.videoComposition = self.videoComposition;\n        }\n        else\n        {\n            self.videoOutput.videoComposition = [self buildDefaultVideoComposition];\n        }\n        if ([self.reader canAddOutput:self.videoOutput])\n        {\n            [self.reader addOutput:self.videoOutput];\n        }\n\n        //\n        // Video input\n        //\n        self.videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:self.videoSettings];\n        self.videoInput.expectsMediaDataInRealTime = NO;\n        if ([self.writer canAddInput:self.videoInput])\n        {\n            [self.writer addInput:self.videoInput];\n        }\n        NSDictionary *pixelBufferAttributes = @\n        {\n            (id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),\n            (id)kCVPixelBufferWidthKey: @(self.videoOutput.videoComposition.renderSize.width),\n            (id)kCVPixelBufferHeightKey: @(self.videoOutput.videoComposition.renderSize.height),\n            @\"IOSurfaceOpenGLESTextureCompatibility\": @YES,\n            @\"IOSurfaceOpenGLESFBOCompatibility\": @YES,\n        };\n        self.videoPixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:self.videoInput sourcePixelBufferAttributes:pixelBufferAttributes];\n    }\n\n    //\n    //Audio output\n    //\n    NSArray *audioTracks = [self.asset tracksWithMediaType:AVMediaTypeAudio];\n    if (audioTracks.count > 0) {\n      self.audioOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:audioTracks audioSettings:nil];\n      self.audioOutput.alwaysCopiesSampleData = NO;\n      self.audioOutput.audioMix = self.audioMix;\n      if ([self.reader canAddOutput:self.audioOutput])\n      {\n          [self.reader addOutput:self.audioOutput];\n      }\n    } else {\n        // Just in case this gets reused\n        self.audioOutput = nil;\n    }\n\n    //\n    // Audio input\n    //\n    if (self.audioOutput) {\n        self.audioInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:self.audioSettings];\n        self.audioInput.expectsMediaDataInRealTime = NO;\n        if ([self.writer canAddInput:self.audioInput])\n        {\n            [self.writer addInput:self.audioInput];\n        }\n    }\n    \n    [self.writer startWriting];\n    [self.reader startReading];\n    [self.writer startSessionAtSourceTime:self.timeRange.start];\n\n    __block BOOL videoCompleted = NO;\n    __block BOOL audioCompleted = NO;\n    __weak typeof(self) wself = self;\n    self.inputQueue = dispatch_queue_create(\"VideoEncoderInputQueue\", DISPATCH_QUEUE_SERIAL);\n    if (videoTracks.count > 0) {\n        NSLog(@\"%ld\", (long)[self.writer status]);\n        if(self.writer.error) {\n            NSLog(@\"%@\", self.writer.error.localizedDescription);\n        }\n        \n        [self.videoInput requestMediaDataWhenReadyOnQueue:self.inputQueue usingBlock:^\n        {\n            if (![wself encodeReadySamplesFromOutput:wself.videoOutput toInput:wself.videoInput])\n            {\n                @synchronized(wself)\n                {\n                    videoCompleted = YES;\n                    if (audioCompleted)\n                    {\n                        [wself finish];\n                    }\n                }\n            }\n        }];\n    }\n    else {\n        videoCompleted = YES;\n    }\n    \n    if (!self.audioOutput) {\n        audioCompleted = YES;\n    } else {\n        [self.audioInput requestMediaDataWhenReadyOnQueue:self.inputQueue usingBlock:^\n         {\n             if (![wself encodeReadySamplesFromOutput:wself.audioOutput toInput:wself.audioInput])\n             {\n                 @synchronized(wself)\n                 {\n                     audioCompleted = YES;\n                     if (videoCompleted)\n                     {\n                         [wself finish];\n                     }\n                 }\n             }\n         }];\n    }\n}\n\n- (BOOL)encodeReadySamplesFromOutput:(AVAssetReaderOutput *)output toInput:(AVAssetWriterInput *)input\n{\n    while (input.isReadyForMoreMediaData)\n    {\n        CMSampleBufferRef sampleBuffer = [output copyNextSampleBuffer];\n        if (sampleBuffer)\n        {\n            BOOL handled = NO;\n            BOOL error = NO;\n\n            if (self.reader.status != AVAssetReaderStatusReading || self.writer.status != AVAssetWriterStatusWriting)\n            {\n                handled = YES;\n                error = YES;\n            }\n            \n            if (!handled && self.videoOutput == output)\n            {\n                // update the video progress\n                lastSamplePresentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);\n                lastSamplePresentationTime = CMTimeSubtract(lastSamplePresentationTime, self.timeRange.start);\n                self.progress = duration == 0 ? 1 : CMTimeGetSeconds(lastSamplePresentationTime) / duration;\n\n                if ([self.delegate respondsToSelector:@selector(exportSession:renderFrame:withPresentationTime:toBuffer:)])\n                {\n                    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);\n                    CVPixelBufferRef renderBuffer = NULL;\n                    CVPixelBufferPoolCreatePixelBuffer(NULL, self.videoPixelBufferAdaptor.pixelBufferPool, &renderBuffer);\n                    [self.delegate exportSession:self renderFrame:pixelBuffer withPresentationTime:lastSamplePresentationTime toBuffer:renderBuffer];\n                    if (![self.videoPixelBufferAdaptor appendPixelBuffer:renderBuffer withPresentationTime:lastSamplePresentationTime])\n                    {\n                        error = YES;\n                    }\n                    CVPixelBufferRelease(renderBuffer);\n                    handled = YES;\n                }\n            }\n            if (!handled && ![input appendSampleBuffer:sampleBuffer])\n            {\n                error = YES;\n            }\n            CFRelease(sampleBuffer);\n\n            if (error)\n            {\n                return NO;\n            }\n        }\n        else\n        {\n            [input markAsFinished];\n            return NO;\n        }\n    }\n\n    return YES;\n}\n\n- (AVMutableVideoComposition *)buildDefaultVideoComposition\n{\n    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];\n    AVAssetTrack *videoTrack = [[self.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];\n\n    // get the frame rate from videoSettings, if not set then try to get it from the video track,\n    // if not set (mainly when asset is AVComposition) then use the default frame rate of 30\n    float trackFrameRate = 0;\n    if (self.videoSettings)\n    {\n        NSDictionary *videoCompressionProperties = [self.videoSettings objectForKey:AVVideoCompressionPropertiesKey];\n        if (videoCompressionProperties)\n        {\n            NSNumber *frameRate = [videoCompressionProperties objectForKey:AVVideoAverageNonDroppableFrameRateKey];\n            if (frameRate)\n            {\n                trackFrameRate = frameRate.floatValue;\n            }\n        }\n    }\n    else\n    {\n        trackFrameRate = [videoTrack nominalFrameRate];\n    }\n\n    if (trackFrameRate == 0)\n    {\n        trackFrameRate = 30;\n    }\n\n\tvideoComposition.frameDuration = CMTimeMake(1, trackFrameRate);\n\tCGSize targetSize = CGSizeMake([self.videoSettings[AVVideoWidthKey] floatValue], [self.videoSettings[AVVideoHeightKey] floatValue]);\n\tCGSize naturalSize = [videoTrack naturalSize];\n\tCGAffineTransform transform = videoTrack.preferredTransform;\n\tCGFloat videoAngleInDegree  = atan2(transform.b, transform.a) * 180 / M_PI;\n\tif (videoAngleInDegree == 90 || videoAngleInDegree == -90) {\n\t\tCGFloat width = naturalSize.width;\n\t\tnaturalSize.width = naturalSize.height;\n\t\tnaturalSize.height = width;\n\t}\n\tvideoComposition.renderSize = naturalSize;\n\t// center inside\n\t{\n\t\tfloat ratio;\n\t\tfloat xratio = targetSize.width / naturalSize.width;\n\t\tfloat yratio = targetSize.height / naturalSize.height;\n\t\tratio = MIN(xratio, yratio);\n\n\t\tfloat postWidth = naturalSize.width * ratio;\n\t\tfloat postHeight = naturalSize.height * ratio;\n\t\tfloat transx = (targetSize.width - postWidth) / 2;\n\t\tfloat transy = (targetSize.height - postHeight) / 2;\n\n\t\tCGAffineTransform matrix = CGAffineTransformMakeTranslation(transx / xratio, transy / yratio);\n\t\tmatrix = CGAffineTransformScale(matrix, ratio / xratio, ratio / yratio);\n\t\ttransform = CGAffineTransformConcat(transform, matrix);\n\t}\n\n\t// Make a \"pass through video track\" video composition.\n\tAVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];\n\tpassThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, self.asset.duration);\n\n\tAVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];\n\n    [passThroughLayer setTransform:transform atTime:kCMTimeZero];\n\n\tpassThroughInstruction.layerInstructions = @[passThroughLayer];\n\tvideoComposition.instructions = @[passThroughInstruction];\n\n    return videoComposition;\n}\n\n- (void)finish\n{\n    // Synchronized block to ensure we never cancel the writer before calling finishWritingWithCompletionHandler\n    if (self.reader.status == AVAssetReaderStatusCancelled || self.writer.status == AVAssetWriterStatusCancelled)\n    {\n        return;\n    }\n\n    if (self.writer.status == AVAssetWriterStatusFailed)\n    {\n        [self complete];\n    }\n    else if (self.reader.status == AVAssetReaderStatusFailed) {\n        [self.writer cancelWriting];\n        [self complete];\n    }\n    else\n    {\n        [self.writer finishWritingWithCompletionHandler:^\n        {\n            [self complete];\n        }];\n    }\n}\n\n- (void)complete\n{\n    if (self.writer.status == AVAssetWriterStatusFailed || self.writer.status == AVAssetWriterStatusCancelled)\n    {\n        [NSFileManager.defaultManager removeItemAtURL:self.outputURL error:nil];\n    }\n\n    if (self.completionHandler)\n    {\n        self.completionHandler();\n        self.completionHandler = nil;\n    }\n}\n\n- (NSError *)error\n{\n    if (_error)\n    {\n        return _error;\n    }\n    else\n    {\n        return self.writer.error ? : self.reader.error;\n    }\n}\n\n- (AVAssetExportSessionStatus)status\n{\n    switch (self.writer.status)\n    {\n        default:\n        case AVAssetWriterStatusUnknown:\n            return AVAssetExportSessionStatusUnknown;\n        case AVAssetWriterStatusWriting:\n            return AVAssetExportSessionStatusExporting;\n        case AVAssetWriterStatusFailed:\n            return AVAssetExportSessionStatusFailed;\n        case AVAssetWriterStatusCompleted:\n            return AVAssetExportSessionStatusCompleted;\n        case AVAssetWriterStatusCancelled:\n            return AVAssetExportSessionStatusCancelled;\n    }\n}\n\n- (void)cancelExport\n{\n    if (self.inputQueue)\n    {\n        dispatch_async(self.inputQueue, ^\n        {\n            [self.writer cancelWriting];\n            [self.reader cancelReading];\n            [self complete];\n            [self reset];\n        });\n    }\n}\n\n- (void)reset\n{\n    _error = nil;\n    self.progress = 0;\n    self.reader = nil;\n    self.videoOutput = nil;\n    self.audioOutput = nil;\n    self.writer = nil;\n    self.videoInput = nil;\n    self.videoPixelBufferAdaptor = nil;\n    self.audioInput = nil;\n    self.inputQueue = nil;\n    self.completionHandler = nil;\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/iDebounce.h",
    "content": "#import <Foundation/Foundation.h>\n\ntypedef void (^iDebounceBlock)();\n\n@interface iDebounce : NSObject\n\n+(instancetype)sharedInstance;\n\n+(void)debounce:( iDebounceBlock )block withIdentifier:(NSString *)identifier wait:( NSTimeInterval )seconds;\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework/iDebounce.m",
    "content": "#import \"iDebounce.h\"\n\n@interface iDebounce()\n\n@property (nonatomic, strong) NSMutableDictionary *iDebounceBlockMap;\n\n@end\n\n@implementation iDebounce\n\n+(instancetype)sharedInstance {\n\n    static iDebounce *_sharedInstance = nil;\n    static dispatch_once_t onceToken;\n\n    dispatch_once( &onceToken, ^{\n        _sharedInstance = [iDebounce new];\n    });\n\n    return _sharedInstance;\n}\n\n+(void)debounce:( iDebounceBlock )block withIdentifier:(NSString *)identifier wait:( NSTimeInterval )seconds {\n    dispatch_async(dispatch_get_main_queue(), ^{\n        iDebounce *instance = [[self class] sharedInstance];\n\n        if( [instance.iDebounceBlockMap objectForKey:identifier] ) {\n            return;\n        }\n\n\n        [[NSRunLoop mainRunLoop] addTimer:[NSTimer scheduledTimerWithTimeInterval:seconds target:instance selector:@selector( executeDebouncedBlockForTimer: ) userInfo:@{ @\"name\": identifier } repeats:NO] forMode:NSRunLoopCommonModes];\n\n        [instance.iDebounceBlockMap setObject:block forKey:identifier];\n    });\n}\n\n\n-(instancetype)init {\n\n    self = [super init];\n    if( !self ) {\n        return nil;\n    }\n\n    _iDebounceBlockMap = [NSMutableDictionary dictionary];\n\n    return self;\n}\n\n-(void)executeDebouncedBlockForTimer:(NSTimer *)timer {\n\n    NSString *methodIdentifier = [timer.userInfo[@\"name\"] copy];\n    if( self.iDebounceBlockMap[methodIdentifier] ) {\n\n        NSLog( @\"Executing iDebounce block having identifier = %@\", methodIdentifier );\n\n        iDebounceBlock block = [self.iDebounceBlockMap[methodIdentifier] copy];\n        if (block != nil) {\n            block();\n        }\n\n        [self.iDebounceBlockMap removeObjectForKey:methodIdentifier];\n    }\n\n    [timer invalidate];\n}\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFramework.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t6302902D1E0C7A1900A39835 /* PHAssetWithCollectionIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 6302902C1E0C7A1900A39835 /* PHAssetWithCollectionIndex.m */; };\n\t\t6326189F1F5C85C4008A3E90 /* PHCancellationTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 6326189E1F5C85C4008A3E90 /* PHCancellationTokenManager.m */; };\n\t\t632618A21F5C85E4008A3E90 /* PHCancellationToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 632618A11F5C85E4008A3E90 /* PHCancellationToken.m */; };\n\t\t632D5ED31DF19458006A862C /* PHAssetsService_getAssetsForFetchResultTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 632D5ED21DF19458006A862C /* PHAssetsService_getAssetsForFetchResultTests.m */; };\n\t\t632D5ED51DF19458006A862C /* libRNPhotosFramework.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 632F8C131DB758E7007E83E1 /* libRNPhotosFramework.a */; };\n\t\t632D5EDD1DF19526006A862C /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 632D5EDC1DF19526006A862C /* libReact.a */; };\n\t\t632F8C251DB75A4A007E83E1 /* PHCachingImageManagerInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = 632F8C201DB75A4A007E83E1 /* PHCachingImageManagerInstance.m */; };\n\t\t632F8C261DB75A4A007E83E1 /* RNPFManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 632F8C221DB75A4A007E83E1 /* RNPFManager.m */; };\n\t\t632F8C271DB75A4A007E83E1 /* RNPFImageLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 632F8C241DB75A4A007E83E1 /* RNPFImageLoader.m */; };\n\t\t6342E0701DC346E300F7765E /* PHSaveAssetRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6342E06F1DC346E300F7765E /* PHSaveAssetRequest.m */; };\n\t\t63880A7B1E1281F3007532B2 /* RCTConvert+RNPhotosFrameworkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63880A7A1E1281F3007532B2 /* RCTConvert+RNPhotosFrameworkTests.m */; };\n\t\t6394ACE61EA6AB4800AC445F /* ImageHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6394ACE51EA6AB4800AC445F /* ImageHelpers.m */; };\n\t\t6394ACE91EA6AB5600AC445F /* RCTImageResizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6394ACE81EA6AB5600AC445F /* RCTImageResizer.m */; };\n\t\t639BE3591DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.m in Sources */ = {isa = PBXBuildFile; fileRef = 639BE3581DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.m */; };\n\t\t639BE3661DBB902E00A2BE6F /* PHChangeObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 639BE3651DBB902E00A2BE6F /* PHChangeObserver.m */; };\n\t\t63A33AA51DBE94350022B5FF /* PHCachedFetchResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 63A33AA41DBE94350022B5FF /* PHCachedFetchResult.m */; };\n\t\t63A33AA81DBE9D3F0022B5FF /* PHAssetsService.m in Sources */ = {isa = PBXBuildFile; fileRef = 63A33AA71DBE9D3F0022B5FF /* PHAssetsService.m */; };\n\t\t63A33AAE1DBE9DB80022B5FF /* PHFetchOptionsService.m in Sources */ = {isa = PBXBuildFile; fileRef = 63A33AAD1DBE9DB80022B5FF /* PHFetchOptionsService.m */; };\n\t\t63A33AB11DBEA06C0022B5FF /* PHCollectionService.m in Sources */ = {isa = PBXBuildFile; fileRef = 63A33AB01DBEA06C0022B5FF /* PHCollectionService.m */; };\n\t\t63C543481DC00BDA004BFE57 /* RNPFHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 63C543471DC00BDA004BFE57 /* RNPFHelpers.m */; };\n\t\t63D8F94B1E65C7F200A74433 /* RNPFUrlRequestHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 63D8F94A1E65C7F200A74433 /* RNPFUrlRequestHandler.m */; };\n\t\t63DCC8E71EA750ED000E46F9 /* PHSaveAssetFileRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 63DCC8E61EA750ED000E46F9 /* PHSaveAssetFileRequest.m */; };\n\t\t63DCC8EA1EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 63DCC8E91EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.m */; };\n\t\t63DCC8F01EA7945F000E46F9 /* PHVideoExporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 63DCC8EF1EA7945F000E46F9 /* PHVideoExporter.m */; };\n\t\t63DCC8F31EA7CA42000E46F9 /* SDAVAssetExportSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 63DCC8F21EA7CA42000E46F9 /* SDAVAssetExportSession.m */; };\n\t\t8C2A0F491E22FBB500E31596 /* PHSaveAsset.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2A0F481E22FBB500E31596 /* PHSaveAsset.m */; };\n\t\t8C2A0FB81E2584F300E31596 /* RNPFFileDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2A0FB71E2584F300E31596 /* RNPFFileDownloader.m */; };\n\t\t8C2A0FC71E2788F800E31596 /* PHCreateMediaQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2A0FC61E2788F800E31596 /* PHCreateMediaQueue.m */; };\n\t\t8C2A0FCA1E27940300E31596 /* PHOperationResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2A0FC91E27940300E31596 /* PHOperationResult.m */; };\n\t\t8C2A0FCD1E2826E300E31596 /* iDebounce.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2A0FCC1E2826E200E31596 /* iDebounce.m */; };\n\t\t8C2A0FD01E283B6400E31596 /* PHCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C2A0FCF1E283B6400E31596 /* PHCache.m */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t632D5ED61DF19458006A862C /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 632F8C0B1DB758E6007E83E1 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 632F8C121DB758E6007E83E1;\n\t\t\tremoteInfo = RNPhotosFramework;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t632F8C111DB758E6007E83E1 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"include/$(PRODUCT_NAME)\";\n\t\t\tdstSubfolderSpec = 16;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t6302902B1E0C7A1900A39835 /* PHAssetWithCollectionIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHAssetWithCollectionIndex.h; sourceTree = \"<group>\"; };\n\t\t6302902C1E0C7A1900A39835 /* PHAssetWithCollectionIndex.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHAssetWithCollectionIndex.m; sourceTree = \"<group>\"; };\n\t\t6326189D1F5C85C4008A3E90 /* PHCancellationTokenManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCancellationTokenManager.h; sourceTree = \"<group>\"; };\n\t\t6326189E1F5C85C4008A3E90 /* PHCancellationTokenManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCancellationTokenManager.m; sourceTree = \"<group>\"; };\n\t\t632618A01F5C85E4008A3E90 /* PHCancellationToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCancellationToken.h; sourceTree = \"<group>\"; };\n\t\t632618A11F5C85E4008A3E90 /* PHCancellationToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCancellationToken.m; sourceTree = \"<group>\"; };\n\t\t632D5ED01DF19458006A862C /* RNPhotosFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNPhotosFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t632D5ED21DF19458006A862C /* PHAssetsService_getAssetsForFetchResultTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PHAssetsService_getAssetsForFetchResultTests.m; sourceTree = \"<group>\"; };\n\t\t632D5ED41DF19458006A862C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t632D5EDC1DF19526006A862C /* libReact.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libReact.a; path = \"../node_modules/react-native/React/build/Debug-iphoneos/libReact.a\"; sourceTree = \"<group>\"; };\n\t\t632F8C131DB758E7007E83E1 /* libRNPhotosFramework.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNPhotosFramework.a; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t632F8C1F1DB75A4A007E83E1 /* PHCachingImageManagerInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCachingImageManagerInstance.h; sourceTree = \"<group>\"; };\n\t\t632F8C201DB75A4A007E83E1 /* PHCachingImageManagerInstance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCachingImageManagerInstance.m; sourceTree = \"<group>\"; };\n\t\t632F8C211DB75A4A007E83E1 /* RNPFManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPFManager.h; sourceTree = \"<group>\"; };\n\t\t632F8C221DB75A4A007E83E1 /* RNPFManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPFManager.m; sourceTree = \"<group>\"; };\n\t\t632F8C231DB75A4A007E83E1 /* RNPFImageLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPFImageLoader.h; sourceTree = \"<group>\"; };\n\t\t632F8C241DB75A4A007E83E1 /* RNPFImageLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPFImageLoader.m; sourceTree = \"<group>\"; };\n\t\t6342E06E1DC346E300F7765E /* PHSaveAssetRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHSaveAssetRequest.h; sourceTree = \"<group>\"; };\n\t\t6342E06F1DC346E300F7765E /* PHSaveAssetRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHSaveAssetRequest.m; sourceTree = \"<group>\"; };\n\t\t6349B2B91E6700DF00A153FD /* RNPFGlobals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPFGlobals.h; sourceTree = \"<group>\"; };\n\t\t63880A7A1E1281F3007532B2 /* RCTConvert+RNPhotosFrameworkTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"RCTConvert+RNPhotosFrameworkTests.m\"; sourceTree = \"<group>\"; };\n\t\t6394ACE41EA6AB4800AC445F /* ImageHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageHelpers.h; sourceTree = \"<group>\"; };\n\t\t6394ACE51EA6AB4800AC445F /* ImageHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageHelpers.m; sourceTree = \"<group>\"; };\n\t\t6394ACE71EA6AB5600AC445F /* RCTImageResizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTImageResizer.h; sourceTree = \"<group>\"; };\n\t\t6394ACE81EA6AB5600AC445F /* RCTImageResizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTImageResizer.m; sourceTree = \"<group>\"; };\n\t\t639BE3571DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"RCTConvert+RNPhotosFramework.h\"; sourceTree = \"<group>\"; };\n\t\t639BE3581DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = \"RCTConvert+RNPhotosFramework.m\"; sourceTree = \"<group>\"; };\n\t\t639BE3641DBB902E00A2BE6F /* PHChangeObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHChangeObserver.h; sourceTree = \"<group>\"; };\n\t\t639BE3651DBB902E00A2BE6F /* PHChangeObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHChangeObserver.m; sourceTree = \"<group>\"; };\n\t\t63A33AA31DBE94350022B5FF /* PHCachedFetchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCachedFetchResult.h; sourceTree = \"<group>\"; };\n\t\t63A33AA41DBE94350022B5FF /* PHCachedFetchResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCachedFetchResult.m; sourceTree = \"<group>\"; };\n\t\t63A33AA61DBE9D3F0022B5FF /* PHAssetsService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHAssetsService.h; sourceTree = \"<group>\"; };\n\t\t63A33AA71DBE9D3F0022B5FF /* PHAssetsService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHAssetsService.m; sourceTree = \"<group>\"; };\n\t\t63A33AAC1DBE9DB80022B5FF /* PHFetchOptionsService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHFetchOptionsService.h; sourceTree = \"<group>\"; };\n\t\t63A33AAD1DBE9DB80022B5FF /* PHFetchOptionsService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHFetchOptionsService.m; sourceTree = \"<group>\"; };\n\t\t63A33AAF1DBEA06C0022B5FF /* PHCollectionService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCollectionService.h; sourceTree = \"<group>\"; };\n\t\t63A33AB01DBEA06C0022B5FF /* PHCollectionService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCollectionService.m; sourceTree = \"<group>\"; };\n\t\t63C543461DC00BDA004BFE57 /* RNPFHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPFHelpers.h; sourceTree = \"<group>\"; };\n\t\t63C543471DC00BDA004BFE57 /* RNPFHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPFHelpers.m; sourceTree = \"<group>\"; };\n\t\t63D8F9491E65C7F200A74433 /* RNPFUrlRequestHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPFUrlRequestHandler.h; sourceTree = \"<group>\"; };\n\t\t63D8F94A1E65C7F200A74433 /* RNPFUrlRequestHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPFUrlRequestHandler.m; sourceTree = \"<group>\"; };\n\t\t63DCC8E51EA750ED000E46F9 /* PHSaveAssetFileRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHSaveAssetFileRequest.h; sourceTree = \"<group>\"; };\n\t\t63DCC8E61EA750ED000E46F9 /* PHSaveAssetFileRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHSaveAssetFileRequest.m; sourceTree = \"<group>\"; };\n\t\t63DCC8E81EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHSaveAssetToFileOperationResult.h; sourceTree = \"<group>\"; };\n\t\t63DCC8E91EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHSaveAssetToFileOperationResult.m; sourceTree = \"<group>\"; };\n\t\t63DCC8EE1EA7945F000E46F9 /* PHVideoExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHVideoExporter.h; sourceTree = \"<group>\"; };\n\t\t63DCC8EF1EA7945F000E46F9 /* PHVideoExporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHVideoExporter.m; sourceTree = \"<group>\"; };\n\t\t63DCC8F11EA7CA42000E46F9 /* SDAVAssetExportSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAVAssetExportSession.h; sourceTree = \"<group>\"; };\n\t\t63DCC8F21EA7CA42000E46F9 /* SDAVAssetExportSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAVAssetExportSession.m; sourceTree = \"<group>\"; };\n\t\t8C2A0F471E22FBB500E31596 /* PHSaveAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHSaveAsset.h; sourceTree = \"<group>\"; };\n\t\t8C2A0F481E22FBB500E31596 /* PHSaveAsset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHSaveAsset.m; sourceTree = \"<group>\"; };\n\t\t8C2A0FB61E2584F300E31596 /* RNPFFileDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNPFFileDownloader.h; sourceTree = \"<group>\"; };\n\t\t8C2A0FB71E2584F300E31596 /* RNPFFileDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNPFFileDownloader.m; sourceTree = \"<group>\"; };\n\t\t8C2A0FC51E2788F800E31596 /* PHCreateMediaQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCreateMediaQueue.h; sourceTree = \"<group>\"; };\n\t\t8C2A0FC61E2788F800E31596 /* PHCreateMediaQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCreateMediaQueue.m; sourceTree = \"<group>\"; };\n\t\t8C2A0FC81E27940300E31596 /* PHOperationResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHOperationResult.h; sourceTree = \"<group>\"; };\n\t\t8C2A0FC91E27940300E31596 /* PHOperationResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHOperationResult.m; sourceTree = \"<group>\"; };\n\t\t8C2A0FCB1E2826E200E31596 /* iDebounce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iDebounce.h; sourceTree = \"<group>\"; };\n\t\t8C2A0FCC1E2826E200E31596 /* iDebounce.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iDebounce.m; sourceTree = \"<group>\"; };\n\t\t8C2A0FCE1E283B6400E31596 /* PHCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PHCache.h; sourceTree = \"<group>\"; };\n\t\t8C2A0FCF1E283B6400E31596 /* PHCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PHCache.m; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t632D5ECD1DF19458006A862C /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t632D5EDD1DF19526006A862C /* libReact.a in Frameworks */,\n\t\t\t\t632D5ED51DF19458006A862C /* libRNPhotosFramework.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t632F8C101DB758E6007E83E1 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t632D5ED11DF19458006A862C /* RNPhotosFrameworkTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t632D5ED21DF19458006A862C /* PHAssetsService_getAssetsForFetchResultTests.m */,\n\t\t\t\t632D5ED41DF19458006A862C /* Info.plist */,\n\t\t\t\t63880A7A1E1281F3007532B2 /* RCTConvert+RNPhotosFrameworkTests.m */,\n\t\t\t);\n\t\t\tpath = RNPhotosFrameworkTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t632D5EDB1DF19525006A862C /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t632D5EDC1DF19526006A862C /* libReact.a */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t632F8C0A1DB758E6007E83E1 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t632F8C151DB758E7007E83E1 /* RNPhotosFramework */,\n\t\t\t\t632D5ED11DF19458006A862C /* RNPhotosFrameworkTests */,\n\t\t\t\t632F8C141DB758E7007E83E1 /* Products */,\n\t\t\t\t632D5EDB1DF19525006A862C /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t632F8C141DB758E7007E83E1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t632F8C131DB758E7007E83E1 /* libRNPhotosFramework.a */,\n\t\t\t\t632D5ED01DF19458006A862C /* RNPhotosFrameworkTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t632F8C151DB758E7007E83E1 /* RNPhotosFramework */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8CA929DD1E1FAE0200F79455 /* PHServices */,\n\t\t\t\t8CA929DC1E1FADDA00F79455 /* Models */,\n\t\t\t\t8CA929DB1E1FADB900F79455 /* Base */,\n\t\t\t\t632F8C231DB75A4A007E83E1 /* RNPFImageLoader.h */,\n\t\t\t\t632F8C241DB75A4A007E83E1 /* RNPFImageLoader.m */,\n\t\t\t\t632F8C211DB75A4A007E83E1 /* RNPFManager.h */,\n\t\t\t\t632F8C221DB75A4A007E83E1 /* RNPFManager.m */,\n\t\t\t\t63D8F9491E65C7F200A74433 /* RNPFUrlRequestHandler.h */,\n\t\t\t\t63D8F94A1E65C7F200A74433 /* RNPFUrlRequestHandler.m */,\n\t\t\t\t6349B2B91E6700DF00A153FD /* RNPFGlobals.h */,\n\t\t\t);\n\t\t\tpath = RNPhotosFramework;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t8CA929DB1E1FADB900F79455 /* Base */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t63DCC8F11EA7CA42000E46F9 /* SDAVAssetExportSession.h */,\n\t\t\t\t63DCC8F21EA7CA42000E46F9 /* SDAVAssetExportSession.m */,\n\t\t\t\t6394ACE71EA6AB5600AC445F /* RCTImageResizer.h */,\n\t\t\t\t6394ACE81EA6AB5600AC445F /* RCTImageResizer.m */,\n\t\t\t\t6394ACE41EA6AB4800AC445F /* ImageHelpers.h */,\n\t\t\t\t6394ACE51EA6AB4800AC445F /* ImageHelpers.m */,\n\t\t\t\t639BE3571DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.h */,\n\t\t\t\t639BE3581DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.m */,\n\t\t\t\t63C543461DC00BDA004BFE57 /* RNPFHelpers.h */,\n\t\t\t\t63C543471DC00BDA004BFE57 /* RNPFHelpers.m */,\n\t\t\t\t8C2A0FB61E2584F300E31596 /* RNPFFileDownloader.h */,\n\t\t\t\t8C2A0FB71E2584F300E31596 /* RNPFFileDownloader.m */,\n\t\t\t\t63DCC8EE1EA7945F000E46F9 /* PHVideoExporter.h */,\n\t\t\t\t63DCC8EF1EA7945F000E46F9 /* PHVideoExporter.m */,\n\t\t\t);\n\t\t\tname = Base;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t8CA929DC1E1FADDA00F79455 /* Models */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t63DCC8E81EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.h */,\n\t\t\t\t63DCC8E91EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.m */,\n\t\t\t\t63DCC8E51EA750ED000E46F9 /* PHSaveAssetFileRequest.h */,\n\t\t\t\t63DCC8E61EA750ED000E46F9 /* PHSaveAssetFileRequest.m */,\n\t\t\t\t8C2A0FCB1E2826E200E31596 /* iDebounce.h */,\n\t\t\t\t8C2A0FCC1E2826E200E31596 /* iDebounce.m */,\n\t\t\t\t6302902B1E0C7A1900A39835 /* PHAssetWithCollectionIndex.h */,\n\t\t\t\t6302902C1E0C7A1900A39835 /* PHAssetWithCollectionIndex.m */,\n\t\t\t\t63A33AA31DBE94350022B5FF /* PHCachedFetchResult.h */,\n\t\t\t\t63A33AA41DBE94350022B5FF /* PHCachedFetchResult.m */,\n\t\t\t\t6342E06E1DC346E300F7765E /* PHSaveAssetRequest.h */,\n\t\t\t\t6342E06F1DC346E300F7765E /* PHSaveAssetRequest.m */,\n\t\t\t\t8C2A0F471E22FBB500E31596 /* PHSaveAsset.h */,\n\t\t\t\t8C2A0F481E22FBB500E31596 /* PHSaveAsset.m */,\n\t\t\t\t8C2A0FC51E2788F800E31596 /* PHCreateMediaQueue.h */,\n\t\t\t\t8C2A0FC61E2788F800E31596 /* PHCreateMediaQueue.m */,\n\t\t\t\t8C2A0FC81E27940300E31596 /* PHOperationResult.h */,\n\t\t\t\t8C2A0FC91E27940300E31596 /* PHOperationResult.m */,\n\t\t\t\t6326189D1F5C85C4008A3E90 /* PHCancellationTokenManager.h */,\n\t\t\t\t6326189E1F5C85C4008A3E90 /* PHCancellationTokenManager.m */,\n\t\t\t\t632618A01F5C85E4008A3E90 /* PHCancellationToken.h */,\n\t\t\t\t632618A11F5C85E4008A3E90 /* PHCancellationToken.m */,\n\t\t\t);\n\t\t\tname = Models;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t8CA929DD1E1FAE0200F79455 /* PHServices */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t63A33AA61DBE9D3F0022B5FF /* PHAssetsService.h */,\n\t\t\t\t63A33AA71DBE9D3F0022B5FF /* PHAssetsService.m */,\n\t\t\t\t63A33AAC1DBE9DB80022B5FF /* PHFetchOptionsService.h */,\n\t\t\t\t63A33AAD1DBE9DB80022B5FF /* PHFetchOptionsService.m */,\n\t\t\t\t63A33AAF1DBEA06C0022B5FF /* PHCollectionService.h */,\n\t\t\t\t63A33AB01DBEA06C0022B5FF /* PHCollectionService.m */,\n\t\t\t\t639BE3641DBB902E00A2BE6F /* PHChangeObserver.h */,\n\t\t\t\t639BE3651DBB902E00A2BE6F /* PHChangeObserver.m */,\n\t\t\t\t632F8C1F1DB75A4A007E83E1 /* PHCachingImageManagerInstance.h */,\n\t\t\t\t632F8C201DB75A4A007E83E1 /* PHCachingImageManagerInstance.m */,\n\t\t\t\t8C2A0FCE1E283B6400E31596 /* PHCache.h */,\n\t\t\t\t8C2A0FCF1E283B6400E31596 /* PHCache.m */,\n\t\t\t);\n\t\t\tname = PHServices;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t632D5ECF1DF19458006A862C /* RNPhotosFrameworkTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 632D5EDA1DF19458006A862C /* Build configuration list for PBXNativeTarget \"RNPhotosFrameworkTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t632D5ECC1DF19458006A862C /* Sources */,\n\t\t\t\t632D5ECD1DF19458006A862C /* Frameworks */,\n\t\t\t\t632D5ECE1DF19458006A862C /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t632D5ED71DF19458006A862C /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = RNPhotosFrameworkTests;\n\t\t\tproductName = RNPhotosFrameworkTests;\n\t\t\tproductReference = 632D5ED01DF19458006A862C /* RNPhotosFrameworkTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t632F8C121DB758E6007E83E1 /* RNPhotosFramework */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 632F8C1C1DB758E7007E83E1 /* Build configuration list for PBXNativeTarget \"RNPhotosFramework\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t632F8C0F1DB758E6007E83E1 /* Sources */,\n\t\t\t\t632F8C101DB758E6007E83E1 /* Frameworks */,\n\t\t\t\t632F8C111DB758E6007E83E1 /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = RNPhotosFramework;\n\t\t\tproductName = RNPhotosFramework;\n\t\t\tproductReference = 632F8C131DB758E7007E83E1 /* libRNPhotosFramework.a */;\n\t\t\tproductType = \"com.apple.product-type.library.static\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t632F8C0B1DB758E6007E83E1 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0820;\n\t\t\t\tORGANIZATIONNAME = \"Olof Dahlbom\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t632D5ECF1DF19458006A862C = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.1;\n\t\t\t\t\t\tDevelopmentTeam = 5BEG6QJ94B;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t632F8C121DB758E6007E83E1 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 8.0;\n\t\t\t\t\t\tDevelopmentTeam = 5BEG6QJ94B;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 632F8C0E1DB758E6007E83E1 /* Build configuration list for PBXProject \"RNPhotosFramework\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 632F8C0A1DB758E6007E83E1;\n\t\t\tproductRefGroup = 632F8C141DB758E7007E83E1 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t632F8C121DB758E6007E83E1 /* RNPhotosFramework */,\n\t\t\t\t632D5ECF1DF19458006A862C /* RNPhotosFrameworkTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t632D5ECE1DF19458006A862C /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t632D5ECC1DF19458006A862C /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t632D5ED31DF19458006A862C /* PHAssetsService_getAssetsForFetchResultTests.m in Sources */,\n\t\t\t\t63880A7B1E1281F3007532B2 /* RCTConvert+RNPhotosFrameworkTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t632F8C0F1DB758E6007E83E1 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6394ACE91EA6AB5600AC445F /* RCTImageResizer.m in Sources */,\n\t\t\t\t632618A21F5C85E4008A3E90 /* PHCancellationToken.m in Sources */,\n\t\t\t\t63DCC8E71EA750ED000E46F9 /* PHSaveAssetFileRequest.m in Sources */,\n\t\t\t\t632F8C251DB75A4A007E83E1 /* PHCachingImageManagerInstance.m in Sources */,\n\t\t\t\t63A33AAE1DBE9DB80022B5FF /* PHFetchOptionsService.m in Sources */,\n\t\t\t\t63A33AA51DBE94350022B5FF /* PHCachedFetchResult.m in Sources */,\n\t\t\t\t6302902D1E0C7A1900A39835 /* PHAssetWithCollectionIndex.m in Sources */,\n\t\t\t\t63A33AB11DBEA06C0022B5FF /* PHCollectionService.m in Sources */,\n\t\t\t\t639BE3591DB82A7C00A2BE6F /* RCTConvert+RNPhotosFramework.m in Sources */,\n\t\t\t\t8C2A0FCA1E27940300E31596 /* PHOperationResult.m in Sources */,\n\t\t\t\t8C2A0FC71E2788F800E31596 /* PHCreateMediaQueue.m in Sources */,\n\t\t\t\t63C543481DC00BDA004BFE57 /* RNPFHelpers.m in Sources */,\n\t\t\t\t632F8C261DB75A4A007E83E1 /* RNPFManager.m in Sources */,\n\t\t\t\t63DCC8F01EA7945F000E46F9 /* PHVideoExporter.m in Sources */,\n\t\t\t\t8C2A0FD01E283B6400E31596 /* PHCache.m in Sources */,\n\t\t\t\t6394ACE61EA6AB4800AC445F /* ImageHelpers.m in Sources */,\n\t\t\t\t63DCC8F31EA7CA42000E46F9 /* SDAVAssetExportSession.m in Sources */,\n\t\t\t\t6326189F1F5C85C4008A3E90 /* PHCancellationTokenManager.m in Sources */,\n\t\t\t\t8C2A0FCD1E2826E300E31596 /* iDebounce.m in Sources */,\n\t\t\t\t63D8F94B1E65C7F200A74433 /* RNPFUrlRequestHandler.m in Sources */,\n\t\t\t\t6342E0701DC346E300F7765E /* PHSaveAssetRequest.m in Sources */,\n\t\t\t\t8C2A0F491E22FBB500E31596 /* PHSaveAsset.m in Sources */,\n\t\t\t\t63A33AA81DBE9D3F0022B5FF /* PHAssetsService.m in Sources */,\n\t\t\t\t8C2A0FB81E2584F300E31596 /* RNPFFileDownloader.m in Sources */,\n\t\t\t\t632F8C271DB75A4A007E83E1 /* RNPFImageLoader.m in Sources */,\n\t\t\t\t63DCC8EA1EA7510D000E46F9 /* PHSaveAssetToFileOperationResult.m in Sources */,\n\t\t\t\t639BE3661DBB902E00A2BE6F /* PHChangeObserver.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t632D5ED71DF19458006A862C /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 632F8C121DB758E6007E83E1 /* RNPhotosFramework */;\n\t\t\ttargetProxy = 632D5ED61DF19458006A862C /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t632D5ED81DF19458006A862C /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SRCROOT)/../../react-native/React/**\",\n\t\t\t\t\t\"$(SRCROOT)/../../react-native/Libraries/Image\",\n\t\t\t\t\t\"$(SRCROOT)/../example/node_modules/react-native/React/**\",\n\t\t\t\t\t\"$(SRCROOT)/../example/node_modules/react-native/Libraries/Image\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = RNPhotosFrameworkTests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 10.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.olof.dahlbom.RNPhotosFrameworkTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t632D5ED91DF19458006A862C /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SRCROOT)/../../react-native/React/**\",\n\t\t\t\t\t\"$(SRCROOT)/../../react-native/Libraries/Image\",\n\t\t\t\t\t\"$(SRCROOT)/../example/node_modules/react-native/React/**\",\n\t\t\t\t\t\"$(SRCROOT)/../example/node_modules/react-native/Libraries/Image\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = RNPhotosFrameworkTests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 10.1;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.olof.dahlbom.RNPhotosFrameworkTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t632F8C1A1DB758E7007E83E1 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 10.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t632F8C1B1DB758E7007E83E1 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVES = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 10.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t632F8C1D1DB758E7007E83E1 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tHEADER_SEARCH_PATHS = \"\";\n\t\t\t\tOTHER_LDFLAGS = \"-ObjC\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t632F8C1E1DB758E7007E83E1 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tDEVELOPMENT_TEAM = 5BEG6QJ94B;\n\t\t\t\tHEADER_SEARCH_PATHS = \"\";\n\t\t\t\tOTHER_LDFLAGS = \"-ObjC\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t632D5EDA1DF19458006A862C /* Build configuration list for PBXNativeTarget \"RNPhotosFrameworkTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t632D5ED81DF19458006A862C /* Debug */,\n\t\t\t\t632D5ED91DF19458006A862C /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t632F8C0E1DB758E6007E83E1 /* Build configuration list for PBXProject \"RNPhotosFramework\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t632F8C1A1DB758E7007E83E1 /* Debug */,\n\t\t\t\t632F8C1B1DB758E7007E83E1 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t632F8C1C1DB758E7007E83E1 /* Build configuration list for PBXNativeTarget \"RNPhotosFramework\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t632F8C1D1DB758E7007E83E1 /* Debug */,\n\t\t\t\t632F8C1E1DB758E7007E83E1 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 632F8C0B1DB758E6007E83E1 /* Project object */;\n}\n"
  },
  {
    "path": "ios/RNPhotosFrameworkTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/RNPhotosFrameworkTests/PHAssetsService_getAssetsForFetchResultTests.m",
    "content": "#pragma clang diagnostic ignored \"-Wincompatible-pointer-types\"\n\n#import <XCTest/XCTest.h>\n#import \"PHAssetsService.h\"\n#import \"RNPFHelpers.h\"\n\n@interface PHAssetsServicegetAssetsForFetchResultTests : XCTestCase\n@end\n\n@implementation PHAssetsServicegetAssetsForFetchResultTests\nNSMutableArray *arrayWithFakeAssets;\nNSMutableArray *scenarioAssets;\n\n\n- (void)setUp {\n    arrayWithFakeAssets = [NSMutableArray new];\n    for(int i = 0; i < 200;i++){\n        [arrayWithFakeAssets addObject:@(i)];\n    }\n    \n    scenarioAssets = [NSMutableArray new];\n    [scenarioAssets addObject:@(2012)];\n    [scenarioAssets addObject:@(2013)];\n    [scenarioAssets addObject:@(2014)];\n    [scenarioAssets addObject:@(2015)];\n    [scenarioAssets addObject:@(2016)];\n\n    [super setUp];\n}\n\n- (void)tearDown {\n    arrayWithFakeAssets = nil;\n    scenarioAssets = nil;\n    [super tearDown];\n}\n\n- (void)testLoad {\n    \n\n\n}\n\n- (void)testShouldReturnEqualAmountOfAssets {\n    NSArray *resultYesYes = [PHAssetsService getAssetsForFetchResult:arrayWithFakeAssets startIndex:5 endIndex:15 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:YES];\n    [self setUp];\n    NSArray *resultYesNo = [PHAssetsService getAssetsForFetchResult:arrayWithFakeAssets startIndex:5 endIndex:15 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:NO];\n    [self setUp];\n    NSArray *resultNoYes = [PHAssetsService getAssetsForFetchResult:arrayWithFakeAssets startIndex:5 endIndex:15 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:NO];\n    [self setUp];\n    NSArray *resultNoNo = [PHAssetsService getAssetsForFetchResult:arrayWithFakeAssets startIndex:5 endIndex:15 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:NO];\n    XCTAssertTrue(resultYesYes.count == 10);\n    XCTAssertTrue(resultYesNo.count == 10);\n    XCTAssertTrue(resultNoYes.count == 10);\n    XCTAssertTrue(resultNoNo.count == 10);\n}\n\n-(int) assetAsInt:(PHAssetWithCollectionIndex *)assetWithIndex{\n    return [(NSNumber *)[assetWithIndex asset] intValue];\n}\n\n//Testing scenarios from : https://github.com/olofd/react-native-photos-framework/pull/11#issuecomment-264324873\n-(void) testOrderScenarioOne {\n    // load assets from newest to oldest from the top to bottom of screen\n    // this is default behavior\n    NSArray <PHAssetWithCollectionIndex *> *result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:0 endIndex:2 assetDisplayStartToEnd:NO andAssetDisplayBottomUp:NO];\n    \n    XCTAssertEqual(result.count, 3);\n    \n    XCTAssertEqual([self assetAsInt:result[0]], 2016);\n    XCTAssertEqual([self assetAsInt:result[1]], 2015);\n    XCTAssertEqual([self assetAsInt:result[2]], 2014);\n    //scrolling down will load\n    result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:3 endIndex:5 assetDisplayStartToEnd:NO andAssetDisplayBottomUp:NO];\n    XCTAssertEqual(result.count, 2);\n    XCTAssertEqual([self assetAsInt:result[0]], 2013);\n    XCTAssertEqual([self assetAsInt:result[1]], 2012);\n}\n\n-(void) testOrderScenarioTwo {\n    // load assets from newest to oldest from the bottom to top of screen\n    NSArray <NSNumber *> *result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:0 endIndex:2 assetDisplayStartToEnd:NO andAssetDisplayBottomUp:YES];\n    \n    XCTAssertEqual(result.count, 3);\n    XCTAssertEqual([self assetAsInt:result[0]], 2014);\n    XCTAssertEqual([self assetAsInt:result[1]], 2015);\n    XCTAssertEqual([self assetAsInt:result[2]], 2016);\n    //scrolling down will load\n    result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:3 endIndex:5 assetDisplayStartToEnd:NO andAssetDisplayBottomUp:YES];\n    XCTAssertEqual(result.count, 2);\n    XCTAssertEqual([self assetAsInt:result[0]], 2012);\n    XCTAssertEqual([self assetAsInt:result[1]], 2013);\n}\n\n-(void) testOrderScenarioThree {\n    // load assets from oldest to newest from the top to bottom of screen\n    NSArray <NSNumber *> *result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:0 endIndex:2 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:NO];\n    \n    XCTAssertEqual(result.count, 3);\n    XCTAssertEqual([self assetAsInt:result[0]], 2012);\n    XCTAssertEqual([self assetAsInt:result[1]], 2013);\n    XCTAssertEqual([self assetAsInt:result[2]], 2014);\n    //scrolling up will load\n    result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:3 endIndex:5 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:NO];\n    XCTAssertEqual(result.count, 2);\n    XCTAssertEqual([self assetAsInt:result[0]], 2015);\n    XCTAssertEqual([self assetAsInt:result[1]], 2016);\n}\n\n-(void) testOrderScenarioFour {\n    // load assets from oldest to newest from the bottom to top of screen\n    NSArray <NSNumber *> *result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:0 endIndex:2 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:YES];\n    \n    XCTAssertEqual(result.count, 3);\n    XCTAssertEqual([self assetAsInt:result[0]], 2014);\n    XCTAssertEqual([self assetAsInt:result[1]], 2013);\n    XCTAssertEqual([self assetAsInt:result[2]], 2012);\n    //scrolling up will load\n    result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:3 endIndex:5 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:YES];\n    XCTAssertEqual(result.count, 2);\n    XCTAssertEqual([self assetAsInt:result[0]], 2016);\n    XCTAssertEqual([self assetAsInt:result[1]], 2015);\n}\n\n-(void) testOrderScenarioFive {\n    // load assets from oldest to newest from the bottom to top of screen\n    NSArray <NSNumber *> *result = [PHAssetsService getAssetsForFetchResult:scenarioAssets startIndex:3 endIndex:7 assetDisplayStartToEnd:YES andAssetDisplayBottomUp:YES];\n    \n    XCTAssertEqual(result.count, 2);\n    XCTAssertEqual([self assetAsInt:result[0]], 2016);\n    XCTAssertEqual([self assetAsInt:result[1]], 2015);\n}\n\n\n@end\n"
  },
  {
    "path": "ios/RNPhotosFrameworkTests/RCTConvert+RNPhotosFrameworkTests.m",
    "content": "#import <XCTest/XCTest.h>\n#import <React/RCTConvert.h>\n#import \"RCTConvert+RNPhotosFramework.h\"\n\n@interface RCTConvert_RNPhotosFrameworkTests : XCTestCase\n\n@end\n\n@implementation RCTConvert_RNPhotosFrameworkTests\n\n- (void)setUp {\n    [super setUp];\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n}\n\n- (void)tearDown {\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n}\n\n- (void)testSourceTypesNil {\n    int extracted = [RCTConvert PHAssetSourceTypes:nil];\n    int nsOptionsExpected = PHAssetSourceTypeNone;\n    XCTAssertEqual(extracted, nsOptionsExpected);\n}\n\n\n- (void)testSourceTypesEmpty {\n    int extracted = [RCTConvert PHAssetSourceTypes:@[]];\n    int nsOptionsExpected = PHAssetSourceTypeNone;\n    XCTAssertEqual(extracted, nsOptionsExpected);\n}\n\n- (void)testSourceTypesOneType {\n    int extracted = [RCTConvert PHAssetSourceTypes:@[@\"userLibrary\"]];\n    int nsOptionsExpected = PHAssetSourceTypeUserLibrary;\n    XCTAssertEqual(extracted, nsOptionsExpected);\n}\n\n- (void)testSourceTypesMultipleTypes {\n    int extracted = [RCTConvert PHAssetSourceTypes:@[@\"userLibrary\" , @\"cloudShared\", @\"itunesSynced\"]];\n    int nsOptionsExpected = PHAssetSourceTypeCloudShared | PHAssetSourceTypeUserLibrary | PHAssetSourceTypeiTunesSynced;\n    XCTAssertEqual(extracted, nsOptionsExpected);\n}\n\n\n@end\n"
  },
  {
    "path": "local-cli/android/android.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar generate = require('../generate/generate');\nvar fs = require('fs');\n\nfunction android(argv, config, args) {\n  return generate([\n    '--platform', 'android',\n    '--project-path', process.cwd(),\n    '--project-name', args.projectName,\n  ], config);\n}\n\nmodule.exports = {\n  name: 'android',\n  description: 'creates an empty android project',\n  func: android,\n  options: [{\n    command: '--project-name [name]',\n    default: () => JSON.parse(\n      fs.readFileSync('package.json', 'utf8')\n    ).name,\n  }],\n};\n"
  },
  {
    "path": "local-cli/bundle/assetPathUtils.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nfunction getAndroidAssetSuffix(scale) {\n  switch (scale) {\n    case 0.75: return 'ldpi';\n    case 1: return 'mdpi';\n    case 1.5: return 'hdpi';\n    case 2: return 'xhdpi';\n    case 3: return 'xxhdpi';\n    case 4: return 'xxxhdpi';\n  }\n}\n\nfunction getAndroidDrawableFolderName(asset, scale) {\n  var suffix = getAndroidAssetSuffix(scale);\n  if (!suffix) {\n    throw new Error(\n      'Don\\'t know which android drawable suffix to use for asset: ' +\n      JSON.stringify(asset)\n    );\n  }\n  const androidFolder = 'drawable-' + suffix;\n  return androidFolder;\n}\n\nfunction getAndroidResourceIdentifier(asset) {\n  var folderPath = getBasePath(asset);\n  return (folderPath + '/' + asset.name)\n    .toLowerCase()\n    .replace(/\\//g, '_')           // Encode folder structure in file name\n    .replace(/([^a-z0-9_])/g, '')  // Remove illegal chars\n    .replace(/^assets_/, '');      // Remove \"assets_\" prefix\n}\n\nfunction getBasePath(asset) {\n  var basePath = asset.httpServerLocation;\n  if (basePath[0] === '/') {\n    basePath = basePath.substr(1);\n  }\n  return basePath;\n}\n\nmodule.exports = {\n  getAndroidAssetSuffix: getAndroidAssetSuffix,\n  getAndroidDrawableFolderName: getAndroidDrawableFolderName,\n  getAndroidResourceIdentifier: getAndroidResourceIdentifier,\n  getBasePath: getBasePath\n};"
  },
  {
    "path": "local-cli/bundle/buildBundle.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nconst log = require('../util/log').out('bundle');\nconst outputBundle = require('./output/bundle');\nconst path = require('path');\nconst Promise = require('promise');\nconst saveAssets = require('./saveAssets');\nconst Server = require('../../packager/react-packager/src/Server');\nconst defaultAssetExts = require('../../packager/defaultAssetExts');\n\nfunction saveBundle(output, bundle, args) {\n  return Promise.resolve(\n    output.save(bundle, args, log)\n  ).then(() => bundle);\n}\n\nfunction buildBundle(args, config, output = outputBundle, packagerInstance) {\n  // This is used by a bazillion of npm modules we don't control so we don't\n  // have other choice than defining it as an env variable here.\n  process.env.NODE_ENV = args.dev ? 'development' : 'production';\n\n  const requestOpts = {\n    entryFile: args.entryFile,\n    sourceMapUrl: args.sourcemapOutput && path.basename(args.sourcemapOutput),\n    dev: args.dev,\n    minify: !args.dev,\n    platform: args.platform,\n  };\n\n  // If a packager instance was not provided, then just create one for this\n  // bundle command and close it down afterwards.\n  var shouldClosePackager = false;\n  if (!packagerInstance) {\n    let assetExts = (config.getAssetExts && config.getAssetExts()) || [];\n\n    const transformModulePath =\n      args.transformer ? path.resolve(args.transformer) :\n      typeof config.getTransformModulePath === 'function' ? config.getTransformModulePath() :\n      undefined;\n\n    const options = {\n      projectRoots: config.getProjectRoots(),\n      assetExts: defaultAssetExts.concat(assetExts),\n      assetRoots: config.getAssetRoots(),\n      blacklistRE: config.getBlacklistRE(args.platform),\n      getTransformOptionsModulePath: config.getTransformOptionsModulePath,\n      transformModulePath: transformModulePath,\n      extraNodeModules: config.extraNodeModules,\n      nonPersistent: true,\n      resetCache: args.resetCache,\n    };\n\n    packagerInstance = new Server(options);\n    shouldClosePackager = true;\n  }\n\n  const bundlePromise = output.build(packagerInstance, requestOpts)\n    .then(bundle => {\n      if (shouldClosePackager) {\n        packagerInstance.end();\n      }\n      return saveBundle(output, bundle, args);\n    });\n\n  // Save the assets of the bundle\n  const assets = bundlePromise\n    .then(bundle => bundle.getAssets())\n    .then(outputAssets => saveAssets(\n      outputAssets,\n      args.platform,\n      args.assetsDest,\n    ));\n\n  // When we're done saving bundle output and the assets, we're done.\n  return assets;\n}\n\nmodule.exports = buildBundle;\n"
  },
  {
    "path": "local-cli/bundle/bundle.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nconst buildBundle = require('./buildBundle');\nconst outputBundle = require('./output/bundle');\nconst outputPrepack = require('./output/prepack');\nconst bundleCommandLineArgs = require('./bundleCommandLineArgs');\n\n/**\n * Builds the bundle starting to look for dependencies at the given entry path.\n */\nfunction bundleWithOutput(argv, config, args, output, packagerInstance) {\n  if (!output) {\n    output = args.prepack ? outputPrepack : outputBundle;\n  }\n  return buildBundle(args, config, output, packagerInstance);\n}\n\nfunction bundle(argv, config, args, packagerInstance) {\n  return bundleWithOutput(argv, config, args, undefined, packagerInstance);\n}\n\nmodule.exports = {\n  name: 'bundle',\n  description: 'builds the javascript bundle for offline use',\n  func: bundle,\n  options: bundleCommandLineArgs,\n\n  // not used by the CLI itself\n  withOutput: bundleWithOutput,\n};\n"
  },
  {
    "path": "local-cli/bundle/bundleCommandLineArgs.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nmodule.exports = [\n  {\n    command: '--entry-file <path>',\n    description: 'Path to the root JS file, either absolute or relative to JS root',\n  }, {\n    command: '--platform [string]',\n    description: 'Either \"ios\" or \"android\"',\n    default: 'ios',\n  }, {\n    command: '--transformer [string]',\n    description: 'Specify a custom transformer to be used',\n  }, {\n    command: '--dev [boolean]',\n    description: 'If false, warnings are disabled and the bundle is minified',\n    parse: (val) => val === 'false' ? false : true,\n    default: true,\n  }, {\n    command: '--prepack',\n    description: 'When passed, the output bundle will use the Prepack format.',\n  }, {\n    command: '--bridge-config [string]',\n    description: 'File name of a a JSON export of __fbBatchedBridgeConfig. Used by Prepack. Ex. ./bridgeconfig.json',\n  }, {\n    command: '--bundle-output <string>',\n    description: 'File name where to store the resulting bundle, ex. /tmp/groups.bundle',\n  }, {\n    command: '--bundle-encoding [string]',\n    description: 'Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).',\n    default: 'utf8',\n  }, {\n    command: '--sourcemap-output [string]',\n    description: 'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map',\n  }, {\n    command: '--assets-dest [string]',\n    description: 'Directory name where to store assets referenced in the bundle',\n  }, {\n    command: '--verbose',\n    description: 'Enables logging',\n    default: false,\n  }, {\n    command: '--reset-cache',\n    description: 'Removes cached files',\n    default: false,\n  },\n];\n"
  },
  {
    "path": "local-cli/bundle/getAssetDestPathAndroid.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst path = require('path');\nconst assetPathUtils = require('./assetPathUtils');\n\nfunction getAssetDestPathAndroid(asset, scale) {\n  const androidFolder = assetPathUtils.getAndroidDrawableFolderName(asset, scale);\n  const fileName =  assetPathUtils.getAndroidResourceIdentifier(asset);\n  return path.join(androidFolder, fileName + '.' + asset.type);\n}\n\nmodule.exports = getAssetDestPathAndroid;\n"
  },
  {
    "path": "local-cli/bundle/getAssetDestPathIOS.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst path = require('path');\n\nfunction getAssetDestPathIOS(asset, scale) {\n  const suffix = scale === 1 ? '' : '@' + scale + 'x';\n  const fileName = asset.name + suffix + '.' + asset.type;\n  return path.join(asset.httpServerLocation.substr(1), fileName);\n}\n\nmodule.exports = getAssetDestPathIOS;\n"
  },
  {
    "path": "local-cli/bundle/output/bundle.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst Promise = require('promise');\nconst meta = require('./meta');\nconst writeFile = require('./writeFile');\n\nfunction buildBundle(packagerClient, requestOptions) {\n  return packagerClient.buildBundle({\n    ...requestOptions,\n    isolateModuleIDs: true,\n  });\n}\n\nfunction createCodeWithMap(bundle, dev) {\n  return {\n    code: bundle.getSource({dev}),\n    map: JSON.stringify(bundle.getSourceMap({dev})),\n  };\n}\n\nfunction saveBundleAndMap(bundle, options, log) {\n  const {\n    bundleOutput,\n    bundleEncoding: encoding,\n    dev,\n    sourcemapOutput\n  } = options;\n\n  log('start');\n  const codeWithMap = createCodeWithMap(bundle, dev);\n  log('finish');\n\n  log('Writing bundle output to:', bundleOutput);\n\n  const {code} = codeWithMap;\n  const writeBundle = writeFile(bundleOutput, code, encoding);\n  const writeMetadata = writeFile(\n    bundleOutput + '.meta',\n    meta(code, encoding),\n    'binary');\n  Promise.all([writeBundle, writeMetadata])\n    .then(() => log('Done writing bundle output'));\n\n  if (sourcemapOutput) {\n    log('Writing sourcemap output to:', sourcemapOutput);\n    const writeMap = writeFile(sourcemapOutput, codeWithMap.map, null);\n    writeMap.then(() => log('Done writing sourcemap output'));\n    return Promise.all([writeBundle, writeMetadata, writeMap]);\n  } else {\n    return writeBundle;\n  }\n}\n\nexports.build = buildBundle;\nexports.save = saveBundleAndMap;\nexports.formatName = 'bundle';\n"
  },
  {
    "path": "local-cli/bundle/output/meta.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\n/* global Buffer: true */\n\nconst crypto = require('crypto');\n\nconst isUTF8 = encoding => /^utf-?8$/i.test(encoding);\n\nconst constantFor = encoding =>\n  /^ascii$/i.test(encoding) ? 1 :\n  isUTF8(encoding) ? 2 :\n  /^(?:utf-?16(?:le)?|ucs-?2)$/.test(encoding) ? 3 : 0;\n\nmodule.exports = function(code, encoding) {\n  const hash = crypto.createHash('sha1');\n  hash.update(code, encoding);\n  const digest = hash.digest('binary');\n  const signature = Buffer(digest.length + 1);\n  signature.write(digest, 'binary');\n  signature.writeUInt8(\n    constantFor(tryAsciiPromotion(code, encoding)),\n    signature.length - 1);\n  return signature;\n};\n\nfunction tryAsciiPromotion(string, encoding) {\n  if (!isUTF8(encoding)) { return encoding; }\n  for (let i = 0, n = string.length; i < n; i++) {\n    if (string.charCodeAt(i) > 0x7f) { return encoding; }\n  }\n  return 'ascii';\n}\n"
  },
  {
    "path": "local-cli/bundle/output/prepack.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst writeFile = require('./writeFile');\n\nfunction buildPrepackBundle(packagerClient, requestOptions) {\n  return packagerClient.buildPrepackBundle(requestOptions);\n}\n\nfunction savePrepackBundle(bundle, options, log) {\n  const {\n    bundleOutput,\n    bridgeConfig,\n  } = options;\n\n  const result = bundle.build({\n    batchedBridgeConfig: bridgeConfig\n  });\n\n  log('Writing prepack bundle output to:', bundleOutput);\n  const writePrepackBundle = writeFile(bundleOutput, result, 'ucs-2');\n  writePrepackBundle.then(() => log('Done writing prepack bundle output'));\n  return writePrepackBundle;\n}\n\nexports.build = buildPrepackBundle;\nexports.save = savePrepackBundle;\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/as-assets.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst mkdirp = require('mkdirp');\nconst path = require('path');\nconst Promise = require('promise');\n\nconst buildSourceMapWithMetaData = require('./build-unbundle-sourcemap-with-metadata');\nconst writeFile = require('../writeFile');\nconst writeSourceMap = require('./write-sourcemap');\nconst MAGIC_UNBUNDLE_NUMBER = require('./magic-number');\nconst {joinModules} = require('./util');\n\nconst MAGIC_UNBUNDLE_FILENAME = 'UNBUNDLE'; // must not start with a dot, as that won't go into the apk\nconst MODULES_DIR = 'js-modules';\n\n/**\n * Saves all JS modules of an app as single files\n * The startup code (prelude, polyfills etc.) are written to the file\n * designated by the `bundleOuput` option.\n * All other modules go into a 'js-modules' folder that in the same parent\n * directory as the startup file.\n */\nfunction saveAsAssets(bundle, options, log) {\n  const {\n    bundleOutput,\n    bundleEncoding: encoding,\n    sourcemapOutput\n  } = options;\n\n  log('start');\n  const {startupModules, lazyModules} = bundle.getUnbundle();\n  log('finish');\n  const startupCode = joinModules(startupModules);\n\n  log('Writing bundle output to:', bundleOutput);\n  const modulesDir = path.join(path.dirname(bundleOutput), MODULES_DIR);\n  const writeUnbundle =\n    createDir(modulesDir).then( // create the modules directory first\n      () => Promise.all([\n        writeModules(lazyModules, modulesDir, encoding),\n        writeFile(bundleOutput, startupCode, encoding),\n        writeMagicFlagFile(modulesDir),\n      ])\n    );\n  writeUnbundle.then(() => log('Done writing unbundle output'));\n\n  const sourceMap =\n    buildSourceMapWithMetaData({startupModules, lazyModules});\n\n  return Promise.all([\n    writeUnbundle,\n    writeSourceMap(sourcemapOutput, JSON.stringify(sourceMap), log)\n  ]);\n}\n\nfunction createDir(dirName) {\n  return new Promise((resolve, reject) =>\n    mkdirp(dirName, error => error ? reject(error) : resolve()));\n}\n\nfunction writeModuleFile(module, modulesDir, encoding) {\n  const {code, id} = module;\n  return writeFile(path.join(modulesDir, id + '.js'), code, encoding);\n}\n\nfunction writeModules(modules, modulesDir, encoding) {\n  const writeFiles =\n    modules.map(module => writeModuleFile(module, modulesDir, encoding));\n  return Promise.all(writeFiles);\n}\n\nfunction writeMagicFlagFile(outputDir) {\n  /* global Buffer: true */\n  const buffer = Buffer(4);\n  buffer.writeUInt32LE(MAGIC_UNBUNDLE_NUMBER);\n  return writeFile(path.join(outputDir, MAGIC_UNBUNDLE_FILENAME), buffer);\n}\n\nmodule.exports = saveAsAssets;\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/as-indexed-file.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst buildSourceMapWithMetaData = require('./build-unbundle-sourcemap-with-metadata');\nconst fs = require('fs');\nconst Promise = require('promise');\nconst writeSourceMap = require('./write-sourcemap');\nconst {joinModules} = require('./util');\n\nconst MAGIC_UNBUNDLE_FILE_HEADER = require('./magic-number');\nconst SIZEOF_UINT32 = 4;\n\n/**\n * Saves all JS modules of an app as a single file, separated with null bytes.\n * The file begins with an offset table that contains module ids and their\n * lengths/offsets.\n * The module id for the startup code (prelude, polyfills etc.) is the\n * empty string.\n */\nfunction saveAsIndexedFile(bundle, options, log) {\n  const {\n    bundleOutput,\n    bundleEncoding: encoding,\n    sourcemapOutput\n  } = options;\n\n  log('start');\n  const {startupModules, lazyModules, groups} = bundle.getUnbundle();\n  log('finish');\n\n  const moduleGroups = ModuleGroups(groups, lazyModules);\n  const startupCode = joinModules(startupModules);\n\n  log('Writing unbundle output to:', bundleOutput);\n  const writeUnbundle = writeBuffers(\n    fs.createWriteStream(bundleOutput),\n    buildTableAndContents(startupCode, lazyModules, moduleGroups, encoding)\n  ).then(() => log('Done writing unbundle output'));\n\n  const sourceMap =\n    buildSourceMapWithMetaData({startupModules, lazyModules, moduleGroups});\n\n  return Promise.all([\n    writeUnbundle,\n    writeSourceMap(sourcemapOutput, JSON.stringify(sourceMap), log),\n  ]);\n}\n\n/* global Buffer: true */\n\nconst fileHeader = Buffer(4);\nfileHeader.writeUInt32LE(MAGIC_UNBUNDLE_FILE_HEADER);\nconst nullByteBuffer = Buffer(1).fill(0);\n\nfunction writeBuffers(stream, buffers) {\n  buffers.forEach(buffer => stream.write(buffer));\n  return new Promise((resolve, reject) => {\n    stream.on('error', reject);\n    stream.on('finish', () => resolve());\n    stream.end();\n  });\n}\n\nfunction nullTerminatedBuffer(contents, encoding) {\n  return Buffer.concat([Buffer(contents, encoding), nullByteBuffer]);\n}\n\nfunction moduleToBuffer(id, code, encoding) {\n  return {\n    id,\n    buffer: nullTerminatedBuffer(code, encoding),\n  };\n}\n\nfunction entryOffset(n) {\n  // 2: num_entries + startup_code_len\n  // n * 2: each entry consists of two uint32s\n  return (2 + n * 2) * SIZEOF_UINT32;\n}\n\nfunction buildModuleTable(startupCode, buffers, moduleGroups) {\n  // table format:\n  // - num_entries:      uint_32  number of entries\n  // - startup_code_len: uint_32  length of the startup section\n  // - entries:          entry...\n  //\n  // entry:\n  //  - module_offset:   uint_32  offset into the modules blob\n  //  - module_length:   uint_32  length of the module code in bytes\n\n  const moduleIds = Array.from(moduleGroups.modulesById.keys());\n  const maxId = moduleIds.reduce((max, id) => Math.max(max, id));\n  const numEntries = maxId + 1;\n  const table = new Buffer(entryOffset(numEntries)).fill(0);\n\n  // num_entries\n  table.writeUInt32LE(numEntries, 0);\n\n  // startup_code_len\n  table.writeUInt32LE(startupCode.length, SIZEOF_UINT32);\n\n  // entries\n  let codeOffset = startupCode.length;\n  buffers.forEach(({id, buffer}) => {\n    const idsInGroup = moduleGroups.groups.has(id)\n      ? [id].concat(Array.from(moduleGroups.groups.get(id)))\n      : [id];\n\n    idsInGroup.forEach(moduleId => {\n      const offset = entryOffset(moduleId);\n      // module_offset\n      table.writeUInt32LE(codeOffset, offset);\n      // module_length\n      table.writeUInt32LE(buffer.length, offset + SIZEOF_UINT32);\n    });\n    codeOffset += buffer.length;\n  });\n\n  return table;\n}\n\nfunction groupCode(rootCode, moduleGroup, modulesById) {\n  if (!moduleGroup || !moduleGroup.size) {\n    return rootCode;\n  }\n  const code = [rootCode];\n  for (const id of moduleGroup) {\n    code.push(modulesById.get(id).code);\n  }\n\n  return code.join('\\n');\n}\n\nfunction buildModuleBuffers(modules, moduleGroups, encoding) {\n  return modules\n    .filter(m => !moduleGroups.modulesInGroups.has(m.id))\n    .map(({id, code}) => moduleToBuffer(\n      id,\n      groupCode(\n        code,\n        moduleGroups.groups.get(id),\n        moduleGroups.modulesById,\n      ),\n      encoding\n    ));\n}\n\nfunction buildTableAndContents(startupCode, modules, moduleGroups, encoding) {\n  // file contents layout:\n  // - magic number      char[4]  0xE5 0xD1 0x0B 0xFB (0xFB0BD1E5 uint32 LE)\n  // - offset table      table    see `buildModuleTables`\n  // - code blob         char[]   null-terminated code strings, starting with\n  //                              the startup code\n\n  const startupCodeBuffer = nullTerminatedBuffer(startupCode, encoding);\n  const moduleBuffers = buildModuleBuffers(modules, moduleGroups, encoding);\n  const table = buildModuleTable(startupCodeBuffer, moduleBuffers, moduleGroups);\n\n  return [\n    fileHeader,\n    table,\n    startupCodeBuffer\n  ].concat(moduleBuffers.map(({buffer}) => buffer));\n}\n\nfunction ModuleGroups(groups, modules) {\n  return {\n    groups,\n    modulesById: new Map(modules.map(m => [m.id, m])),\n    modulesInGroups: new Set(concat(groups.values())),\n  };\n}\n\nfunction * concat(iterators) {\n  for (const it of iterators) {\n    yield * it;\n  }\n}\n\nmodule.exports = saveAsIndexedFile;\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/build-unbundle-sourcemap-with-metadata.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst {combineSourceMaps, joinModules} = require('./util');\n\nmodule.exports = ({startupModules, lazyModules, moduleGroups}) => {\n  const startupModule = {\n    code: joinModules(startupModules),\n    map: combineSourceMaps({modules: startupModules}),\n  };\n  return combineSourceMaps({\n    modules: [startupModule].concat(lazyModules),\n    moduleGroups,\n    withCustomOffsets: true,\n  });\n};\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/index.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst asIndexedFile = require('./as-indexed-file');\nconst asAssets = require('./as-assets');\n\nfunction buildBundle(packagerClient, requestOptions) {\n  return packagerClient.buildBundle({\n    ...requestOptions,\n    unbundle: true,\n    isolateModuleIDs: true,\n  });\n}\n\nfunction saveUnbundle(bundle, options, log) {\n  // we fork here depending on the platform:\n  // while android is pretty good at loading individual assets, ios has a large\n  // overhead when reading hundreds pf assets from disk\n  return options.platform === 'android' ?\n    asAssets(bundle, options, log) :\n    asIndexedFile(bundle, options, log);\n}\n\nexports.build = buildBundle;\nexports.save = saveUnbundle;\nexports.formatName = 'bundle';\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/magic-number.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nmodule.exports = 0xFB0BD1E5;\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/util.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst newline = /\\r\\n?|\\n|\\u2028|\\u2029/g;\nconst countLines =\n  string => (string.match(newline) || []).length + 1; // fastest implementation\n\nfunction lineToLineSourceMap(source, filename) {\n  // The first line mapping in our package is the base64vlq code for zeros (A).\n  const firstLine = 'AAAA;';\n\n  // Most other lines in our mappings are all zeros (for module, column etc)\n  // except for the lineno mapping: curLineno - prevLineno = 1; Which is C.\n  const line = 'AACA;';\n\n  return {\n    version: 3,\n    sources: [filename],\n    mappings: firstLine + Array(countLines(source)).join(line),\n  };\n}\n\nconst wrapperEnd = wrappedCode => wrappedCode.indexOf('{') + 1;\n\nconst Section = (line, column, map) => ({map, offset: {line, column}});\n\nfunction combineSourceMaps({modules, withCustomOffsets, moduleGroups}) {\n  let offsets;\n  const sections = [];\n  const sourceMap = {\n    version: 3,\n    sections,\n  };\n\n  if (withCustomOffsets) {\n    offsets = sourceMap.x_facebook_offsets = [];\n  }\n\n  let line = 0;\n  modules.forEach(({code, id, map, name}) => {\n    let column = 0;\n    let hasOffset = false;\n    let group;\n    let groupLines = 0;\n\n    if (withCustomOffsets) {\n      if (moduleGroups && moduleGroups.modulesInGroups.has(id)) {\n        // this is a module appended to another module\n        return;\n      }\n\n      if (moduleGroups && moduleGroups.groups.has(id)) {\n        group = moduleGroups.groups.get(id);\n        const otherModules = Array.from(group).map(\n          moduleId => moduleGroups.modulesById.get(moduleId));\n        otherModules.forEach(m => {\n          groupLines += countLines(m.code);\n        });\n        map = combineSourceMaps({\n          modules: [{code, id, map, name}].concat(otherModules),\n        });\n      }\n\n      hasOffset = id != null;\n      column = wrapperEnd(code);\n    }\n\n    sections.push(Section(line, column, map || lineToLineSourceMap(code, name)));\n    if (hasOffset) {\n      offsets[id] = line;\n      for (const moduleId of group || []) {\n        offsets[moduleId] = line;\n      }\n    }\n    line += countLines(code) + groupLines;\n  });\n\n  return sourceMap;\n}\n\nconst joinModules = modules => modules.map(m => m.code).join('\\n');\n\nmodule.exports = {\n  countLines,\n  lineToLineSourceMap,\n  combineSourceMaps,\n  joinModules,\n};\n"
  },
  {
    "path": "local-cli/bundle/output/unbundle/write-sourcemap.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst Promise = require('promise');\nconst writeFile = require('../writeFile');\n\nfunction writeSourcemap(fileName, contents, log) {\n  if (!fileName) {\n    return Promise.resolve();\n  }\n  log('Writing sourcemap output to:', fileName);\n  const writeMap = writeFile(fileName, contents, null);\n  writeMap.then(() => log('Done writing sourcemap output'));\n  return writeMap;\n}\n\nmodule.exports = writeSourcemap;\n"
  },
  {
    "path": "local-cli/bundle/output/writeFile.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fs = require('fs');\nconst Promise = require('promise');\n\nfunction writeFile(file, data, encoding) {\n  return new Promise((resolve, reject) => {\n    fs.writeFile(\n      file,\n      data,\n      encoding,\n      error => error ? reject(error) : resolve()\n    );\n  });\n}\n\nmodule.exports = writeFile;\n"
  },
  {
    "path": "local-cli/bundle/saveAssets.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fs = require('fs');\nconst getAssetDestPathAndroid = require('./getAssetDestPathAndroid');\nconst getAssetDestPathIOS = require('./getAssetDestPathIOS');\nconst log = require('../util/log').out('bundle');\nconst mkdirp = require('mkdirp');\nconst path = require('path');\n\nfunction saveAssets(\n  assets,\n  platform,\n  assetsDest\n) {\n  if (!assetsDest) {\n    console.warn('Assets destination folder is not set, skipping...');\n    return Promise.resolve();\n  }\n\n  const getAssetDestPath = platform === 'android'\n    ? getAssetDestPathAndroid\n    : getAssetDestPathIOS;\n\n  const filesToCopy = Object.create(null); // Map src -> dest\n  assets\n    .filter(asset => !asset.deprecated)\n    .forEach(asset =>\n      asset.scales.forEach((scale, idx) => {\n        const src = asset.files[idx];\n        const dest = path.join(assetsDest, getAssetDestPath(asset, scale));\n        filesToCopy[src] = dest;\n      })\n    );\n\n  return copyAll(filesToCopy);\n}\n\nfunction copyAll(filesToCopy) {\n  const queue = Object.keys(filesToCopy);\n  if (queue.length === 0) {\n    return Promise.resolve();\n  }\n\n  log('Copying ' + queue.length + ' asset files');\n  return new Promise((resolve, reject) => {\n    const copyNext = (error) => {\n      if (error) {\n        return reject(error);\n      }\n      if (queue.length === 0) {\n        log('Done copying assets');\n        resolve();\n      } else {\n        const src = queue.shift();\n        const dest = filesToCopy[src];\n        copy(src, dest, copyNext);\n      }\n    };\n    copyNext();\n  });\n}\n\nfunction copy(src, dest, callback) {\n  const destDir = path.dirname(dest);\n  mkdirp(destDir, err => {\n    if (err) {\n      return callback(err);\n    }\n    fs.createReadStream(src)\n      .pipe(fs.createWriteStream(dest))\n      .on('finish', callback);\n  });\n}\n\nmodule.exports = saveAssets;\n"
  },
  {
    "path": "local-cli/bundle/sign.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst signedsource = require('./signedsource');\nconst util = require('util');\n\nfunction sign(source) {\n  var ssToken = util.format('<<%sSource::*O*zOeWoEQle#+L!plEphiEmie@IsG>>', 'Signed');\n  var signedPackageText =\n    source + util.format('\\n__SSTOKENSTRING = \"@%s %s\";\\n', 'generated', ssToken);\n  return signedsource.sign(signedPackageText).signed_data;\n}\n\nmodule.exports = sign;\n"
  },
  {
    "path": "local-cli/bundle/signedsource.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar TOKEN    = '<<SignedSource::*O*zOeWoEQle#+L!plEphiEmie@IsG>>',\n    OLDTOKEN = '<<SignedSource::*O*zOeWoEQle#+L!plEphiEmie@I>>',\n    TOKENS   = [TOKEN, OLDTOKEN],\n    PATTERN  = new RegExp('@'+'generated (?:SignedSource<<([a-f0-9]{32})>>)');\n\nexports.SIGN_OK = {message:'ok'};\nexports.SIGN_UNSIGNED = new Error('unsigned');\nexports.SIGN_INVALID = new Error('invalid');\n\n// Thrown by sign(). Primarily for unit tests.\nexports.TokenNotFoundError = new Error(\n  'Code signing placeholder not found (expected to find \\''+TOKEN+'\\')');\n\nvar md5_hash_hex;\n\n// MD5 hash function for Node.js. To port this to other platforms, provide an\n// alternate code path for defining the md5_hash_hex function.\nvar crypto = require('crypto');\nmd5_hash_hex = function md5_hash_hex(data, input_encoding) {\n  var md5sum = crypto.createHash('md5');\n  md5sum.update(data, input_encoding);\n  return md5sum.digest('hex');\n};\n\n// Returns the signing token to be embedded, generally in a header comment,\n// in the file you wish to be signed.\n//\n// @return str  to be embedded in to-be-signed file\nfunction signing_token() {\n  return '@'+'generated '+TOKEN;\n}\nexports.signing_token = signing_token;\n\n// Determine whether a file is signed. This does NOT verify the signature.\n//\n// @param  str  File contents as a string.\n// @return bool True if the file has a signature.\nfunction is_signed(file_data) {\n  return !!PATTERN.exec(file_data);\n}\nexports.is_signed = is_signed;\n\n// Sign a source file which you have previously embedded a signing token\n// into. Signing modifies only the signing token, so the semantics of the\n// file will not change if you've put it in a comment.\n//\n// @param  str File contents as a string (with embedded token).\n// @return str Signed data.\nfunction sign(file_data) {\n  var first_time = file_data.indexOf(TOKEN) !== -1;\n  if (!first_time) {\n    if (is_signed(file_data))\n      file_data = file_data.replace(PATTERN, signing_token());\n    else\n      throw exports.TokenNotFoundError;\n  }\n  var signature = md5_hash_hex(file_data, 'utf8');\n  var signed_data = file_data.replace(TOKEN, 'SignedSource<<'+signature+'>>');\n  return { first_time: first_time,  signed_data: signed_data };\n}\nexports.sign = sign;\n\n// Verify a file's signature.\n//\n// @param  str  File contents as a string.\n// @return      Returns SIGN_OK if the data contains a valid signature,\n//              SIGN_UNSIGNED if it contains no signature, or SIGN_INVALID if\n//              it contains an invalid signature.\nfunction verify_signature(file_data) {\n  var match = PATTERN.exec(file_data);\n  if (!match)\n    return exports.SIGN_UNSIGNED;\n  // Replace the signature with the TOKEN, then hash and see if it matches\n  // the value in the file.  For backwards compatibility, also try with\n  // OLDTOKEN if that doesn't match.\n  var k, token, with_token, actual_md5, expected_md5 = match[1];\n  for (k in TOKENS) {\n    token = TOKENS[k];\n    with_token = file_data.replace(PATTERN, '@'+'generated '+token);\n    actual_md5 = md5_hash_hex(with_token, 'utf8');\n    if (expected_md5 === actual_md5)\n      return exports.SIGN_OK;\n  }\n  return exports.SIGN_INVALID;\n}\nexports.verify_signature = verify_signature;\n"
  },
  {
    "path": "local-cli/bundle/unbundle.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nconst bundleWithOutput = require('./bundle').withOutput;\nconst bundleCommandLineArgs = require('./bundleCommandLineArgs');\nconst outputUnbundle = require('./output/unbundle');\n\n/**\n * Builds the bundle starting to look for dependencies at the given entry path.\n */\nfunction unbundle(argv, config, args, packagerInstance) {\n  return bundleWithOutput(argv, config, args, outputUnbundle, packagerInstance);\n}\n\nmodule.exports = {\n  name: 'unbundle',\n  description: 'builds javascript as \"unbundle\" for offline use',\n  func: unbundle,\n  options: bundleCommandLineArgs,\n};\n"
  },
  {
    "path": "local-cli/cli.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\n// This file must be able to run in node 0.12 without babel so we can show that\n// it is not supported. This is why the rest of the cli code is in `cliEntry.js`.\nrequire('./server/checkNodeVersion')();\n\nrequire('../packager/babelRegisterOnly')([\n  /private-cli\\/src/,\n  /local-cli/,\n  /react-packager\\/src/\n]);\n\nvar cliEntry = require('./cliEntry');\n\nif (require.main === module) {\n  cliEntry.run();\n}\n\nmodule.exports = cliEntry;\n"
  },
  {
    "path": "local-cli/cliEntry.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @flow\n */\n'use strict';\n\nconst commander = require('commander');\n\nconst Config = require('./util/Config');\nconst childProcess = require('child_process');\nconst Promise = require('promise');\nconst chalk = require('chalk');\nconst minimist = require('minimist');\nconst path = require('path');\nconst fs = require('fs');\nconst gracefulFs = require('graceful-fs');\n\nconst init = require('./init/init');\nconst commands = require('./commands');\nconst assertRequiredOptions = require('./util/assertRequiredOptions');\nconst pkg = require('../package.json');\nconst defaultConfig = require('./default.config');\n\nimport type { Command } from './commands';\n\n// graceful-fs helps on getting an error when we run out of file\n// descriptors. When that happens it will enqueue the operation and retry it.\ngracefulFs.gracefulify(fs);\n\ncommander.version(pkg.version);\n\nconst defaultOptParser = (val) => val;\n\nconst handleError = (err) => {\n  console.error();\n  console.error(err.message || err);\n  console.error();\n  process.exit(1);\n};\n\n// Custom printHelpInformation command inspired by internal Commander.js\n// one modified to suit our needs\nfunction printHelpInformation() {\n  let cmdName = this._name;\n  if (this._alias) {\n    cmdName = cmdName + '|' + this._alias;\n  }\n\n  const sourceInformation = this.pkg\n    ? [\n      `  ${chalk.bold('Source:')} ${this.pkg.name}@${this.pkg.version}`,\n      '',\n    ]\n    : [];\n\n  let output = [\n    '',\n    chalk.bold(chalk.cyan((`  react-native ${cmdName} ${this.usage()}`))),\n    `  ${this._description}`,\n    '',\n    ...sourceInformation,\n    `  ${chalk.bold('Options:')}`,\n    '',\n    this.optionHelp().replace(/^/gm, '    '),\n    '',\n  ];\n\n  if (this.examples && this.examples.length > 0) {\n    const formattedUsage = this.examples.map(\n      example => `    ${example.desc}: \\n    ${chalk.cyan(example.cmd)}`,\n    ).join('\\n\\n');\n\n    output = output.concat([\n      chalk.bold('  Example usage:'),\n      '',\n      formattedUsage,\n    ]);\n  }\n\n  return output.concat([\n    '',\n    '',\n  ]).join('\\n');\n}\n\nfunction printUnknownCommand(cmdName) {\n  console.log([\n    '',\n    cmdName\n      ? chalk.red(`  Unrecognized command '${cmdName}'`)\n      : chalk.red('  You didn\\'t pass any command'),\n    `  Run ${chalk.cyan('react-native --help')} to see list of all available commands`,\n    '',\n  ].join('\\n'));\n}\n\nconst addCommand = (command: Command, config: Config) => {\n  const options = command.options || [];\n\n  const cmd = commander\n    .command(command.name, undefined, {\n      noHelp: !command.description,\n    })\n    .description(command.description)\n    .action(function runAction() {\n      const passedOptions = this.opts();\n      const argv: Array<string> = Array.from(arguments).slice(0, -1);\n\n      Promise.resolve()\n        .then(() => {\n          assertRequiredOptions(options, passedOptions);\n          return command.func(argv, config, passedOptions);\n        })\n        .catch(handleError);\n    });\n\n    cmd.helpInformation = printHelpInformation.bind(cmd);\n    cmd.examples = command.examples;\n    cmd.pkg = command.pkg;\n\n  options\n    .forEach(opt => cmd.option(\n      opt.command,\n      opt.description,\n      opt.parse || defaultOptParser,\n      typeof opt.default === 'function' ? opt.default(config) : opt.default,\n    ));\n\n  // Placeholder option for --config, which is parsed before any other option,\n  // but needs to be here to avoid \"unknown option\" errors when specified\n  cmd.option('--config [string]', 'Path to the CLI configuration file');\n};\n\nfunction getCliConfig() {\n  // Use a lightweight option parser to look up the CLI configuration file,\n  // which we need to set up the parser for the other args and options\n  let cliArgs = minimist(process.argv.slice(2));\n\n  let cwd;\n  let configPath;\n  if (cliArgs.config != null) {\n    cwd = process.cwd();\n    configPath = cliArgs.config;\n  } else {\n    cwd = __dirname;\n    configPath = Config.findConfigPath(cwd);\n  }\n\n  return Config.get(cwd, defaultConfig, configPath);\n}\n\nfunction run() {\n  const setupEnvScript = /^win/.test(process.platform)\n    ? 'setup_env.bat'\n    : 'setup_env.sh';\n\n  childProcess.execFileSync(path.join(__dirname, setupEnvScript));\n\n  const config = getCliConfig();\n  commands.forEach(cmd => addCommand(cmd, config));\n\n  commander.parse(process.argv);\n\n  const isValidCommand = commands.find(cmd => cmd.name.split(' ')[0] === process.argv[2]);\n\n  if (!isValidCommand) {\n    printUnknownCommand(process.argv[2]);\n    return;\n  }\n\n  if (!commander.args.length) {\n    commander.help();\n  }\n}\n\nmodule.exports = {\n  run: run,\n  init: init,\n};\n"
  },
  {
    "path": "local-cli/commands.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @flow\n */\n'use strict';\n\nconst Config = require('./util/Config');\nconst getUserCommands = require('./core/getCommands');\n\nexport type Command = {\n  name: string,\n  description?: string,\n  usage?: string,\n  func: (argv: Array<string>, config: Config, args: Object) => ?Promise<void>,\n  options?: Array<{\n    command: string,\n    description?: string,\n    parse?: (val: string) => any,\n    default?: (config: Config) => any | any,\n  }>,\n  examples?: Array<{\n    desc: string,\n    cmd: string,\n  }>,\n  pkg?: {\n    version: string,\n    name: string,\n  },\n};\n\nconst documentedCommands = [\n  require('./android/android'),\n  require('./server/server'),\n  require('./runIOS/runIOS'),\n  require('./runAndroid/runAndroid'),\n  require('./library/library'),\n  require('./bundle/bundle'),\n  require('./bundle/unbundle'),\n  require('./link/link'),\n  require('./link/unlink'),\n  require('./install/install'),\n  require('./install/uninstall'),\n  require('./upgrade/upgrade'),\n  require('./logAndroid/logAndroid'),\n  require('./logIOS/logIOS'),\n  require('./dependencies/dependencies'),\n];\n\n// The user should never get here because projects are inited by\n// using `react-native-cli` from outside a project directory.\nconst undocumentedCommands = [\n  {\n    name: 'init',\n    func: () => {\n      console.log([\n        'Looks like React Native project already exists in the current',\n        'folder. Run this command from a different folder or remove node_modules/react-native'\n      ].join('\\n'));\n    },\n  },\n];\n\nconst commands: Array<Command> = [\n  ...documentedCommands,\n  ...undocumentedCommands,\n  ...getUserCommands(),\n];\n\nmodule.exports = commands;\n"
  },
  {
    "path": "local-cli/core/config/android/findAndroidAppFolder.js",
    "content": "const fs = require('fs');\nconst path = require('path');\n\n/**\n * @param  {String} folder Folder to seek in\n * @return {String}\n */\nmodule.exports = function findAndroidAppFolder(folder) {\n  const flat = 'android';\n  const nested = path.join('android', 'app');\n\n  if (fs.existsSync(path.join(folder, nested))) {\n    return nested;\n  }\n\n  if (fs.existsSync(path.join(folder, flat))) {\n    return flat;\n  }\n\n  return null;\n};\n"
  },
  {
    "path": "local-cli/core/config/android/findManifest.js",
    "content": "const glob = require('glob');\nconst path = require('path');\n\n/**\n * Find an android application path in the folder\n *\n * @param {String} folder Name of the folder where to seek\n * @return {String}\n */\nmodule.exports = function findManifest(folder) {\n  const manifestPath = glob.sync(path.join('**', 'AndroidManifest.xml'), {\n    cwd: folder,\n    ignore: ['node_modules/**', '**/build/**', 'Examples/**', 'examples/**'],\n  })[0];\n\n  return manifestPath ? path.join(folder, manifestPath) : null;\n};\n"
  },
  {
    "path": "local-cli/core/config/android/findPackageClassName.js",
    "content": "const fs = require('fs');\nconst path = require('path');\nconst glob = require('glob');\n\n/**\n * Gets package's class name (class that implements ReactPackage)\n * by searching for its declaration in all Java files present in the folder\n *\n * @param {String} folder Folder to find java files\n */\nmodule.exports = function getPackageClassName(folder) {\n  const files = glob.sync('**/*.java', { cwd: folder });\n\n  const packages = files\n    .map(filePath => fs.readFileSync(path.join(folder, filePath), 'utf8'))\n    .map(file => file.match(/class (.*) implements ReactPackage/))\n    .filter(match => match);\n\n  return packages.length ? packages[0][1] : null;\n};\n"
  },
  {
    "path": "local-cli/core/config/android/index.js",
    "content": "const path = require('path');\nconst fs = require('fs');\nconst glob = require('glob');\nconst findAndroidAppFolder = require('./findAndroidAppFolder');\nconst findManifest = require('./findManifest');\nconst readManifest = require('./readManifest');\nconst findPackageClassName = require('./findPackageClassName');\n\nconst getPackageName = (manifest) => manifest.attr.package;\n\n/**\n * Gets android project config by analyzing given folder and taking some\n * defaults specified by user into consideration\n */\nexports.projectConfig = function projectConfigAndroid(folder, userConfig) {\n  const src = userConfig.sourceDir || findAndroidAppFolder(folder);\n\n  if (!src) {\n    return null;\n  }\n\n  const sourceDir = path.join(folder, src);\n  const isFlat = sourceDir.indexOf('app') === -1;\n  const manifestPath = findManifest(sourceDir);\n\n  if (!manifestPath) {\n    return null;\n  }\n\n  const manifest = readManifest(manifestPath);\n\n  const packageName = userConfig.packageName || getPackageName(manifest);\n  const packageFolder = userConfig.packageFolder ||\n    packageName.replace(/\\./g, path.sep);\n\n  const mainFilePath = path.join(\n    sourceDir,\n    userConfig.mainFilePath || `src/main/java/${packageFolder}/MainApplication.java`\n  );\n\n  const stringsPath = path.join(\n    sourceDir,\n    userConfig.stringsPath || 'src/main/res/values/strings.xml'\n  );\n\n  const settingsGradlePath = path.join(\n    folder,\n    'android',\n    userConfig.settingsGradlePath || 'settings.gradle'\n  );\n\n  const assetsPath = path.join(\n    sourceDir,\n    userConfig.assetsPath || 'src/main/assets'\n  );\n\n  const buildGradlePath = path.join(\n    sourceDir,\n    userConfig.buildGradlePath || 'build.gradle'\n  );\n\n  return {\n    sourceDir,\n    isFlat,\n    folder,\n    stringsPath,\n    manifestPath,\n    buildGradlePath,\n    settingsGradlePath,\n    assetsPath,\n    mainFilePath,\n  };\n};\n\n/**\n * Same as projectConfigAndroid except it returns\n * different config that applies to packages only\n */\nexports.dependencyConfig = function dependencyConfigAndroid(folder, userConfig) {\n  const src = userConfig.sourceDir || findAndroidAppFolder(folder);\n\n  if (!src) {\n    return null;\n  }\n\n  const sourceDir = path.join(folder, src);\n  const manifestPath = findManifest(sourceDir);\n\n  if (!manifestPath) {\n    return null;\n  }\n\n  const manifest = readManifest(manifestPath);\n  const packageName = userConfig.packageName || getPackageName(manifest);\n  const packageClassName = findPackageClassName(sourceDir);\n\n  /**\n   * This module has no package to export\n   */\n  if (!packageClassName) {\n    return null;\n  }\n\n  const packageImportPath = userConfig.packageImportPath ||\n    `import ${packageName}.${packageClassName};`;\n\n  const packageInstance = userConfig.packageInstance ||\n    `new ${packageClassName}()`;\n\n  return { sourceDir, folder, manifest, packageImportPath, packageInstance };\n};\n"
  },
  {
    "path": "local-cli/core/config/android/readManifest.js",
    "content": "const fs = require('fs');\nconst xml = require('xmldoc');\n\n/**\n * @param  {String} manifestPath\n * @return {XMLDocument} Parsed manifest's content\n */\nmodule.exports = function readManifest(manifestPath) {\n  return new xml.XmlDocument(fs.readFileSync(manifestPath, 'utf8'));\n};\n"
  },
  {
    "path": "local-cli/core/config/findAssets.js",
    "content": "const glob = require('glob');\nconst path = require('path');\n\nconst findAssetsInFolder = (folder) =>\n  glob.sync(path.join(folder, '**'), { nodir: true });\n\n/**\n * Given an array of assets folders, e.g. ['Fonts', 'Images'],\n * it globs in them to find all files that can be copied.\n *\n * It returns an array of absolute paths to files found.\n */\nmodule.exports = function findAssets(folder, assets) {\n  return (assets || [])\n    .map(assetsFolder => path.join(folder, assetsFolder))\n    .reduce((assets, assetsFolder) =>\n      assets.concat(findAssetsInFolder(assetsFolder)),\n      []\n    );\n};\n"
  },
  {
    "path": "local-cli/core/config/index.js",
    "content": "const path = require('path');\n\nconst android = require('./android');\nconst ios = require('./ios');\nconst findAssets = require('./findAssets');\nconst wrapCommands = require('./wrapCommands');\n\nconst getRNPMConfig = (folder) =>\n  require(path.join(folder, './package.json')).rnpm || {};\n\n/**\n * Returns project config from the current working directory\n * @return {Object}\n */\nexports.getProjectConfig = function getProjectConfig(root) {\n  const folder = root || process.cwd();\n  const rnpm = getRNPMConfig(folder);\n\n  return Object.assign({}, rnpm, {\n    ios: ios.projectConfig(folder, rnpm.ios || {}),\n    android: android.projectConfig(folder, rnpm.android || {}),\n    assets: findAssets(folder, rnpm.assets),\n  });\n};\n\n/**\n * Returns a dependency config from node_modules/<package_name>\n * @param {String} packageName Dependency name\n * @return {Object}\n */\nexports.getDependencyConfig = function getDependencyConfig(packageName, rootPath) {\n  const folder = path.join(rootPath || process.cwd(), 'node_modules', packageName);\n  const rnpm = getRNPMConfig(\n    path.join(rootPath || process.cwd(), 'node_modules', packageName)\n  );\n\n  return Object.assign({}, rnpm, {\n    ios: ios.dependencyConfig(folder, rnpm.ios || {}),\n    android: android.dependencyConfig(folder, rnpm.android || {}),\n    assets: findAssets(folder, rnpm.assets),\n    commands: wrapCommands(rnpm.commands),\n    params: rnpm.params || [],\n  });\n};\n"
  },
  {
    "path": "local-cli/core/config/ios/findProject.js",
    "content": "const glob = require('glob');\nconst path = require('path');\n\n/**\n * Glob pattern to look for xcodeproj\n */\nconst GLOB_PATTERN = '**/*.xcodeproj';\n\n/**\n * Regexp matching all test projects\n */\nconst TEST_PROJECTS = /test|example|sample/i;\n\n/**\n * Base iOS folder\n */\nconst IOS_BASE = 'ios';\n\n/**\n * These folders will be excluded from search to speed it up\n */\nconst GLOB_EXCLUDE_PATTERN = ['**/@(Pods|node_modules)/**'];\n\n/**\n * Finds iOS project by looking for all .xcodeproj files\n * in given folder.\n *\n * Returns first match if files are found or null\n *\n * Note: `./ios/*.xcodeproj` are returned regardless of the name\n */\nmodule.exports = function findProject(folder) {\n  const projects = glob\n    .sync(GLOB_PATTERN, {\n      cwd: folder,\n      ignore: GLOB_EXCLUDE_PATTERN,\n    })\n    .filter(project => {\n      return path.dirname(project) === IOS_BASE || !TEST_PROJECTS.test(project);\n    });\n\n  if (projects.length === 0) {\n    return null;\n  }\n\n  return projects[0];\n};\n"
  },
  {
    "path": "local-cli/core/config/ios/index.js",
    "content": "const path = require('path');\nconst findProject = require('./findProject');\n\n/**\n * For libraries specified without an extension, add '.tbd' for those that\n * start with 'lib' and '.framework' to the rest.\n */\nconst mapSharedLibaries = (libraries) => {\n  return libraries.map(name => {\n    if (path.extname(name)) {\n      return name;\n    }\n    return name + (name.indexOf('lib') === 0 ? '.tbd' : '.framework');\n  });\n};\n\n/**\n * Returns project config by analyzing given folder and applying some user defaults\n * when constructing final object\n */\nexports.projectConfig = function projectConfigIOS(folder, userConfig) {\n  const project = userConfig.project || findProject(folder);\n  console.log(folder, userConfig);\n  /**\n   * No iOS config found here\n   */\n  if (!project) {\n    return null;\n  }\n\n  const projectPath = path.join(folder, project);\n\n  return {\n    sourceDir: path.dirname(projectPath),\n    folder: folder,\n    pbxprojPath: path.join(projectPath, 'project.pbxproj'),\n    projectPath: projectPath,\n    projectName: path.basename(projectPath),\n    libraryFolder: userConfig.libraryFolder || 'Libraries',\n    sharedLibraries: mapSharedLibaries(userConfig.sharedLibraries || []),\n    plist: userConfig.plist || [],\n  };\n};\n\nexports.dependencyConfig = exports.projectConfig;\n"
  },
  {
    "path": "local-cli/core/config/wrapCommands.js",
    "content": "const makeCommand = require('../makeCommand');\n\nmodule.exports = function wrapCommands(commands) {\n  const mappedCommands = {};\n  Object.keys(commands || []).forEach((k) =>\n    mappedCommands[k] = makeCommand(commands[k])\n  );\n  return mappedCommands;\n};\n"
  },
  {
    "path": "local-cli/core/findPlugins.js",
    "content": "const path = require('path');\nconst union = require('lodash').union;\nconst uniq = require('lodash').uniq;\nconst flatten = require('lodash').flatten;\n\n/**\n * Filter dependencies by name pattern\n * @param  {String} dependency Name of the dependency\n * @return {Boolean}           If dependency is a rnpm plugin\n */\nconst isRNPMPlugin = (dependency) => dependency.indexOf('rnpm-plugin-') === 0;\nconst isReactNativePlugin = (dependency) => dependency.indexOf('react-native-') === 0;\n\nconst readPackage = (folder) => {\n  try {\n    return require(path.join(folder, 'package.json'));\n  } catch (e) {\n    return null;\n  }\n};\n\nconst findPluginsInReactNativePackage = (pjson) => {\n  if (!pjson.rnpm || !pjson.rnpm.plugin) {\n    return [];\n  }\n\n  return path.join(pjson.name, pjson.rnpm.plugin);\n};\n\nconst findPluginInFolder = (folder) => {\n  const pjson = readPackage(folder);\n\n  if (!pjson) {\n    return [];\n  }\n\n  const deps = union(\n    Object.keys(pjson.dependencies || {}),\n    Object.keys(pjson.devDependencies || {})\n  );\n\n  return deps.reduce(\n    (acc, pkg) => {\n      if (isRNPMPlugin(pkg)) {\n        return acc.concat(pkg);\n      }\n      if (isReactNativePlugin(pkg)) {\n        const pkgJson = readPackage(path.join(folder, 'node_modules', pkg));\n        if (!pkgJson) {\n          return acc;\n        }\n        return acc.concat(findPluginsInReactNativePackage(pkgJson));\n      }\n      return acc;\n    },\n    []\n  );\n};\n\n/**\n * Find plugins in package.json of the given folder\n * @param {String} folder Path to the folder to get the package.json from\n * @type  {Array}         Array of plugins or an empty array if no package.json found\n */\nmodule.exports = function findPlugins(folders) {\n  return uniq(flatten(folders.map(findPluginInFolder)));\n};\n"
  },
  {
    "path": "local-cli/core/getCommands.js",
    "content": "const path = require('path');\nconst findPlugins = require('./findPlugins');\nconst flatten = require('lodash').flatten;\n\nconst attachPackage = (command, pkg) => Array.isArray(command)\n  ? command.map(cmd => attachPackage(cmd, pkg))\n  : { ...command, pkg };\n\n/**\n * @return {Array} Array of commands\n */\nmodule.exports = function getCommands() {\n  const appRoot = process.cwd();\n  const plugins = findPlugins([appRoot])\n    .map(pathToCommands => {\n      const name = pathToCommands.split(path.sep)[0];\n\n      return attachPackage(\n        require(path.join(appRoot, 'node_modules', pathToCommands)),\n        require(path.join(appRoot, 'node_modules', name, 'package.json'))\n      );\n    });\n\n  return flatten(plugins);\n};\n"
  },
  {
    "path": "local-cli/core/makeCommand.js",
    "content": "const spawn = require('child_process').spawn;\n\nmodule.exports = function makeCommand(command) {\n  return (cb) => {\n    if (!cb) {\n      throw new Error(`You missed a callback function for the ${command} command`);\n    }\n\n    const args = command.split(' ');\n    const cmd = args.shift();\n\n    const commandProcess = spawn(cmd, args, {\n      stdio: 'inherit',\n      stdin: 'inherit',\n    });\n\n    commandProcess.on('close', function prelink(code) {\n      if (code) {\n        throw new Error(`Error occured during executing \"${command}\" command`);\n      }\n\n      cb();\n    });\n  };\n};\n"
  },
  {
    "path": "local-cli/default.config.js",
    "content": "'use strict';\n\nvar blacklist = require('../packager/blacklist');\nvar path = require('path');\nvar rnpmConfig = require('./core/config');\n\n/**\n * Default configuration for the CLI.\n *\n * If you need to override any of this functions do so by defining the file\n * `rn-cli.config.js` on the root of your project with the functions you need\n * to tweak.\n */\nvar config = {\n  getProjectRoots() {\n    return getRoots();\n  },\n\n  getProjectConfig: rnpmConfig.getProjectConfig,\n  getDependencyConfig: rnpmConfig.getDependencyConfig,\n\n  /**\n   * Specify where to look for assets that are referenced using\n   * `image!<image_name>`. Asset directories for images referenced using\n   * `./<image.extension>` don't require any entry in here.\n   */\n  getAssetRoots() {\n    return getRoots();\n  },\n\n  /**\n   * Specify any additional asset extentions to be used by the packager.\n   * For example, if you want to include a .ttf file, you would return ['ttf']\n   * from here and use `require('./fonts/example.ttf')` inside your app.\n   */\n  getAssetExts() {\n    return [];\n  },\n\n  /**\n   * Returns a regular expression for modules that should be ignored by the\n   * packager on a given platform.\n   */\n  getBlacklistRE(platform) {\n    return blacklist(platform);\n  },\n\n  /**\n   * Returns the path to a custom transformer. This can also be overridden\n   * with the --transformer commandline argument.\n   */\n  getTransformModulePath() {\n    return require.resolve('../packager/transformer');\n  },\n};\n\nfunction getRoots() {\n  var root = process.env.REACT_NATIVE_APP_ROOT;\n  if (root) {\n    return [path.resolve(root)];\n  }\n  if (__dirname.match(/node_modules[\\/\\\\]react-native[\\/\\\\]local-cli$/)) {\n    // Packager is running from node_modules.\n    // This is the default case for all projects created using 'react-native init'.\n    return [path.resolve(__dirname, '../../..')];\n  } else if (__dirname.match(/Pods[\\/\\\\]React[\\/\\\\]packager$/)) {\n     // React Native was installed using CocoaPods.\n    return [path.resolve(__dirname, '../../..')];\n  } else {\n    return [path.resolve(__dirname, '..')];\n  }\n}\n\nmodule.exports = config;\n"
  },
  {
    "path": "local-cli/dependencies/dependencies.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nconst fs = require('fs');\nconst path = require('path');\nconst Promise = require('promise');\nconst ReactPackager = require('../../packager/react-packager');\n\nfunction dependencies(argv, config, args, packagerInstance) {\n  const rootModuleAbsolutePath = args.entryFile;\n  if (!fs.existsSync(rootModuleAbsolutePath)) {\n    return Promise.reject(`File ${rootModuleAbsolutePath} does not exist`);\n  }\n\n  const transformModulePath =\n      args.transformer ? path.resolve(args.transformer) :\n      typeof config.getTransformModulePath === 'function' ? config.getTransformModulePath() :\n      undefined;\n\n  const packageOpts = {\n    projectRoots: config.getProjectRoots(),\n    assetRoots: config.getAssetRoots(),\n    blacklistRE: config.getBlacklistRE(args.platform),\n    getTransformOptionsModulePath: config.getTransformOptionsModulePath,\n    transformModulePath: transformModulePath,\n    extraNodeModules: config.extraNodeModules,\n    verbose: config.verbose,\n  };\n\n  const relativePath = packageOpts.projectRoots.map(root =>\n    path.relative(\n      root,\n      rootModuleAbsolutePath\n    )\n  )[0];\n\n  const options = {\n    platform: args.platform,\n    entryFile: relativePath,\n  };\n\n  const writeToFile = args.output;\n  const outStream = writeToFile\n    ? fs.createWriteStream(args.output)\n    : process.stdout;\n\n  return Promise.resolve((packagerInstance ?\n    packagerInstance.getOrderedDependencyPaths(options) :\n    ReactPackager.getOrderedDependencyPaths(packageOpts, options)).then(\n    deps => {\n      deps.forEach(modulePath => {\n        // Temporary hack to disable listing dependencies not under this directory.\n        // Long term, we need either\n        // (a) JS code to not depend on anything outside this directory, or\n        // (b) Come up with a way to declare this dependency in Buck.\n        const isInsideProjectRoots = packageOpts.projectRoots.filter(\n          root => modulePath.startsWith(root)\n        ).length > 0;\n\n        if (isInsideProjectRoots) {\n          outStream.write(modulePath + '\\n');\n        }\n      });\n      return writeToFile\n        ? Promise.denodeify(outStream.end).bind(outStream)()\n        : Promise.resolve();\n    }\n  ));\n}\n\nmodule.exports = {\n  name: 'dependencies',\n  func: dependencies,\n  options: [\n    {\n      command: '--entry-file <path>',\n      description: 'Absolute path to the root JS file',\n    }, {\n      command: '--output [path]',\n      description: 'File name where to store the output, ex. /tmp/dependencies.txt',\n    }, {\n      command: '--platform [extension]',\n      description: 'The platform extension used for selecting modules',\n    }, {\n      command: '--transformer [path]',\n      description: 'Specify a custom transformer to be used'\n    }, {\n      command: '--verbose',\n      description: 'Enables logging',\n      default: false,\n    },\n  ],\n};\n"
  },
  {
    "path": "local-cli/generate/generate.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst parseCommandLine = require('../util/parseCommandLine');\nconst path = require('path');\nconst Promise = require('promise');\nconst yeoman = require('yeoman-environment');\n\n/**\n * Generates the template for the given platform.\n */\nfunction generate(argv, config) {\n  return new Promise((resolve, reject) => {\n    _generate(argv, config, resolve, reject);\n  });\n}\n\nfunction _generate(argv, config, resolve, reject) {\n  const args = parseCommandLine([{\n    command: 'platform',\n    description: 'Platform (ios|android)',\n    type: 'string',\n    required: true,\n  },\n  {\n    command: 'project-path',\n    description: 'Path to the project directory',\n    type: 'string',\n    required: true,\n  },\n  {\n    command: 'project-name',\n    description: 'Name of the project',\n    type: 'string',\n    required: true,\n  }], argv);\n\n  const oldCwd = process.cwd();\n  process.chdir(args['project-path']);\n\n  const env = yeoman.createEnv();\n  env.register(path.join(__dirname, '../generator'), 'react:app');\n  env.run(\n    ['react:app', args['project-name']],\n    {\n      'skip-ios': args.platform !== 'ios',\n      'skip-android': args.platform !== 'android'\n    },\n    () => {\n      process.chdir(oldCwd);\n      resolve();\n    }\n  );\n}\n\nmodule.exports = generate;\n"
  },
  {
    "path": "local-cli/generate-android.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar fs = require('fs');\nvar path = require('path');\nvar yeoman = require('yeoman-environment');\n\n/**\n * Simple utility for running the android yeoman generator.\n *\n * @param  {String} projectDir root project directory (i.e. contains index.js)\n * @param  {String} name       name of the root JS module for this app\n */\nmodule.exports = function(projectDir, name) {\n  var oldCwd = process.cwd();\n  process.chdir(projectDir);\n\n  var env = yeoman.createEnv();\n  var generatorPath = path.join(__dirname, 'generator');\n  env.register(generatorPath, 'react:app');\n  var args = ['react:app', name].concat(process.argv.slice(4));\n  env.run(args, {'skip-ios': true}, function() {\n    process.chdir(oldCwd);\n  });\n};\n"
  },
  {
    "path": "local-cli/generator/index.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar fs = require('fs');\nvar path = require('path');\nvar yeoman = require('yeoman-generator');\nvar utils = require('../generator-utils');\n\nmodule.exports = yeoman.generators.NamedBase.extend({\n  constructor: function() {\n    yeoman.generators.NamedBase.apply(this, arguments);\n    this.option('skip-ios', {\n      desc: 'Skip generating iOS files',\n      type: Boolean,\n      defaults: false\n    });\n    this.option('skip-android', {\n      desc: 'Skip generating Android files',\n      type: Boolean,\n      defaults: false\n    });\n    this.option('skip-jest', {\n      desc: 'Skip installing Jest',\n      type: Boolean,\n      defaults: false\n    });\n    this.option('upgrade', {\n      desc: 'Specify an upgrade',\n      type: Boolean,\n      defaults: false\n    });\n\n    // this passes command line arguments down to the composed generators\n    var args = {args: arguments[0], options: this.options};\n    if (!this.options['skip-ios']) {\n      this.composeWith('react:ios', args, {\n        local: require.resolve(path.resolve(__dirname, '..', 'generator-ios'))\n      });\n    }\n    if (!this.options['skip-android']) {\n      this.composeWith('react:android', args, {\n        local: require.resolve(path.resolve(__dirname, '..', 'generator-android'))\n      });\n    }\n  },\n\n  configuring: function() {\n    utils.copyAndReplace(\n      this.templatePath('../../../.flowconfig'),\n      this.destinationPath('.flowconfig'),\n      {\n        'Libraries\\/react-native\\/react-native-interface.js' : 'node_modules/react-native/Libraries/react-native/react-native-interface.js',\n        '^flow/$' : 'node_modules/react-native/flow\\nflow/'\n      }\n    );\n\n    this.fs.copy(\n      this.templatePath('_gitignore'),\n      this.destinationPath('.gitignore')\n    );\n    this.fs.copy(\n      this.templatePath('_watchmanconfig'),\n      this.destinationPath('.watchmanconfig')\n    );\n    this.fs.copy(\n      this.templatePath('_buckconfig'),\n      this.destinationPath('.buckconfig')\n    );\n  },\n\n  writing: function() {\n    if (this.options.upgrade) {\n      // never upgrade index.*.js files\n      return;\n    }\n    if (!this.options['skip-ios']) {\n      this.fs.copyTpl(\n        this.templatePath('index.ios.js'),\n        this.destinationPath('index.ios.js'),\n        {name: this.name}\n      );\n    }\n    if (!this.options['skip-android']) {\n      this.fs.copyTpl(\n        this.templatePath('index.android.js'),\n        this.destinationPath('index.android.js'),\n        {name: this.name}\n      );\n    }\n  },\n\n  install: function() {\n    if (this.options.upgrade) {\n      return;\n    }\n\n    var reactNativePackageJson = require('../../package.json');\n    var { peerDependencies } = reactNativePackageJson;\n    if (!peerDependencies) {\n      return;\n    }\n\n    var reactVersion = peerDependencies.react;\n    if (!reactVersion) {\n      return;\n    }\n\n    this.npmInstall(`react@${reactVersion}`, { '--save': true, '--save-exact': true });\n    if (!this.options['skip-jest']) {\n      this.npmInstall(`jest babel-jest jest-react-native babel-preset-react-native react-test-renderer@${reactVersion}`.split(' '), {\n        saveDev: true,\n        '--save-exact': true\n      });\n      fs.writeFileSync(\n        path.join(\n          this.destinationRoot(),\n          '.babelrc'\n        ),\n        '{\\n\"presets\": [\"react-native\"]\\n}'\n      );\n\n      this.fs.copy(\n        this.templatePath('__tests__'),\n        this.destinationPath('__tests__'),\n        {\n          nodir: false\n        }\n      );\n\n      var packageJSONPath = path.join(\n        this.destinationRoot(),\n        'package.json'\n      );\n      var packageJSON = JSON.parse(\n        fs.readFileSync(\n          packageJSONPath\n        )\n      );\n      packageJSON.scripts.test = 'jest';\n      packageJSON.jest = {\n        preset: 'jest-react-native'\n      };\n      fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON, null, '\\t'));\n    }\n  }\n});\n"
  },
  {
    "path": "local-cli/generator-android/index.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar chalk = require('chalk');\nvar fs = require('fs');\nvar path = require('path');\nvar yeoman = require('yeoman-generator');\n\nfunction validatePackageName(name) {\n  if (!name.match(/^([a-zA-Z][a-zA-Z\\d_]*\\.)+([a-zA-Z_][a-zA-Z\\d_]*)$/)) {\n    return false;\n  }\n  return true;\n}\n\nmodule.exports = yeoman.generators.NamedBase.extend({\n  constructor: function() {\n    yeoman.generators.NamedBase.apply(this, arguments);\n\n    this.option('package', {\n      desc: 'Package name for the application (com.example.app)',\n      type: String,\n      defaults: 'com.' + this.name.toLowerCase()\n    });\n    this.option('upgrade', {\n      desc: 'Specify an upgrade',\n      type: Boolean,\n      defaults: false\n    });\n  },\n\n  initializing: function() {\n    if (!validatePackageName(this.options.package)) {\n      throw new Error('Package name ' + this.options.package + ' is invalid');\n    }\n  },\n\n  writing: function() {\n    var templateParams = {\n      package: this.options.package,\n      name: this.name\n    };\n    if (!this.options.upgrade) {\n      this.fs.copyTpl(\n        this.templatePath(path.join('src', '**')),\n        this.destinationPath('android'),\n        templateParams\n      );\n      this.fs.copy(\n        this.templatePath(path.join('bin', '**')),\n        this.destinationPath('android')\n      );\n    } else {\n      this.fs.copyTpl(\n        this.templatePath(path.join('src', '*')),\n        this.destinationPath('android'),\n        templateParams\n      );\n      this.fs.copyTpl(\n        this.templatePath(path.join('src', 'app', '*')),\n        this.destinationPath(path.join('android', 'app')),\n        templateParams\n      );\n    }\n\n    var javaPath = path.join.apply(\n      null,\n      ['android', 'app', 'src', 'main', 'java'].concat(this.options.package.split('.'))\n    );\n    this.fs.copyTpl(\n      this.templatePath(path.join('package', '**')),\n      this.destinationPath(javaPath),\n      templateParams\n    );\n  },\n\n  end: function() {\n    var projectPath = this.destinationRoot();\n    this.log(chalk.white.bold('To run your app on Android:'));\n    this.log(chalk.white('   Have an Android emulator running (quickest way to get started), or a device connected'));\n    this.log(chalk.white('   cd ' + projectPath));\n    this.log(chalk.white('   react-native run-android'));\n  }\n});\n"
  },
  {
    "path": "local-cli/generator-android/templates/bin/gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.4-all.zip\n"
  },
  {
    "path": "local-cli/generator-android/templates/bin/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "local-cli/generator-android/templates/bin/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "local-cli/generator-android/templates/package/MainActivity.java",
    "content": "package <%= package %>;\n\nimport com.facebook.react.ReactActivity;\n\npublic class MainActivity extends ReactActivity {\n\n    /**\n     * Returns the name of the main component registered from JavaScript.\n     * This is used to schedule rendering of the component.\n     */\n    @Override\n    protected String getMainComponentName() {\n        return \"<%= name %>\";\n    }\n}\n"
  },
  {
    "path": "local-cli/generator-android/templates/package/MainApplication.java",
    "content": "package <%= package %>;\n\nimport android.app.Application;\nimport android.util.Log;\n\nimport com.facebook.react.ReactApplication;\nimport com.facebook.react.ReactInstanceManager;\nimport com.facebook.react.ReactNativeHost;\nimport com.facebook.react.ReactPackage;\nimport com.facebook.react.shell.MainReactPackage;\n\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class MainApplication extends Application implements ReactApplication {\n\n  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {\n    @Override\n    protected boolean getUseDeveloperSupport() {\n      return BuildConfig.DEBUG;\n    }\n\n    @Override\n    protected List<ReactPackage> getPackages() {\n      return Arrays.<ReactPackage>asList(\n          new MainReactPackage()\n      );\n    }\n  };\n\n  @Override\n  public ReactNativeHost getReactNativeHost() {\n      return mReactNativeHost;\n  }\n}\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/app/BUCK",
    "content": "import re\n\n# To learn about Buck see [Docs](https://buckbuild.com/).\n# To run your application with Buck:\n# - install Buck\n# - `npm start` - to start the packager\n# - `cd android`\n# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname \"CN=Android Debug,O=Android,C=US\"`\n# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck\n# - `buck install -r android/app` - compile, install and run application\n#\n\nlib_deps = []\nfor jarfile in glob(['libs/*.jar']):\n  name = 'jars__' + re.sub(r'^.*/([^/]+)\\.jar$', r'\\1', jarfile)\n  lib_deps.append(':' + name)\n  prebuilt_jar(\n    name = name,\n    binary_jar = jarfile,\n  )\n\nfor aarfile in glob(['libs/*.aar']):\n  name = 'aars__' + re.sub(r'^.*/([^/]+)\\.aar$', r'\\1', aarfile)\n  lib_deps.append(':' + name)\n  android_prebuilt_aar(\n    name = name,\n    aar = aarfile,\n  )\n\nandroid_library(\n  name = 'all-libs',\n  exported_deps = lib_deps\n)\n\nandroid_library(\n  name = 'app-code',\n  srcs = glob([\n    'src/main/java/**/*.java',\n  ]),\n  deps = [\n    ':all-libs',\n    ':build_config',\n    ':res',\n  ],\n)\n\nandroid_build_config(\n  name = 'build_config',\n  package = '<%= package %>',\n)\n\nandroid_resource(\n  name = 'res',\n  res = 'src/main/res',\n  package = '<%= package %>',\n)\n\nandroid_binary(\n  name = 'app',\n  package_type = 'debug',\n  manifest = 'src/main/AndroidManifest.xml',\n  keystore = '//android/keystores:debug',\n  deps = [\n    ':app-code',\n  ],\n)\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/app/build.gradle",
    "content": "apply plugin: \"com.android.application\"\n\nimport com.android.build.OutputFile\n\n/**\n * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets\n * and bundleReleaseJsAndAssets).\n * These basically call `react-native bundle` with the correct arguments during the Android build\n * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the\n * bundle directly from the development server. Below you can see all the possible configurations\n * and their defaults. If you decide to add a configuration block, make sure to add it before the\n * `apply from: \"../../node_modules/react-native/react.gradle\"` line.\n *\n * project.ext.react = [\n *   // the name of the generated asset file containing your JS bundle\n *   bundleAssetName: \"index.android.bundle\",\n *\n *   // the entry file for bundle generation\n *   entryFile: \"index.android.js\",\n *\n *   // whether to bundle JS and assets in debug mode\n *   bundleInDebug: false,\n *\n *   // whether to bundle JS and assets in release mode\n *   bundleInRelease: true,\n *\n *   // whether to bundle JS and assets in another build variant (if configured).\n *   // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants\n *   // The configuration property can be in the following formats\n *   //         'bundleIn${productFlavor}${buildType}'\n *   //         'bundleIn${buildType}'\n *   // bundleInFreeDebug: true,\n *   // bundleInPaidRelease: true,\n *   // bundleInBeta: true,\n *\n *   // the root of your project, i.e. where \"package.json\" lives\n *   root: \"../../\",\n *\n *   // where to put the JS bundle asset in debug mode\n *   jsBundleDirDebug: \"$buildDir/intermediates/assets/debug\",\n *\n *   // where to put the JS bundle asset in release mode\n *   jsBundleDirRelease: \"$buildDir/intermediates/assets/release\",\n *\n *   // where to put drawable resources / React Native assets, e.g. the ones you use via\n *   // require('./image.png')), in debug mode\n *   resourcesDirDebug: \"$buildDir/intermediates/res/merged/debug\",\n *\n *   // where to put drawable resources / React Native assets, e.g. the ones you use via\n *   // require('./image.png')), in release mode\n *   resourcesDirRelease: \"$buildDir/intermediates/res/merged/release\",\n *\n *   // by default the gradle tasks are skipped if none of the JS files or assets change; this means\n *   // that we don't look at files in android/ or ios/ to determine whether the tasks are up to\n *   // date; if you have any other folders that you want to ignore for performance reasons (gradle\n *   // indexes the entire tree), add them here. Alternatively, if you have JS files in android/\n *   // for example, you might want to remove it from here.\n *   inputExcludes: [\"android/**\", \"ios/**\"],\n *\n *   // override which node gets called and with what additional arguments\n *   nodeExecutableAndArgs: [\"node\"]\n *\n *   // supply additional arguments to the packager\n *   extraPackagerArgs: []\n * ]\n */\n\napply from: \"../../node_modules/react-native/react.gradle\"\n\n/**\n * Set this to true to create two separate APKs instead of one:\n *   - An APK that only works on ARM devices\n *   - An APK that only works on x86 devices\n * The advantage is the size of the APK is reduced by about 4MB.\n * Upload all the APKs to the Play Store and people will download\n * the correct one based on the CPU architecture of their device.\n */\ndef enableSeparateBuildPerCPUArchitecture = false\n\n/**\n * Run Proguard to shrink the Java bytecode in release builds.\n */\ndef enableProguardInReleaseBuilds = false\n\nandroid {\n    compileSdkVersion 23\n    buildToolsVersion \"23.0.1\"\n\n    defaultConfig {\n        applicationId \"<%= package %>\"\n        minSdkVersion 16\n        targetSdkVersion 22\n        versionCode 1\n        versionName \"1.0\"\n        ndk {\n            abiFilters \"armeabi-v7a\", \"x86\"\n        }\n    }\n    splits {\n        abi {\n            reset()\n            enable enableSeparateBuildPerCPUArchitecture\n            universalApk false  // If true, also generate a universal APK\n            include \"armeabi-v7a\", \"x86\"\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled enableProguardInReleaseBuilds\n            proguardFiles getDefaultProguardFile(\"proguard-android.txt\"), \"proguard-rules.pro\"\n        }\n    }\n    // applicationVariants are e.g. debug, release\n    applicationVariants.all { variant ->\n        variant.outputs.each { output ->\n            // For each separate APK per architecture, set a unique version code as described here:\n            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits\n            def versionCodes = [\"armeabi-v7a\":1, \"x86\":2]\n            def abi = output.getFilter(OutputFile.ABI)\n            if (abi != null) {  // null for the universal-debug, universal-release variants\n                output.versionCodeOverride =\n                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode\n            }\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: \"libs\", include: [\"*.jar\"])\n    compile \"com.android.support:appcompat-v7:23.0.1\"\n    compile \"com.facebook.react:react-native:+\"  // From node_modules\n}\n\n// Run this once to be able to run the application with BUCK\n// puts all compile dependencies into folder libs for BUCK to use\ntask copyDownloadableDepsToLibs(type: Copy) {\n  from configurations.compile\n  into 'libs'\n}\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Disabling obfuscation is useful if you collect stack traces from production crashes\n# (unless you are using a system that supports de-obfuscate the stack traces).\n-dontobfuscate\n\n# React Native\n\n# Keep our interfaces so they can be used by other ProGuard rules.\n# See http://sourceforge.net/p/proguard/bugs/466/\n-keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip\n-keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters\n-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip\n\n# Do not strip any method/class that is annotated with @DoNotStrip\n-keep @com.facebook.proguard.annotations.DoNotStrip class *\n-keep @com.facebook.common.internal.DoNotStrip class *\n-keepclassmembers class * {\n    @com.facebook.proguard.annotations.DoNotStrip *;\n    @com.facebook.common.internal.DoNotStrip *;\n}\n\n-keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {\n  void set*(***);\n  *** get*();\n}\n\n-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }\n-keep class * extends com.facebook.react.bridge.NativeModule { *; }\n-keepclassmembers,includedescriptorclasses class * { native <methods>; }\n-keepclassmembers class *  { @com.facebook.react.uimanager.UIProp <fields>; }\n-keepclassmembers class *  { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }\n-keepclassmembers class *  { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }\n\n-dontwarn com.facebook.react.**\n\n# okhttp\n\n-keepattributes Signature\n-keepattributes *Annotation*\n-keep class okhttp3.** { *; }\n-keep interface okhttp3.** { *; }\n-dontwarn okhttp3.**\n\n# okio\n\n-keep class sun.misc.Unsafe { *; }\n-dontwarn java.nio.file.*\n-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement\n-dontwarn okio.**\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"<%= package %>\"\n    android:versionCode=\"1\"\n    android:versionName=\"1.0\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>\n\n    <uses-sdk\n        android:minSdkVersion=\"16\"\n        android:targetSdkVersion=\"22\" />\n\n    <application\n      android:name=\".MainApplication\"\n      android:allowBackup=\"true\"\n      android:label=\"@string/app_name\"\n      android:icon=\"@mipmap/ic_launcher\"\n      android:theme=\"@style/AppTheme\">\n      <activity\n        android:name=\".MainActivity\"\n        android:label=\"@string/app_name\"\n        android:configChanges=\"keyboard|keyboardHidden|orientation|screenSize\">\n        <intent-filter>\n            <action android:name=\"android.intent.action.MAIN\" />\n            <category android:name=\"android.intent.category.LAUNCHER\" />\n        </intent-filter>\n      </activity>\n      <activity android:name=\"com.facebook.react.devsupport.DevSettingsActivity\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\"><%= name %></string>\n</resources>\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <!-- Customize your theme here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:1.3.1'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        mavenLocal()\n        jcenter()\n        maven {\n            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm\n            url \"$rootDir/../node_modules/react-native/android\"\n        }\n    }\n}\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n\nandroid.useDeprecatedNdk=true\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/keystores/BUCK",
    "content": "keystore(\n  name = 'debug',\n  store = 'debug.keystore',\n  properties = 'debug.keystore.properties',\n  visibility = [\n    'PUBLIC',\n  ],\n)\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/keystores/debug.keystore.properties",
    "content": "key.store=debug.keystore\nkey.alias=androiddebugkey\nkey.store.password=android\nkey.alias.password=android\n"
  },
  {
    "path": "local-cli/generator-android/templates/src/settings.gradle",
    "content": "rootProject.name = '<%= name %>'\n\ninclude ':app'\n"
  },
  {
    "path": "local-cli/generator-ios/index.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar chalk = require('chalk');\nvar path = require('path');\nvar yeoman = require('yeoman-generator');\n\nmodule.exports = yeoman.generators.NamedBase.extend({\n  writing: function() {\n    var templateVars = {name: this.name};\n    // SomeApp/ios/SomeApp\n    this.fs.copyTpl(\n      this.templatePath(path.join('app', '**')),\n      this.destinationPath(path.join('ios', this.name)),\n      templateVars\n    );\n\n    // SomeApp/ios/SomeAppTests\n    this.fs.copyTpl(\n      this.templatePath(path.join('tests', 'Tests.m')),\n      this.destinationPath(path.join('ios', this.name + 'Tests', this.name + 'Tests.m')),\n      templateVars\n    );\n    this.fs.copy(\n      this.templatePath(path.join('tests', 'Info.plist')),\n      this.destinationPath(path.join('ios', this.name + 'Tests', 'Info.plist'))\n    );\n\n    // SomeApp/ios/SomeApp.xcodeproj\n    this.fs.copyTpl(\n      this.templatePath(path.join('xcodeproj', 'project.pbxproj')),\n      this.destinationPath(path.join('ios', this.name + '.xcodeproj', 'project.pbxproj')),\n      templateVars\n    );\n    this.fs.copyTpl(\n      this.templatePath(path.join('xcodeproj', 'xcshareddata', 'xcschemes', '_xcscheme')),\n      this.destinationPath(path.join('ios', this.name + '.xcodeproj', 'xcshareddata', 'xcschemes', this.name + '.xcscheme')),\n      templateVars\n    );\n  },\n\n  end: function() {\n    var projectPath = path.resolve(this.destinationRoot(), 'ios', this.name);\n    this.log(chalk.white.bold('To run your app on iOS:'));\n    this.log(chalk.white('   cd ' + this.destinationRoot()));\n    this.log(chalk.white('   react-native run-ios'));\n    this.log(chalk.white('   - or -'));\n    this.log(chalk.white('   Open ' + projectPath + '.xcodeproj in Xcode'));\n    this.log(chalk.white('   Hit the Run button'));\n  }\n});\n"
  },
  {
    "path": "local-cli/generator-ios/templates/app/AppDelegate.h",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (nonatomic, strong) UIWindow *window;\n\n@end\n"
  },
  {
    "path": "local-cli/generator-ios/templates/app/AppDelegate.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import \"AppDelegate.h\"\n\n#import \"RCTBundleURLProvider.h\"\n#import \"RCTRootView.h\"\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\n{\n  NSURL *jsCodeLocation;\n\n  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\"index.ios\" fallbackResource:nil];\n\n  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation\n                                                      moduleName:@\"<%= name %>\"\n                                               initialProperties:nil\n                                                   launchOptions:launchOptions];\n  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];\n\n  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n  UIViewController *rootViewController = [UIViewController new];\n  rootViewController.view = rootView;\n  self.window.rootViewController = rootViewController;\n  [self.window makeKeyAndVisible];\n  return YES;\n}\n\n@end\n"
  },
  {
    "path": "local-cli/generator-ios/templates/app/Base.lproj/LaunchScreen.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"7702\" systemVersion=\"14D136\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"7701\"/>\n        <capability name=\"Constraints with non-1.0 multipliers\" minToolsVersion=\"5.1\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <view contentMode=\"scaleToFill\" id=\"iN0-l3-epB\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"480\" height=\"480\"/>\n            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n            <subviews>\n                <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Powered by React Native\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"9\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8ie-xW-0ye\">\n                    <rect key=\"frame\" x=\"20\" y=\"439\" width=\"441\" height=\"21\"/>\n                    <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                    <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                    <nil key=\"highlightedColor\"/>\n                </label>\n                <label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"<%= name %>\" textAlignment=\"center\" lineBreakMode=\"middleTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kId-c2-rCX\">\n                    <rect key=\"frame\" x=\"20\" y=\"140\" width=\"441\" height=\"43\"/>\n                    <fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"36\"/>\n                    <color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                    <nil key=\"highlightedColor\"/>\n                </label>\n            </subviews>\n            <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n            <constraints>\n                <constraint firstItem=\"kId-c2-rCX\" firstAttribute=\"centerY\" secondItem=\"iN0-l3-epB\" secondAttribute=\"bottom\" multiplier=\"1/3\" constant=\"1\" id=\"5cJ-9S-tgC\"/>\n                <constraint firstAttribute=\"centerX\" secondItem=\"kId-c2-rCX\" secondAttribute=\"centerX\" id=\"Koa-jz-hwk\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"8ie-xW-0ye\" secondAttribute=\"bottom\" constant=\"20\" id=\"Kzo-t9-V3l\"/>\n                <constraint firstItem=\"8ie-xW-0ye\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"MfP-vx-nX0\"/>\n                <constraint firstAttribute=\"centerX\" secondItem=\"8ie-xW-0ye\" secondAttribute=\"centerX\" id=\"ZEH-qu-HZ9\"/>\n                <constraint firstItem=\"kId-c2-rCX\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"fvb-Df-36g\"/>\n            </constraints>\n            <nil key=\"simulatedStatusBarMetrics\"/>\n            <freeformSimulatedSizeMetrics key=\"simulatedDestinationMetrics\"/>\n            <point key=\"canvasLocation\" x=\"548\" y=\"455\"/>\n        </view>\n    </objects>\n</document>\n"
  },
  {
    "path": "local-cli/generator-ios/templates/app/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "local-cli/generator-ios/templates/app/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n\t<key>NSLocationWhenInUseUsageDescription</key>\n\t<string></string>\n\t<key>NSAppTransportSecurity</key>\n\t<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->\n\t<dict>\n\t\t<key>NSExceptionDomains</key>\n\t\t<dict>\n\t\t\t<key>localhost</key>\n\t\t\t<dict>\n\t\t\t\t<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>\n\t\t\t\t<true/>\n\t\t\t</dict>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "local-cli/generator-ios/templates/app/main.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import <UIKit/UIKit.h>\n\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n  @autoreleasepool {\n    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n  }\n}\n"
  },
  {
    "path": "local-cli/generator-ios/templates/tests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "local-cli/generator-ios/templates/tests/Tests.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import <UIKit/UIKit.h>\n#import <XCTest/XCTest.h>\n\n#import \"RCTLog.h\"\n#import \"RCTRootView.h\"\n\n#define TIMEOUT_SECONDS 600\n#define TEXT_TO_LOOK_FOR @\"Welcome to React Native!\"\n\n@interface <%= name %>Tests : XCTestCase\n\n@end\n\n@implementation <%= name %>Tests\n\n- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test\n{\n  if (test(view)) {\n    return YES;\n  }\n  for (UIView *subview in [view subviews]) {\n    if ([self findSubviewInView:subview matching:test]) {\n      return YES;\n    }\n  }\n  return NO;\n}\n\n- (void)testRendersWelcomeScreen\n{\n  UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];\n  NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];\n  BOOL foundElement = NO;\n\n  __block NSString *redboxError = nil;\n  RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {\n    if (level >= RCTLogLevelError) {\n      redboxError = message;\n    }\n  });\n\n  while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {\n    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n    [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];\n\n    foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {\n      if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {\n        return YES;\n      }\n      return NO;\n    }];\n  }\n\n  RCTSetLogFunction(RCTDefaultLogFunction);\n\n  XCTAssertNil(redboxError, @\"RedBox error: %@\", redboxError);\n  XCTAssertTrue(foundElement, @\"Couldn't find element with text '%@' in %d seconds\", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);\n}\n\n\n@end\n"
  },
  {
    "path": "local-cli/generator-ios/templates/xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };\n\t\t00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };\n\t\t00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };\n\t\t00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };\n\t\t00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };\n\t\t00E356F31AD99517003FC87E /* <%= name %>Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* <%= name %>Tests.m */; };\n\t\t133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };\n\t\t139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };\n\t\t139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };\n\t\t13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };\n\t\t13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };\n\t\t13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };\n\t\t13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };\n\t\t140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };\n\t\t146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };\n\t\t832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTActionSheet;\n\t\t};\n\t\t00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTGeolocation;\n\t\t};\n\t\t00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B5115D1A9E6B3D00147676;\n\t\t\tremoteInfo = RCTImage;\n\t\t};\n\t\t00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B511DB1A9E6C8500147676;\n\t\t\tremoteInfo = RCTNetwork;\n\t\t};\n\t\t00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 832C81801AAF6DEF007FA2F7;\n\t\t\tremoteInfo = RCTVibration;\n\t\t};\n\t\t00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 13B07F861A680F5B00A75B9A;\n\t\t\tremoteInfo = <%= name %>;\n\t\t};\n\t\t139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTSettings;\n\t\t};\n\t\t139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 3C86DF461ADF2C930047B81A;\n\t\t\tremoteInfo = RCTWebSocket;\n\t\t};\n\t\t146834031AC3E56700842450 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;\n\t\t\tremoteInfo = React;\n\t\t};\n\t\t78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 134814201AA4EA6300B7C361;\n\t\t\tremoteInfo = RCTLinking;\n\t\t};\n\t\t832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 58B5119B1A9E6C1200147676;\n\t\t\tremoteInfo = RCTText;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = main.jsbundle; sourceTree = \"<group>\"; };\n\t\t00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTActionSheet.xcodeproj; path = ../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = \"<group>\"; };\n\t\t00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTGeolocation.xcodeproj; path = ../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = \"<group>\"; };\n\t\t00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTImage.xcodeproj; path = ../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj; sourceTree = \"<group>\"; };\n\t\t00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTNetwork.xcodeproj; path = ../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj; sourceTree = \"<group>\"; };\n\t\t00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTVibration.xcodeproj; path = ../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = \"<group>\"; };\n\t\t00E356EE1AD99517003FC87E /* <%= name %>Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = <%= name %>Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t00E356F21AD99517003FC87E /* <%= name %>Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = <%= name %>Tests.m; sourceTree = \"<group>\"; };\n\t\t139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTSettings.xcodeproj; path = ../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj; sourceTree = \"<group>\"; };\n\t\t139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTWebSocket.xcodeproj; path = ../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = \"<group>\"; };\n\t\t13B07F961A680F5B00A75B9A /* <%= name %>.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = <%= name %>.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = <%= name %>/AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = <%= name %>/AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = \"<group>\"; };\n\t\t13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = <%= name %>/Images.xcassets; sourceTree = \"<group>\"; };\n\t\t13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = <%= name %>/Info.plist; sourceTree = \"<group>\"; };\n\t\t13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = <%= name %>/main.m; sourceTree = \"<group>\"; };\n\t\t146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = React.xcodeproj; path = ../node_modules/react-native/React/React.xcodeproj; sourceTree = \"<group>\"; };\n\t\t78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTLinking.xcodeproj; path = ../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = \"<group>\"; };\n\t\t832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; name = RCTText.xcodeproj; path = ../node_modules/react-native/Libraries/Text/RCTText.xcodeproj; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t00E356EB1AD99517003FC87E /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F8C1A680F5B00A75B9A /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t146834051AC3E58100842450 /* libReact.a in Frameworks */,\n\t\t\t\t00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,\n\t\t\t\t00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,\n\t\t\t\t00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,\n\t\t\t\t133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,\n\t\t\t\t00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,\n\t\t\t\t139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,\n\t\t\t\t832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,\n\t\t\t\t00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,\n\t\t\t\t139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t00C302A81ABCB8CE00DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302B61ABCB90400DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302BC1ABCB91800DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302D41ABCB9D200DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00C302E01ABCB9EE00DB3ED1 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00E356EF1AD99517003FC87E /* <%= name %>Tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00E356F21AD99517003FC87E /* <%= name %>Tests.m */,\n\t\t\t\t00E356F01AD99517003FC87E /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = <%= name %>Tests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t00E356F01AD99517003FC87E /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t00E356F11AD99517003FC87E /* Info.plist */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t139105B71AF99BAD00B5F7CC /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t139FDEE71B06529A00C62182 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t13B07FAE1A68108700A75B9A /* <%= name %> */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t008F07F21AC5B25A0029DE68 /* main.jsbundle */,\n\t\t\t\t13B07FAF1A68108700A75B9A /* AppDelegate.h */,\n\t\t\t\t13B07FB01A68108700A75B9A /* AppDelegate.m */,\n\t\t\t\t13B07FB51A68108700A75B9A /* Images.xcassets */,\n\t\t\t\t13B07FB61A68108700A75B9A /* Info.plist */,\n\t\t\t\t13B07FB11A68108700A75B9A /* LaunchScreen.xib */,\n\t\t\t\t13B07FB71A68108700A75B9A /* main.m */,\n\t\t\t);\n\t\t\tname = <%= name %>;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t146834001AC3E56700842450 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t146834041AC3E56700842450 /* libReact.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t78C398B11ACF4ADC00677621 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t78C398B91ACF4ADC00677621 /* libRCTLinking.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t832341AE1AAA6A7D00B99B32 /* Libraries */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t146833FF1AC3E56700842450 /* React.xcodeproj */,\n\t\t\t\t00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,\n\t\t\t\t00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,\n\t\t\t\t00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,\n\t\t\t\t78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,\n\t\t\t\t00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,\n\t\t\t\t139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,\n\t\t\t\t832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,\n\t\t\t\t00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,\n\t\t\t\t139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,\n\t\t\t);\n\t\t\tname = Libraries;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t832341B11AAA6A8300B99B32 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t832341B51AAA6A8300B99B32 /* libRCTText.a */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t83CBB9F61A601CBA00E9B192 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07FAE1A68108700A75B9A /* <%= name %> */,\n\t\t\t\t832341AE1AAA6A7D00B99B32 /* Libraries */,\n\t\t\t\t00E356EF1AD99517003FC87E /* <%= name %>Tests */,\n\t\t\t\t83CBBA001A601CBA00E9B192 /* Products */,\n\t\t\t);\n\t\t\tindentWidth = 2;\n\t\t\tsourceTree = \"<group>\";\n\t\t\ttabWidth = 2;\n\t\t};\n\t\t83CBBA001A601CBA00E9B192 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07F961A680F5B00A75B9A /* <%= name %>.app */,\n\t\t\t\t00E356EE1AD99517003FC87E /* <%= name %>Tests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t00E356ED1AD99517003FC87E /* <%= name %>Tests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget \"<%= name %>Tests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t00E356EA1AD99517003FC87E /* Sources */,\n\t\t\t\t00E356EB1AD99517003FC87E /* Frameworks */,\n\t\t\t\t00E356EC1AD99517003FC87E /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t00E356F51AD99517003FC87E /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = <%= name %>Tests;\n\t\t\tproductName = <%= name %>Tests;\n\t\t\tproductReference = 00E356EE1AD99517003FC87E /* <%= name %>Tests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n\t\t13B07F861A680F5B00A75B9A /* <%= name %> */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget \"<%= name %>\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t13B07F871A680F5B00A75B9A /* Sources */,\n\t\t\t\t13B07F8C1A680F5B00A75B9A /* Frameworks */,\n\t\t\t\t13B07F8E1A680F5B00A75B9A /* Resources */,\n\t\t\t\t00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = <%= name %>;\n\t\t\tproductName = \"Hello World\";\n\t\t\tproductReference = 13B07F961A680F5B00A75B9A /* <%= name %>.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t83CBB9F71A601CBA00E9B192 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0610;\n\t\t\t\tORGANIZATIONNAME = Facebook;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t00E356ED1AD99517003FC87E = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.2;\n\t\t\t\t\t\tTestTargetID = 13B07F861A680F5B00A75B9A;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject \"<%= name %>\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 83CBB9F61A601CBA00E9B192;\n\t\t\tproductRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 78C398B11ACF4ADC00677621 /* Products */;\n\t\t\t\t\tProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;\n\t\t\t\t\tProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 832341B11AAA6A8300B99B32 /* Products */;\n\t\t\t\t\tProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;\n\t\t\t\t\tProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 139FDEE71B06529A00C62182 /* Products */;\n\t\t\t\t\tProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 146834001AC3E56700842450 /* Products */;\n\t\t\t\t\tProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t13B07F861A680F5B00A75B9A /* <%= name %> */,\n\t\t\t\t00E356ED1AD99517003FC87E /* <%= name %>Tests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXReferenceProxy section */\n\t\t00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTActionSheet.a;\n\t\t\tremoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTGeolocation.a;\n\t\t\tremoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTImage.a;\n\t\t\tremoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTNetwork.a;\n\t\t\tremoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTVibration.a;\n\t\t\tremoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTSettings.a;\n\t\t\tremoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTWebSocket.a;\n\t\t\tremoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t146834041AC3E56700842450 /* libReact.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libReact.a;\n\t\t\tremoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTLinking.a;\n\t\t\tremoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t832341B51AAA6A8300B99B32 /* libRCTText.a */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = archive.ar;\n\t\t\tpath = libRCTText.a;\n\t\t\tremoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n/* End PBXReferenceProxy section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t00E356EC1AD99517003FC87E /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F8E1A680F5B00A75B9A /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,\n\t\t\t\t13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Bundle React Native code and images\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"export NODE_BINARY=node\\n../node_modules/react-native/packager/react-native-xcode.sh\";\n\t\t\tshowEnvVarsInLog = 1;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t00E356EA1AD99517003FC87E /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t00E356F31AD99517003FC87E /* <%= name %>Tests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t13B07F871A680F5B00A75B9A /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,\n\t\t\t\t13B07FC11A68108700A75B9A /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t00E356F51AD99517003FC87E /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 13B07F861A680F5B00A75B9A /* <%= name %> */;\n\t\t\ttargetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t13B07FB21A68108700A75B9A /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.xib;\n\t\t\tpath = <%= name %>;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t00E356F61AD99517003FC87E /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = <%= name %>Tests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/<%= name %>.app/<%= name %>\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t00E356F71AD99517003FC87E /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tINFOPLIST_FILE = <%= name %>Tests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/<%= name %>.app/<%= name %>\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t13B07F941A680F5B00A75B9A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEAD_CODE_STRIPPING = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"$(SRCROOT)/../node_modules/react-native/React/**\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"<%= name %>/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = <%= name %>;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t13B07F951A680F5B00A75B9A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"$(SRCROOT)/../node_modules/react-native/React/**\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = \"<%= name %>/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"-ObjC\",\n\t\t\t\t\t\"-lc++\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_NAME = <%= name %>;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t83CBBA201A601CBA00E9B192 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"$(SRCROOT)/../node_modules/react-native/React/**\",\n\t\t\t\t);\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t83CBBA211A601CBA00E9B192 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,\n\t\t\t\t\t\"$(SRCROOT)/../node_modules/react-native/React/**\",\n\t\t\t\t);\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget \"<%= name %>Tests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t00E356F61AD99517003FC87E /* Debug */,\n\t\t\t\t00E356F71AD99517003FC87E /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget \"<%= name %>\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t13B07F941A680F5B00A75B9A /* Debug */,\n\t\t\t\t13B07F951A680F5B00A75B9A /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject \"<%= name %>\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t83CBBA201A601CBA00E9B192 /* Debug */,\n\t\t\t\t83CBBA211A601CBA00E9B192 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;\n}\n"
  },
  {
    "path": "local-cli/generator-ios/templates/xcodeproj/xcshareddata/xcschemes/_xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0620\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n               BuildableName = \"<%= name %>.app\"\n               BlueprintName = \"<%= name %>\"\n               ReferencedContainer = \"container:<%= name %>.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"NO\"\n            buildForArchiving = \"NO\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"00E356ED1AD99517003FC87E\"\n               BuildableName = \"<%= name %>Tests.xctest\"\n               BlueprintName = \"<%= name %>Tests\"\n               ReferencedContainer = \"container:<%= name %>.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      buildConfiguration = \"Debug\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"00E356ED1AD99517003FC87E\"\n               BuildableName = \"<%= name %>Tests.xctest\"\n               BlueprintName = \"<%= name %>Tests\"\n               ReferencedContainer = \"container:<%= name %>.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"<%= name %>.app\"\n            BlueprintName = \"<%= name %>\"\n            ReferencedContainer = \"container:<%= name %>.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </TestAction>\n   <LaunchAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Debug\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"<%= name %>.app\"\n            BlueprintName = \"<%= name %>\"\n            ReferencedContainer = \"container:<%= name %>.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Release\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"13B07F861A680F5B00A75B9A\"\n            BuildableName = \"<%= name %>.app\"\n            BlueprintName = \"<%= name %>\"\n            ReferencedContainer = \"container:<%= name %>.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "local-cli/generator-utils.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar path = require('path');\nvar fs = require('fs');\n\nfunction copyAndReplace(src, dest, replacements) {\n  if (fs.lstatSync(src).isDirectory()) {\n    if (!fs.existsSync(dest)) {\n      fs.mkdirSync(dest);\n    }\n  } else {\n    var content = fs.readFileSync(src, 'utf8');\n    Object.keys(replacements).forEach(function(regex) {\n      content = content.replace(new RegExp(regex, 'gm'), replacements[regex]);\n    });\n    fs.writeFileSync(dest, content);\n  }\n}\n\nfunction walk(current) {\n  if (!fs.lstatSync(current).isDirectory()) {\n    return [current];\n  }\n\n  var files = fs.readdirSync(current).map(function(child) {\n    child = path.join(current, child);\n    return walk(child);\n  });\n  return [].concat.apply([current], files);\n}\n\nmodule.exports = {\n  copyAndReplace: copyAndReplace,\n  walk: walk\n};\n"
  },
  {
    "path": "local-cli/init/init.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst path = require('path');\nconst TerminalAdapter = require('yeoman-environment/lib/adapter.js');\nconst yeoman = require('yeoman-environment');\n\nclass CreateSuppressingTerminalAdapter extends TerminalAdapter {\n  constructor() {\n    super();\n    // suppress 'create' output generated by yeoman\n    this.log.create = function() {};\n  }\n}\n\n/**\n * Creates the template for a React Native project given the provided\n * parameters:\n *   - projectDir: templates will be copied here.\n *   - argsOrName: project name or full list of custom arguments to pass to the\n *                 generator.\n */\nfunction init(projectDir, argsOrName) {\n  console.log('Setting up new React Native app in ' + projectDir);\n  const env = yeoman.createEnv(\n    undefined,\n    undefined,\n    new CreateSuppressingTerminalAdapter()\n  );\n\n  env.register(\n    require.resolve(path.join(__dirname, '../generator')),\n    'react:app'\n  );\n\n  // argv is for instance\n  // ['node', 'react-native', 'init', 'AwesomeApp', '--verbose']\n  // args should be ['AwesomeApp', '--verbose']\n  const args = Array.isArray(argsOrName)\n    ? argsOrName\n    : [argsOrName].concat(process.argv.slice(4));\n\n  const generator = env.create('react:app', {args: args});\n  generator.destinationRoot(projectDir);\n  generator.run();\n}\n\nmodule.exports = init;\n"
  },
  {
    "path": "local-cli/install/install.js",
    "content": "const spawnSync = require('child_process').spawnSync;\nconst log = require('npmlog');\nconst spawnOpts = {\n  stdio: 'inherit',\n  stdin: 'inherit',\n};\n\nlog.heading = 'rnpm-install';\n\nfunction install(args, config) {\n  const name = args[0];\n\n  var res = spawnSync('npm', ['install', name, '--save'], spawnOpts);\n\n  if (res.status) {\n    process.exit(res.status);\n  }\n\n  res = spawnSync('rnpm', ['link', name], spawnOpts);\n\n  if (res.status) {\n    process.exit(res.status);\n  }\n\n  log.info(`Module ${name} has been successfully installed & linked`);\n};\n\nmodule.exports = {\n  func: install,\n  description: 'install and link native dependencies',\n  name: 'install <packageName>',\n};\n"
  },
  {
    "path": "local-cli/install/uninstall.js",
    "content": "const spawnSync = require('child_process').spawnSync;\nconst log = require('npmlog');\nconst spawnOpts = {\n  stdio: 'inherit',\n  stdin: 'inherit',\n};\n\nlog.heading = 'rnpm-install';\n\nfunction uninstall(args, config) {\n  const name = args[0];\n\n  var res = spawnSync('rnpm', ['unlink', name], spawnOpts);\n\n  if (res.status) {\n    process.exit(res.status);\n  }\n\n  res = spawnSync('npm', ['uninstall', name], spawnOpts);\n\n  if (res.status) {\n    process.exit(res.status);\n  }\n\n  log.info(`Module ${name} has been successfully uninstalled & unlinked`);\n};\n\nmodule.exports = {\n  func: uninstall,\n  description: 'uninstall and unlink native dependencies',\n  name: 'uninstall <packageName>',\n};\n"
  },
  {
    "path": "local-cli/library/library.js",
    "content": " /**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst copyAndReplace = require('../util/copyAndReplace');\nconst fs = require('fs');\nconst isValidPackageName = require('../util/isValidPackageName');\nconst path = require('path');\nconst Promise = require('promise');\nconst walk = require('../util/walk');\n\n/**\n * Creates a new native library with the given name\n */\nfunction library(argv, config, args) {\n  if (!isValidPackageName(args.name)) {\n    return Promise.reject(\n      args.name + ' is not a valid name for a project. Please use a valid ' +\n      'identifier name (alphanumeric).'\n    );\n  }\n\n  const root = process.cwd();\n  const libraries = path.resolve(root, 'Libraries');\n  const libraryDest = path.resolve(libraries, args.name);\n  const source = path.resolve('node_modules', 'react-native', 'Libraries', 'Sample');\n\n  if (!fs.existsSync(libraries)) {\n    fs.mkdir(libraries);\n  }\n\n  if (fs.existsSync(libraryDest)) {\n    return Promise.reject(`Library already exists in ${libraryDest}`);\n  }\n\n  walk(source).forEach(f => {\n    if (f.indexOf('project.xcworkspace') !== -1 ||\n        f.indexOf('.xcodeproj/xcuserdata') !== -1) {\n      return;\n    }\n\n    const dest = f.replace(/Sample/g, args.name).replace(/^_/, '.');\n    copyAndReplace(\n      path.resolve(source, f),\n      path.resolve(libraryDest, dest),\n      {'Sample': args.name}\n    );\n  });\n\n  console.log('Created library in', libraryDest);\n  console.log('Next Steps:');\n  console.log('   Link your library in Xcode:');\n  console.log('   https://facebook.github.io/react-native/docs/linking-libraries-ios.html#content\\n');\n}\n\nmodule.exports = {\n  name: 'new-library',\n  func: library,\n  description: 'generates a native library bridge',\n  options: [{\n    command: '--name <string>',\n    description: 'name of the library to generate',\n    default: null,\n  }],\n};\n"
  },
  {
    "path": "local-cli/link/android/copyAssets.js",
    "content": "const fs = require('fs-extra');\nconst path = require('path');\nconst groupFilesByType = require('../groupFilesByType');\n\n/**\n * Copies each file from an array of assets provided to targetPath directory\n *\n * For now, the only types of files that are handled are:\n * - Fonts (otf, ttf) - copied to targetPath/fonts under original name\n */\nmodule.exports = function copyAssetsAndroid(files, targetPath) {\n  const assets = groupFilesByType(files);\n\n  (assets.font || []).forEach(asset =>\n    fs.copySync(asset, path.join(targetPath, 'fonts', path.basename(asset)))\n  );\n};\n"
  },
  {
    "path": "local-cli/link/android/fs.js",
    "content": "const fs = require('fs-extra');\n\nexports.readFile = (file) =>\n  () => fs.readFileSync(file, 'utf8');\n\nexports.writeFile = (file, content) => content ?\n  fs.writeFileSync(file, content, 'utf8') :\n  (c) => fs.writeFileSync(file, c, 'utf8');\n"
  },
  {
    "path": "local-cli/link/android/isInstalled.js",
    "content": "const fs = require('fs');\nconst makeBuildPatch = require('./patches/makeBuildPatch');\n\nmodule.exports = function isInstalled(config, name) {\n  return fs\n    .readFileSync(config.buildGradlePath)\n    .indexOf(makeBuildPatch(name).patch) > -1;\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/applyParams.js",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nconst toCamelCase = require('lodash').camelCase;\n\nmodule.exports = function applyParams(str, params, prefix) {\n  return str.replace(\n    /\\$\\{(\\w+)\\}/g,\n    (pattern, param) => {\n      const name = toCamelCase(prefix) + '_' + param;\n\n      return params[param]\n        ? `getResources().getString(R.string.${name})`\n        : null;\n    }\n  );\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/applyPatch.js",
    "content": "const fs = require('fs');\n\nmodule.exports = function applyPatch(file, patch) {\n  fs.writeFileSync(file, fs\n    .readFileSync(file, 'utf8')\n    .replace(patch.pattern, match => `${match}${patch.patch}`)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/makeBuildPatch.js",
    "content": "module.exports = function makeBuildPatch(name) {\n  return {\n    pattern: /[^ \\t]dependencies {\\n/,\n    patch: `    compile project(':${name}')\\n`,\n  };\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/makeImportPatch.js",
    "content": "module.exports = function makeImportPatch(packageImportPath) {\n  return {\n    pattern: 'import com.facebook.react.ReactApplication;',\n    patch: '\\n' + packageImportPath,\n  };\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/makePackagePatch.js",
    "content": "const applyParams = require('./applyParams');\n\nmodule.exports = function makePackagePatch(packageInstance, params, prefix) {\n  const processedInstance = applyParams(packageInstance, params, prefix);\n\n  return {\n    pattern: 'new MainReactPackage()',\n    patch: ',\\n            ' + processedInstance,\n  };\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/makeSettingsPatch.js",
    "content": "const path = require('path');\nconst isWin = process.platform === 'win32';\n\nmodule.exports = function makeSettingsPatch(name, androidConfig, projectConfig) {\n  var projectDir = path.relative(\n    path.dirname(projectConfig.settingsGradlePath),\n    androidConfig.sourceDir\n  );\n\n  /*\n   * Fix for Windows\n   * Backslashes is the escape character and will result in\n   * an invalid path in settings.gradle\n   * https://github.com/rnpm/rnpm/issues/113\n   */\n  if (isWin) {\n    projectDir = projectDir.replace(/\\\\/g, '/');\n  }\n\n  return {\n    pattern: 'include \\':app\\'\\n',\n    patch: `include ':${name}'\\n` +\n      `project(':${name}').projectDir = ` +\n      `new File(rootProject.projectDir, '${projectDir}')\\n`,\n  };\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/makeStringsPatch.js",
    "content": "const toCamelCase = require('lodash').camelCase;\n\nmodule.exports = function makeStringsPatch(params, prefix) {\n  const values = Object.keys(params)\n    .map(param => {\n      const name = toCamelCase(prefix) + '_' + param;\n      return '    ' +\n        `<string moduleConfig=\"true\" name=\"${name}\">${params[param]}</string>`;\n    });\n\n  const patch = values.length > 0\n    ? values.join('\\n') + '\\n'\n    : '';\n\n  return {\n    pattern: '<resources>\\n',\n    patch,\n  };\n};\n"
  },
  {
    "path": "local-cli/link/android/patches/revokePatch.js",
    "content": "const fs = require('fs');\n\nmodule.exports = function revokePatch(file, patch) {\n  fs.writeFileSync(file, fs\n    .readFileSync(file, 'utf8')\n    .replace(patch.patch, '')\n  );\n};\n"
  },
  {
    "path": "local-cli/link/android/registerNativeModule.js",
    "content": "const applyPatch = require('./patches/applyPatch');\nconst makeStringsPatch = require('./patches/makeStringsPatch');\nconst makeSettingsPatch = require('./patches/makeSettingsPatch');\nconst makeBuildPatch = require('./patches/makeBuildPatch');\nconst makeImportPatch = require('./patches/makeImportPatch');\nconst makePackagePatch = require('./patches/makePackagePatch');\n\nmodule.exports = function registerNativeAndroidModule(\n  name,\n  androidConfig,\n  params,\n  projectConfig\n) {\n  const buildPatch = makeBuildPatch(name);\n\n  applyPatch(\n    projectConfig.settingsGradlePath,\n    makeSettingsPatch(name, androidConfig, projectConfig)\n  );\n\n  applyPatch(projectConfig.buildGradlePath, buildPatch);\n  applyPatch(projectConfig.stringsPath, makeStringsPatch(params, name));\n\n  applyPatch(\n    projectConfig.mainFilePath,\n    makePackagePatch(androidConfig.packageInstance, params, name)\n  );\n\n  applyPatch(\n    projectConfig.mainFilePath,\n    makeImportPatch(androidConfig.packageImportPath)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/android/unlinkAssets.js",
    "content": "const fs = require('fs-extra');\nconst path = require('path');\nconst groupFilesByType = require('../groupFilesByType');\n\n/**\n * Copies each file from an array of assets provided to targetPath directory\n *\n * For now, the only types of files that are handled are:\n * - Fonts (otf, ttf) - copied to targetPath/fonts under original name\n */\nmodule.exports = function unlinkAssetsAndroid(files, targetPath) {\n  const grouped = groupFilesByType(files);\n\n  grouped.font.forEach((file) => {\n    const filename = path.basename(file);\n    if (fs.existsSync(filename)) {\n      fs.unlinkSync(path.join(targetPath, 'fonts', filename));\n    }\n  });\n};\n"
  },
  {
    "path": "local-cli/link/android/unregisterNativeModule.js",
    "content": "const fs = require('fs');\nconst toCamelCase = require('lodash').camelCase;\n\nconst revokePatch = require('./patches/revokePatch');\nconst makeSettingsPatch = require('./patches/makeSettingsPatch');\nconst makeBuildPatch = require('./patches/makeBuildPatch');\nconst makeStringsPatch = require('./patches/makeStringsPatch');\nconst makeImportPatch = require('./patches/makeImportPatch');\nconst makePackagePatch = require('./patches/makePackagePatch');\n\nmodule.exports = function unregisterNativeAndroidModule(\n  name,\n  androidConfig,\n  projectConfig\n) {\n  const buildPatch = makeBuildPatch(name);\n  const strings = fs.readFileSync(projectConfig.stringsPath, 'utf8');\n  var params = {};\n\n  strings.replace(\n    /moduleConfig=\"true\" name=\"(\\w+)\">(.*)</g,\n    (_, param, value) => {\n      params[param.slice(toCamelCase(name).length + 1)] = value;\n    }\n  );\n\n  revokePatch(\n    projectConfig.settingsGradlePath,\n    makeSettingsPatch(name, androidConfig, projectConfig)\n  );\n\n  revokePatch(projectConfig.buildGradlePath, buildPatch);\n  revokePatch(projectConfig.stringsPath, makeStringsPatch(params, name));\n\n  revokePatch(\n    projectConfig.mainFilePath,\n    makePackagePatch(androidConfig.packageInstance, params, name)\n  );\n\n  revokePatch(\n    projectConfig.mainFilePath,\n    makeImportPatch(androidConfig.packageImportPath)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/commandStub.js",
    "content": "module.exports = (cb) => cb();"
  },
  {
    "path": "local-cli/link/getDependencyConfig.js",
    "content": "/**\n * Given an array of dependencies - it returns their RNPM config\n * if they were valid.\n */\nmodule.exports = function getDependencyConfig(config, deps, root) {\n  return deps.reduce((acc, name) => {\n    try {\n      return acc.concat({\n        config: config.getDependencyConfig(name, root),\n        name,\n      });\n    } catch (err) {\n      console.log(err);\n      return acc;\n    }\n  }, []);\n};\n"
  },
  {
    "path": "local-cli/link/getProjectDependencies.js",
    "content": "const path = require('path');\n\n/**\n * Returns an array of dependencies that should be linked/checked.\n */\nmodule.exports = function getProjectDependencies() {\n  const pjson = require(path.join(process.cwd(), './package.json'));\n  return Object.keys(pjson.dependencies || {}).filter(name => name !== 'react-native');\n};\n"
  },
  {
    "path": "local-cli/link/groupFilesByType.js",
    "content": "const groupBy = require('lodash').groupBy;\nconst mime = require('mime');\n\n/**\n * Since there are no officially registered MIME types\n * for ttf/otf yet http://www.iana.org/assignments/media-types/media-types.xhtml,\n * we define two non-standard ones for the sake of parsing\n */\nmime.define({\n  'font/opentype': ['otf'],\n  'font/truetype': ['ttf'],\n});\n\n/**\n * Given an array of files, it groups it by it's type.\n * Type of the file is inferred from it's mimetype based on the extension\n * file ends up with. The returned value is an object with properties that\n * correspond to the first part of the mimetype, e.g. images will be grouped\n * under `image` key since the mimetype for them is `image/jpg` etc.\n *\n * Example:\n * Given an array ['fonts/a.ttf', 'images/b.jpg'],\n * the returned object will be: {font: ['fonts/a.ttf'], image: ['images/b.jpg']}\n */\nmodule.exports = function groupFilesByType(assets) {\n  return groupBy(assets, type => mime.lookup(type).split('/')[0]);\n};\n"
  },
  {
    "path": "local-cli/link/ios/addFileToProject.js",
    "content": "const PbxFile = require('xcode/lib/pbxFile');\n\n/**\n * Given xcodeproj and filePath, it creates new file\n * from path provided, adds it to the project\n * and returns newly created instance of a file\n */\nmodule.exports = function addFileToProject(project, filePath) {\n  const file = new PbxFile(filePath);\n  file.uuid = project.generateUuid();\n  file.fileRef = project.generateUuid();\n  project.addToPbxFileReferenceSection(file);\n  return file;\n};\n"
  },
  {
    "path": "local-cli/link/ios/addProjectToLibraries.js",
    "content": "/**\n * Given an array of xcodeproj libraries and pbxFile,\n * it appends it to that group\n *\n * Important: That function mutates `libraries` and it's not pure.\n * It's mainly due to limitations of `xcode` library.\n */\nmodule.exports = function addProjectToLibraries(libraries, file) {\n  return libraries.children.push({\n    value: file.fileRef,\n    comment: file.basename,\n  });\n};\n"
  },
  {
    "path": "local-cli/link/ios/addSharedLibraries.js",
    "content": "const createGroupWithMessage = require('./createGroupWithMessage');\n\nmodule.exports = function addSharedLibraries(project, libraries) {\n  if (!libraries.length) {\n    return;\n  }\n\n  // Create a Frameworks group if necessary.\n  createGroupWithMessage(project, 'Frameworks');\n\n  const target = project.getFirstTarget().uuid;\n\n  for (var name of libraries) {\n    project.addFramework(name, { target });\n  }\n};\n"
  },
  {
    "path": "local-cli/link/ios/addToHeaderSearchPaths.js",
    "content": "const mapHeaderSearchPaths = require('./mapHeaderSearchPaths');\n\nmodule.exports = function addToHeaderSearchPaths(project, path) {\n  mapHeaderSearchPaths(project, searchPaths => searchPaths.concat(path));\n};\n"
  },
  {
    "path": "local-cli/link/ios/copyAssets.js",
    "content": "const fs = require('fs-extra');\nconst path = require('path');\nconst xcode = require('xcode');\nconst log = require('npmlog');\nconst plistParser = require('plist');\nconst groupFilesByType = require('../groupFilesByType');\nconst createGroupWithMessage = require('./createGroupWithMessage');\nconst getPlist = require('./getPlist');\nconst getPlistPath = require('./getPlistPath');\n\n/**\n * This function works in a similar manner to its Android version,\n * except it does not copy fonts but creates XCode Group references\n */\nmodule.exports = function linkAssetsIOS(files, projectConfig) {\n  const project = xcode.project(projectConfig.pbxprojPath).parseSync();\n  const assets = groupFilesByType(files);\n  const plist = getPlist(project, projectConfig.sourceDir);\n\n  createGroupWithMessage(project, 'Resources');\n\n  const fonts = (assets.font || [])\n    .map(asset =>\n      project.addResourceFile(\n        path.relative(projectConfig.sourceDir, asset),\n        { target: project.getFirstTarget().uuid }\n      )\n    )\n    .filter(file => file)   // xcode returns false if file is already there\n    .map(file => file.basename);\n\n  plist.UIAppFonts = (plist.UIAppFonts || []).concat(fonts);\n\n  fs.writeFileSync(\n    projectConfig.pbxprojPath,\n    project.writeSync()\n  );\n\n  fs.writeFileSync(\n    getPlistPath(project, projectConfig.sourceDir),\n    plistParser.build(plist)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/createGroup.js",
    "content": "const getGroup = require('./getGroup');\n\nconst hasGroup = (pbxGroup, name) => pbxGroup.children.find(group => group.comment === name);\n\n/**\n * Given project and path of the group, it deeply creates a given group\n * making all outer groups if neccessary\n *\n * Returns newly created group\n */\nmodule.exports = function createGroup(project, path) {\n  return path.split('/').reduce(\n    (group, name) => {\n      if (!hasGroup(group, name)) {\n        const uuid = project.pbxCreateGroup(name, '\"\"');\n\n        group.children.push({\n          value: uuid,\n          comment: name,\n        });\n      }\n\n      return project.pbxGroupByName(name);\n    },\n    getGroup(project)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/createGroupWithMessage.js",
    "content": "const log = require('npmlog');\n\nconst createGroup = require('./createGroup');\nconst getGroup = require('./getGroup');\n\n/**\n * Given project and path of the group, it checks if a group exists at that path,\n * and deeply creates a group for that path if its does not already exist.\n *\n * Returns the existing or newly created group\n */\nmodule.exports = function createGroupWithMessage(project, path) {\n  var group = getGroup(project, path);\n\n  if (!group) {\n    group = createGroup(project, path);\n\n    log.warn(\n      'ERRGROUP',\n      `Group '${path}' does not exist in your XCode project. We have created it automatically for you.`\n    );\n  }\n\n  return group;\n};\n"
  },
  {
    "path": "local-cli/link/ios/getBuildProperty.js",
    "content": "/**\n * Gets build property from the main target build section\n *\n * It differs from the project.getBuildProperty exposed by xcode in the way that:\n * - it only checks for build property in the main target `Debug` section\n * - `xcode` library iterates over all build sections and because it misses\n * an early return when property is found, it will return undefined/wrong value\n * when there's another build section typically after the one you want to access\n * without the property defined (e.g. CocoaPods sections appended to project\n * miss INFOPLIST_FILE), see: https://github.com/alunny/node-xcode/blob/master/lib/pbxProject.js#L1765\n */\nmodule.exports = function getBuildProperty(project, prop) {\n  const target = project.getFirstTarget().firstTarget;\n  const config = project.pbxXCConfigurationList()[target.buildConfigurationList];\n  const buildSection = project.pbxXCBuildConfigurationSection()[config.buildConfigurations[0].value];\n\n  return buildSection.buildSettings[prop];\n};\n"
  },
  {
    "path": "local-cli/link/ios/getGroup.js",
    "content": "const getFirstProject = (project) => project.getFirstProject().firstProject;\n\nconst findGroup = (group, name) => group.children.find(group => group.comment === name);\n\n/**\n * Returns group from .xcodeproj if one exists, null otherwise\n *\n * Unlike node-xcode `pbxGroupByName` - it does not return `first-matching`\n * group if multiple groups with the same name exist\n *\n * If path is not provided, it returns top-level group\n */\nmodule.exports = function getGroup(project, path) {\n  const firstProject = getFirstProject(project);\n\n  var group = project.getPBXGroupByKey(firstProject.mainGroup);\n\n  if (!path) {\n    return group;\n  }\n\n  for (var name of path.split('/')) {\n    var foundGroup = findGroup(group, name);\n\n    if (foundGroup) {\n      group = project.getPBXGroupByKey(foundGroup.value);\n    } else {\n      group = null;\n      break;\n    }\n  }\n\n  return group;\n};\n"
  },
  {
    "path": "local-cli/link/ios/getHeaderSearchPath.js",
    "content": "const path = require('path');\nconst union = require('lodash').union;\nconst last = require('lodash').last;\n\n/**\n * Given an array of directories, it returns the one that contains\n * all the other directories in a given array inside it.\n *\n * Example:\n * Given an array of directories: ['/Users/Kureev/a', '/Users/Kureev/b']\n * the returned folder is `/Users/Kureev`\n *\n * Check `getHeaderSearchPath.spec.js` for more use-cases.\n */\nconst getOuterDirectory = (directories) =>\n  directories.reduce((topDir, currentDir) => {\n    const currentFolders = currentDir.split(path.sep);\n    const topMostFolders = topDir.split(path.sep);\n\n    if (currentFolders.length === topMostFolders.length\n      && last(currentFolders) !== last(topMostFolders)) {\n      return currentFolders.slice(0, -1).join(path.sep);\n    }\n\n    return currentFolders.length < topMostFolders.length\n      ? currentDir\n      : topDir;\n  });\n\n/**\n * Given an array of headers it returns search path so Xcode can resolve\n * headers when referenced like below:\n * ```\n * #import \"CodePush.h\"\n * ```\n * If all files are located in one directory (directories.length === 1),\n * we simply return a relative path to that location.\n *\n * Otherwise, we loop through them all to find the outer one that contains\n * all the headers inside. That location is then returned with /** appended at\n * the end so Xcode marks that location as `recursive` and will look inside\n * every folder of it to locate correct headers.\n */\nmodule.exports = function getHeaderSearchPath(sourceDir, headers) {\n  const directories = union(\n    headers.map(path.dirname)\n  );\n\n  return directories.length === 1\n    ? `\"$(SRCROOT)${path.sep}${path.relative(sourceDir, directories[0])}\"`\n    : `\"$(SRCROOT)${path.sep}${path.relative(sourceDir, getOuterDirectory(directories))}/**\"`;\n};\n"
  },
  {
    "path": "local-cli/link/ios/getHeadersInFolder.js",
    "content": "const glob = require('glob');\nconst path = require('path');\n\nconst GLOB_EXCLUDE_PATTERN = ['node_modules/**', 'Pods/**', 'Examples/**', 'examples/**'];\n\n/**\n * Given folder, it returns an array of all header files\n * inside it, ignoring node_modules and examples\n */\nmodule.exports = function getHeadersInFolder(folder) {\n  return glob\n    .sync('**/*.h', {\n      cwd: folder,\n      nodir: true,\n      ignore: GLOB_EXCLUDE_PATTERN,\n    })\n    .map(file => path.join(folder, file));\n};\n"
  },
  {
    "path": "local-cli/link/ios/getPlist.js",
    "content": "const plistParser = require('plist');\nconst getPlistPath = require('./getPlistPath');\nconst fs = require('fs');\n\n/**\n * Returns Info.plist located in the iOS project\n *\n * Returns `null` if INFOPLIST_FILE is not specified.\n */\nmodule.exports = function getPlist(project, sourceDir) {\n  const plistPath = getPlistPath(project, sourceDir);\n\n  if (!plistPath || !fs.existsSync(plistPath)) {\n    return null;\n  }\n\n  return plistParser.parse(\n    fs.readFileSync(plistPath, 'utf-8')\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/getPlistPath.js",
    "content": "const path = require('path');\nconst getBuildProperty = require('./getBuildProperty');\n\nmodule.exports = function getPlistPath(project, sourceDir) {\n  const plistFile = getBuildProperty(project, 'INFOPLIST_FILE');\n\n  if (!plistFile) {\n    return null;\n  }\n\n  return path.join(\n    sourceDir,\n    plistFile.replace(/\"/g, '').replace('$(SRCROOT)', '')\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/getProducts.js",
    "content": "/**\n * Given xcodeproj it returns list of products ending with\n * .a extension, so that we know what elements add to target\n * project static library\n */\nmodule.exports = function getProducts(project) {\n  return project\n    .pbxGroupByName('Products')\n    .children\n    .map(c => c.comment)\n    .filter(c => c.indexOf('.a') > -1);\n};\n"
  },
  {
    "path": "local-cli/link/ios/hasLibraryImported.js",
    "content": "/**\n * Given an array of libraries already imported and packageName that will be\n * added, returns true or false depending on whether the library is already linked\n * or not\n */\nmodule.exports = function hasLibraryImported(libraries, packageName) {\n  return libraries.children\n    .filter(library => library.comment === packageName)\n    .length > 0;\n};\n"
  },
  {
    "path": "local-cli/link/ios/isInstalled.js",
    "content": "const xcode = require('xcode');\nconst getGroup = require('./getGroup');\nconst hasLibraryImported = require('./hasLibraryImported');\n\n/**\n * Returns true if `xcodeproj` specified by dependencyConfig is present\n * in a top level `libraryFolder`\n */\nmodule.exports = function isInstalled(projectConfig, dependencyConfig) {\n  const project = xcode.project(projectConfig.pbxprojPath).parseSync();\n  const libraries = getGroup(project, projectConfig.libraryFolder);\n\n  if (!libraries) {\n    return false;\n  }\n\n  return hasLibraryImported(libraries, dependencyConfig.projectName);\n};\n"
  },
  {
    "path": "local-cli/link/ios/mapHeaderSearchPaths.js",
    "content": "/**\n * Given Xcode project and path, iterate over all build configurations\n * and execute func with HEADER_SEARCH_PATHS from current section\n *\n * We cannot use builtin addToHeaderSearchPaths method since react-native init does not\n * use $(TARGET_NAME) for PRODUCT_NAME, but sets it manually so that method will skip\n * that target.\n *\n * To workaround that issue and make it more bullet-proof for different names,\n * we iterate over all configurations and look if React is already there. If it is,\n * we assume we want to modify that section either\n *\n * Important: That function mutates `buildSettings` and it's not pure thus you should\n * not rely on its return value\n */\nmodule.exports = function headerSearchPathIter(project, func) {\n  const config = project.pbxXCBuildConfigurationSection();\n\n  Object\n    .keys(config)\n    .filter(ref => ref.indexOf('_comment') === -1)\n    .forEach(ref => {\n      const buildSettings = config[ref].buildSettings;\n      const shouldVisitBuildSettings = (\n          Array.isArray(buildSettings.HEADER_SEARCH_PATHS) ?\n            buildSettings.HEADER_SEARCH_PATHS :\n            []\n        )\n        .filter(path => path.indexOf('react-native/React/**'))\n        .length > 0;\n\n      if (shouldVisitBuildSettings) {\n        buildSettings.HEADER_SEARCH_PATHS = func(buildSettings.HEADER_SEARCH_PATHS);\n      }\n    });\n};\n"
  },
  {
    "path": "local-cli/link/ios/registerNativeModule.js",
    "content": "const xcode = require('xcode');\nconst fs = require('fs');\nconst path = require('path');\nconst log = require('npmlog');\n\nconst addToHeaderSearchPaths = require('./addToHeaderSearchPaths');\nconst getHeadersInFolder = require('./getHeadersInFolder');\nconst getHeaderSearchPath = require('./getHeaderSearchPath');\nconst getProducts = require('./getProducts');\nconst createGroupWithMessage = require('./createGroupWithMessage');\nconst addFileToProject = require('./addFileToProject');\nconst addProjectToLibraries = require('./addProjectToLibraries');\nconst addSharedLibraries = require('./addSharedLibraries');\nconst isEmpty = require('lodash').isEmpty;\nconst getGroup = require('./getGroup');\n\n/**\n * Register native module IOS adds given dependency to project by adding\n * its xcodeproj to project libraries as well as attaching static library\n * to the first target (the main one)\n *\n * If library is already linked, this action is a no-op.\n */\nmodule.exports = function registerNativeModuleIOS(dependencyConfig, projectConfig) {\n  const project = xcode.project(projectConfig.pbxprojPath).parseSync();\n  const dependencyProject = xcode.project(dependencyConfig.pbxprojPath).parseSync();\n\n  const libraries = createGroupWithMessage(project, projectConfig.libraryFolder);\n  const file = addFileToProject(\n    project,\n    path.relative(projectConfig.sourceDir, dependencyConfig.projectPath)\n  );\n\n  addProjectToLibraries(libraries, file);\n\n  getProducts(dependencyProject).forEach(product => {\n    project.addStaticLibrary(product, {\n      target: project.getFirstTarget().uuid,\n    });\n  });\n\n  addSharedLibraries(project, dependencyConfig.sharedLibraries);\n\n  const headers = getHeadersInFolder(dependencyConfig.folder);\n  if (!isEmpty(headers)) {\n    addToHeaderSearchPaths(\n      project,\n      getHeaderSearchPath(projectConfig.sourceDir, headers)\n    );\n  }\n\n  fs.writeFileSync(\n    projectConfig.pbxprojPath,\n    project.writeSync()\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeFromHeaderSearchPaths.js",
    "content": "const mapHeaderSearchPaths = require('./mapHeaderSearchPaths');\n\n/**\n * Given Xcode project and absolute path, it makes sure there are no headers referring to it\n */\nmodule.exports = function addToHeaderSearchPaths(project, path) {\n  mapHeaderSearchPaths(project,\n    searchPaths => searchPaths.filter(searchPath => searchPath !== path)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeFromPbxItemContainerProxySection.js",
    "content": "/**\n * For all files that are created and referenced from another `.xcodeproj` -\n * a new PBXItemContainerProxy is created that contains `containerPortal` value\n * which equals to xcodeproj file.uuid from PBXFileReference section.\n */\nmodule.exports = function removeFromPbxItemContainerProxySection(project, file) {\n  const section = project.hash.project.objects.PBXContainerItemProxy;\n\n  for (var key of Object.keys(section)) {\n    if (section[key].containerPortal === file.uuid) {\n      delete section[key];\n    }\n  }\n\n  return;\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeFromPbxReferenceProxySection.js",
    "content": "/**\n * Every file added to the project from another project is attached to\n * `PBXItemContainerProxy` through `PBXReferenceProxy`.\n */\nmodule.exports = function removeFromPbxReferenceProxySection(project, file) {\n  const section = project.hash.project.objects.PBXReferenceProxy;\n\n  for (var key of Object.keys(section)) {\n    if (section[key].path === file.basename) {\n      delete section[key];\n    }\n  }\n\n  return;\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeFromProjectReferences.js",
    "content": "/**\n * For each file (.xcodeproj), there's an entry in `projectReferences` created\n * that has two entries - `ProjectRef` - reference to a file.uuid and\n * `ProductGroup` - uuid of a Products group.\n *\n * When projectReference is found - it's deleted and the removed value is returned\n * so that ProductGroup in PBXGroup section can be removed as well.\n *\n * Otherwise returns null\n */\nmodule.exports = function removeFromProjectReferences(project, file) {\n  const firstProject = project.getFirstProject().firstProject;\n\n  const projectRef = firstProject.projectReferences.find(item => item.ProjectRef === file.uuid);\n\n  if (!projectRef) {\n    return null;\n  }\n\n  firstProject.projectReferences.splice(\n    firstProject.projectReferences.indexOf(projectRef),\n    1\n  );\n\n  return projectRef;\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeFromStaticLibraries.js",
    "content": "const PbxFile = require('xcode/lib/pbxFile');\nconst removeFromPbxReferenceProxySection = require('./removeFromPbxReferenceProxySection');\n\n/**\n * Removes file from static libraries\n *\n * Similar to `node-xcode` addStaticLibrary\n */\nmodule.exports = function removeFromStaticLibraries(project, path, opts) {\n  const file = new PbxFile(path);\n\n  file.target = opts ? opts.target : undefined;\n\n  project.removeFromPbxFileReferenceSection(file);\n  project.removeFromPbxBuildFileSection(file);\n  project.removeFromPbxFrameworksBuildPhase(file);\n  project.removeFromLibrarySearchPaths(file);\n  removeFromPbxReferenceProxySection(project, file);\n\n  return file;\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeProductGroup.js",
    "content": "module.exports = function removeProductGroup(project, productGroupId) {\n  const section = project.hash.project.objects.PBXGroup;\n\n  for (var key of Object.keys(section)) {\n    if (key === productGroupId) {\n      delete section[key];\n    }\n  }\n\n  return;\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeProjectFromLibraries.js",
    "content": "/**\n * Given an array of xcodeproj libraries and pbxFile,\n * it removes it from that group by comparing basenames\n *\n * Important: That function mutates `libraries` and it's not pure.\n * It's mainly due to limitations of `xcode` library.\n */\nmodule.exports = function removeProjectFromLibraries(libraries, file) {\n  libraries.children = libraries.children.filter(library =>\n    library.comment !== file.basename\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeProjectFromProject.js",
    "content": "const PbxFile = require('xcode/lib/pbxFile');\nconst removeFromPbxItemContainerProxySection = require('./removeFromPbxItemContainerProxySection');\nconst removeFromProjectReferences = require('./removeFromProjectReferences');\nconst removeProductGroup = require('./removeProductGroup');\n\n/**\n * Given xcodeproj and filePath, it creates new file\n * from path provided and removes it. That operation is required since\n * underlying method requires PbxFile instance to be passed (it does not\n * have to have uuid or fileRef defined since it will do equality check\n * by path)\n *\n * Returns removed file (that one will have UUID)\n */\nmodule.exports = function removeProjectFromProject(project, filePath) {\n  const file = project.removeFromPbxFileReferenceSection(new PbxFile(filePath));\n  const projectRef = removeFromProjectReferences(project, file);\n\n  if (projectRef) {\n    removeProductGroup(project, projectRef.ProductGroup);\n  }\n\n  removeFromPbxItemContainerProxySection(project, file);\n\n  return file;\n};\n"
  },
  {
    "path": "local-cli/link/ios/removeSharedLibraries.js",
    "content": "module.exports = function removeSharedLibraries(project, libraries) {\n  if (!libraries.length) {\n    return;\n  }\n\n  const target = project.getFirstTarget().uuid;\n\n  for (var name of libraries) {\n    project.removeFramework(name, { target });\n  }\n};\n"
  },
  {
    "path": "local-cli/link/ios/unlinkAssets.js",
    "content": "const fs = require('fs-extra');\nconst path = require('path');\nconst xcode = require('xcode');\nconst log = require('npmlog');\nconst plistParser = require('plist');\nconst groupFilesByType = require('../groupFilesByType');\nconst getPlist = require('./getPlist');\nconst getPlistPath = require('./getPlistPath');\nconst difference = require('lodash').difference;\n\n/**\n * Unlinks assets from iOS project. Removes references for fonts from `Info.plist`\n * fonts provided by application and from `Resources` group\n */\nmodule.exports = function unlinkAssetsIOS(files, projectConfig) {\n  const project = xcode.project(projectConfig.pbxprojPath).parseSync();\n  const assets = groupFilesByType(files);\n  const plist = getPlist(project, projectConfig.sourceDir);\n\n  if (!plist) {\n    return log.error(\n      'ERRPLIST',\n      `Could not locate Info.plist file. Check if your project has 'INFOPLIST_FILE' set properly`\n    );\n  }\n\n  if (!project.pbxGroupByName('Resources')) {\n    return log.error(\n      'ERRGROUP',\n      `Group 'Resources' does not exist in your XCode project. There is nothing to unlink.`\n    );\n  }\n\n  const fonts = (assets.font || [])\n    .map(asset =>\n      project.removeResourceFile(\n        path.relative(projectConfig.sourceDir, asset),\n        { target: project.getFirstTarget().uuid }\n      )\n    )\n    .map(file => file.basename);\n\n  plist.UIAppFonts = difference(plist.UIAppFonts || [], fonts);\n\n  fs.writeFileSync(\n    projectConfig.pbxprojPath,\n    project.writeSync()\n  );\n\n  fs.writeFileSync(\n    getPlistPath(project, projectConfig.sourceDir),\n    plistParser.build(plist)\n  );\n};\n"
  },
  {
    "path": "local-cli/link/ios/unregisterNativeModule.js",
    "content": "const xcode = require('xcode');\nconst path = require('path');\nconst fs = require('fs');\nconst difference = require('lodash').difference;\nconst isEmpty = require('lodash').isEmpty;\n\nconst getGroup = require('./getGroup');\nconst getProducts = require('./getProducts');\nconst getHeadersInFolder = require('./getHeadersInFolder');\nconst getHeaderSearchPath = require('./getHeaderSearchPath');\nconst removeProjectFromProject = require('./removeProjectFromProject');\nconst removeProjectFromLibraries = require('./removeProjectFromLibraries');\nconst removeFromStaticLibraries = require('./removeFromStaticLibraries');\nconst removeFromHeaderSearchPaths = require('./removeFromHeaderSearchPaths');\nconst removeSharedLibraries = require('./removeSharedLibraries');\n\n/**\n * Unregister native module IOS\n *\n * If library is already unlinked, this action is a no-op.\n */\nmodule.exports = function unregisterNativeModule(dependencyConfig, projectConfig, iOSDependencies) {\n  const project = xcode.project(projectConfig.pbxprojPath).parseSync();\n  const dependencyProject = xcode.project(dependencyConfig.pbxprojPath).parseSync();\n\n  const libraries = getGroup(project, projectConfig.libraryFolder);\n\n  const file = removeProjectFromProject(\n    project,\n    path.relative(projectConfig.sourceDir, dependencyConfig.projectPath)\n  );\n\n  removeProjectFromLibraries(libraries, file);\n\n  getProducts(dependencyProject).forEach(product => {\n    removeFromStaticLibraries(project, product, {\n      target: project.getFirstTarget().uuid,\n    });\n  });\n\n  const sharedLibraries = difference(\n    dependencyConfig.sharedLibraries,\n    iOSDependencies.reduce(\n      (libs, dependency) => libs.concat(dependency.sharedLibraries),\n      projectConfig.sharedLibraries\n    )\n  );\n\n  removeSharedLibraries(project, sharedLibraries);\n\n  const headers = getHeadersInFolder(dependencyConfig.folder);\n  if (!isEmpty(headers)) {\n    removeFromHeaderSearchPaths(\n      project,\n      getHeaderSearchPath(projectConfig.sourceDir, headers)\n    );\n  }\n\n  fs.writeFileSync(\n    projectConfig.pbxprojPath,\n    project.writeSync()\n  );\n};\n"
  },
  {
    "path": "local-cli/link/link.js",
    "content": "/**\n * Copyright (c) 2013-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nconst log = require('npmlog');\nconst path = require('path');\nconst uniq = require('lodash').uniq;\nconst flatten = require('lodash').flatten;\nconst chalk = require('chalk');\n\nconst isEmpty = require('lodash').isEmpty;\nconst promiseWaterfall = require('./promiseWaterfall');\nconst registerDependencyAndroid = require('./android/registerNativeModule');\nconst registerDependencyIOS = require('./ios/registerNativeModule');\nconst isInstalledAndroid = require('./android/isInstalled');\nconst isInstalledIOS = require('./ios/isInstalled');\nconst copyAssetsAndroid = require('./android/copyAssets');\nconst copyAssetsIOS = require('./ios/copyAssets');\nconst getProjectDependencies = require('./getProjectDependencies');\nconst getDependencyConfig = require('./getDependencyConfig');\nconst pollParams = require('./pollParams');\nconst commandStub = require('./commandStub');\nconst promisify = require('./promisify');\n\nlog.heading = 'rnpm-link';\n\nconst dedupeAssets = (assets) => uniq(assets, asset => path.basename(asset));\n\n\nconst linkDependencyAndroid = (androidProject, dependency) => {\n  if (!androidProject || !dependency.config.android) {\n    return null;\n  }\n\n  const isInstalled = isInstalledAndroid(androidProject, dependency.name);\n\n  if (isInstalled) {\n    log.info(chalk.grey(`Android module ${dependency.name} is already linked`));\n    return null;\n  }\n\n  return pollParams(dependency.config.params).then(params => {\n    log.info(`Linking ${dependency.name} android dependency`);\n\n    registerDependencyAndroid(\n      dependency.name,\n      dependency.config.android,\n      params,\n      androidProject\n    );\n\n    log.info(`Android module ${dependency.name} has been successfully linked`);\n  });\n};\n\nconst linkDependencyIOS = (iOSProject, dependency) => {\n  if (!iOSProject || !dependency.config.ios) {\n    return;\n  }\n\n  const isInstalled = isInstalledIOS(iOSProject, dependency.config.ios);\n\n  if (isInstalled) {\n    log.info(chalk.grey(`iOS module ${dependency.name} is already linked`));\n    return;\n  }\n\n  log.info(`Linking ${dependency.name} ios dependency`);\n\n  registerDependencyIOS(dependency.config.ios, iOSProject);\n\n  log.info(`iOS module ${dependency.name} has been successfully linked`);\n};\n\nconst linkAssets = (project, assets) => {\n  if (isEmpty(assets)) {\n    return;\n  }\n\n  if (project.ios) {\n    log.info('Linking assets to ios project');\n    copyAssetsIOS(assets, project.ios);\n  }\n\n  if (project.android) {\n    log.info('Linking assets to android project');\n    copyAssetsAndroid(assets, project.android.assetsPath);\n  }\n\n  log.info('Assets have been successfully linked to your project');\n};\n\n/**\n * Updates project and linkes all dependencies to it\n *\n * If optional argument [packageName] is provided, it's the only one that's checked\n */\n\nconst testLinkArt = () => {\n  const iOSProject = {\n    sourceDir: '/Users/olda/test2/ios',\n    folder: '/Users/olda/test2',\n    pbxprojPath: '/Users/olda/test2/ios/test2.xcodeproj/project.pbxproj',\n    projectPath: '/Users/olda/test2/ios/test2.xcodeproj',\n    projectName: 'test2.xcodeproj',\n    libraryFolder: 'Libraries',\n    sharedLibraries: [],\n    plist: []\n  };\n\n  const startPath = '/Users/olda/test2/node_modules/react-native/Libraries/ART';\n  const artProject = {\n    sourceDir: startPath,\n    folder: startPath,\n    pbxprojPath: startPath + '/ART.xcodeproj' + '/project.pbxproj',\n    projectPath: startPath + '/ART.xcodeproj',\n    projectName: 'ART.xcodeproj',\n    libraryFolder: 'Libraries',\n    sharedLibraries: [],\n    plist: []\n  };\n\n\n  console.log(iOSProject);\n\n  const isInstalled = isInstalledIOS(iOSProject, artProject);\n\n  if (isInstalled) {\n    log.info(chalk.grey(`iOS module art is already linked`));\n    return;\n  }\n\n  log.info(`Linking art ios dependency`);\n\n  registerDependencyIOS(artProject, iOSProject);\n\n  log.info(`iOS module art has been successfully linked`);\n}\n\nfunction link(args, config) {\n  //testLinkArt();\n  var project;\n  try {\n    project = config.getProjectConfig(path.join(process.cwd(), '../../'));\n    console.log(project.ios);\n\n  } catch (err) {\n    log.error(\n      'ERRPACKAGEJSON',\n      'No package found. Are you sure it\\'s a React Native project?'\n    );\n    return Promise.reject(err);\n  }\n\n  const packageName = args[0];\n  const dependencies = getDependencyConfig(\n    config,\n    packageName ? [packageName] : getProjectDependencies(),\n    path.join(process.cwd(), '../../')\n  );\n\n  const assets = dedupeAssets(dependencies.reduce(\n    (assets, dependency) => assets.concat(dependency.config.assets),\n    project.assets\n  ));\n\n  const tasks = flatten(dependencies.map(dependency => [\n    () => promisify(dependency.config.commands.prelink || commandStub),\n    () => linkDependencyAndroid(project.android, dependency),\n    () => linkDependencyIOS(project.ios, dependency),\n    () => promisify(dependency.config.commands.postlink || commandStub),\n  ]));\n\n  tasks.push(() => linkAssets(project, assets));\n\n  return promiseWaterfall(tasks).catch(err => {\n    log.error(\n      `It seems something went wrong while linking. Error: ${err.message} \\n`\n      + 'Please file an issue here: https://github.com/facebook/react-native/issues'\n    );\n    throw err;\n  });\n}\n\nmodule.exports = {\n  func: link,\n  description: 'links all native dependencies',\n  name: 'link [packageName]',\n  linkDependencyIOS : linkDependencyIOS\n};\n"
  },
  {
    "path": "local-cli/link/pollParams.js",
    "content": "var inquirer = require('inquirer');\n\nmodule.exports = (questions) => new Promise((resolve, reject) => {\n  if (!questions) {\n    return resolve({});\n  }\n\n  inquirer.prompt(questions, resolve);\n});\n"
  },
  {
    "path": "local-cli/link/promiseWaterfall.js",
    "content": "/**\n * Given an array of promise creators, executes them in a sequence.\n *\n * If any of the promises in the chain fails, all subsequent promises\n * will be skipped\n *\n * Returns the value last promise from a sequence resolved\n */\nmodule.exports = function promiseWaterfall(tasks) {\n  return tasks.reduce(\n    (prevTaskPromise, task) => prevTaskPromise.then(task),\n    Promise.resolve()\n  );\n};\n"
  },
  {
    "path": "local-cli/link/promisify.js",
    "content": "module.exports = (func) => new Promise((resolve, reject) =>\n  func((err, res) => err ? reject(err) : resolve(res))\n);"
  },
  {
    "path": "local-cli/link/unlink.js",
    "content": "const log = require('npmlog');\n\nconst getProjectDependencies = require('./getProjectDependencies');\nconst unregisterDependencyAndroid = require('./android/unregisterNativeModule');\nconst unregisterDependencyIOS = require('./ios/unregisterNativeModule');\nconst isInstalledAndroid = require('./android/isInstalled');\nconst isInstalledIOS = require('./ios/isInstalled');\nconst unlinkAssetsAndroid = require('./android/unlinkAssets');\nconst unlinkAssetsIOS = require('./ios/unlinkAssets');\nconst getDependencyConfig = require('./getDependencyConfig');\nconst compact = require('lodash').compact;\nconst difference = require('lodash').difference;\nconst filter = require('lodash').filter;\nconst find = require('lodash').find;\nconst flatten = require('lodash').flatten;\nconst isEmpty = require('lodash').isEmpty;\nconst promiseWaterfall = require('./promiseWaterfall');\nconst commandStub = require('./commandStub');\nconst promisify = require('./promisify');\n\nlog.heading = 'rnpm-link';\n\nconst unlinkDependencyAndroid = (androidProject, dependency, packageName) => {\n  if (!androidProject || !dependency.android) {\n    return;\n  }\n\n  const isInstalled = isInstalledAndroid(androidProject, packageName);\n\n  if (!isInstalled) {\n    log.info(`Android module ${packageName} is not installed`);\n    return;\n  }\n\n  log.info(`Unlinking ${packageName} android dependency`);\n\n  unregisterDependencyAndroid(packageName, dependency.android, androidProject);\n\n  log.info(`Android module ${packageName} has been successfully unlinked`);\n};\n\nconst unlinkDependencyIOS = (iOSProject, dependency, packageName, iOSDependencies) => {\n  if (!iOSProject || !dependency.ios) {\n    return;\n  }\n\n  const isInstalled = isInstalledIOS(iOSProject, dependency.ios);\n\n  if (!isInstalled) {\n    log.info(`iOS module ${packageName} is not installed`);\n    return;\n  }\n\n  log.info(`Unlinking ${packageName} ios dependency`);\n\n  unregisterDependencyIOS(dependency.ios, iOSProject, iOSDependencies);\n\n  log.info(`iOS module ${packageName} has been successfully unlinked`);\n};\n\n/**\n * Updates project and unlink specific dependency\n *\n * If optional argument [packageName] is provided, it's the only one\n * that's checked\n */\nfunction unlink(args, config) {\n  const packageName = args[0];\n\n  var project;\n  var dependency;\n\n  try {\n    project = config.getProjectConfig();\n  } catch (err) {\n    log.error(\n      'ERRPACKAGEJSON',\n      'No package found. Are you sure it\\'s a React Native project?'\n    );\n    return Promise.reject(err);\n  }\n\n  try {\n    dependency = config.getDependencyConfig(packageName);\n  } catch (err) {\n    log.warn(\n      'ERRINVALIDPROJ',\n      `Project ${packageName} is not a react-native library`\n    );\n    return Promise.reject(err);\n  }\n\n  const allDependencies = getDependencyConfig(config, getProjectDependencies());\n  const otherDependencies = filter(allDependencies, d => d.name !== packageName);\n  const thisDependency = find(allDependencies, d => d.name === packageName);\n  const iOSDependencies = compact(otherDependencies.map(d => d.config.ios));\n\n  const tasks = [\n    () => promisify(thisDependency.config.commands.preunlink || commandStub),\n    () => unlinkDependencyAndroid(project.android, dependency, packageName),\n    () => unlinkDependencyIOS(project.ios, dependency, packageName, iOSDependencies),\n    () => promisify(thisDependency.config.commands.postunlink || commandStub)\n  ];\n\n  return promiseWaterfall(tasks)\n    .then(() => {\n      const assets = difference(\n        dependency.assets,\n        flatten(allDependencies, d => d.assets)\n      );\n\n      if (isEmpty(assets)) {\n        return Promise.resolve();\n      }\n\n      if (project.ios) {\n        log.info('Unlinking assets from ios project');\n        unlinkAssetsIOS(assets, project.ios);\n      }\n\n      if (project.android) {\n        log.info('Unlinking assets from android project');\n        unlinkAssetsAndroid(assets, project.android.assetsPath);\n      }\n\n      log.info(\n        `${packageName} assets has been successfully unlinked from your project`\n      );\n    })\n    .catch(err => {\n      log.error(\n        `It seems something went wrong while unlinking. Error: ${err.message}`\n      );\n      throw err;\n    });\n};\n\nmodule.exports = {\n  func: unlink,\n  description: 'unlink native dependency',\n  name: 'unlink <packageName>',\n};\n"
  },
  {
    "path": "local-cli/logAndroid/logAndroid.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst chalk = require('chalk');\nconst child_process = require('child_process');\nconst Promise = require('promise');\n\n/**\n * Starts adb logcat\n */\nfunction logAndroid() {\n  return new Promise((resolve, reject) => {\n    _logAndroid(resolve, reject);\n  });\n}\n\nfunction _logAndroid() {\n  try {\n    const adbPath = process.env.ANDROID_HOME\n      ? process.env.ANDROID_HOME + '/platform-tools/adb'\n      : 'adb';\n\n    const adbArgs = ['logcat', '*:S', 'ReactNative:V', 'ReactNativeJS:V'];\n\n    console.log(chalk.bold(\n      `Starting the logger (${adbPath} ${adbArgs.join(' ')})...`\n    ));\n\n    const log = child_process.spawnSync(adbPath, adbArgs, {stdio: 'inherit'});\n\n    if (log.error !== null) {\n      throw log.error;\n    }\n\n  } catch (e) {\n    console.log(chalk.red(\n      'adb invocation failed. Do you have adb in your PATH?'\n    ));\n    return Promise.reject();\n  }\n}\n\nmodule.exports = {\n  name: 'log-android',\n  description: 'starts adb logcat',\n  func: logAndroid,\n};\n"
  },
  {
    "path": "local-cli/logIOS/logIOS.js",
    "content": "'use strict';\n\nconst chalk = require('chalk');\nconst child_process = require('child_process');\nconst os = require('os');\nconst path = require('path');\nconst Promise = require('promise');\n\n/**\n * Starts iOS device syslog tail\n */\nfunction logIOS() {\n  return new Promise((resolve, reject) => {\n    _logIOS(resolve, reject);\n  });\n}\n\nfunction _logIOS() {\n  let rawDevices;\n\n  try {\n    rawDevices = child_process.execFileSync(\n      'xcrun', ['simctl', 'list', 'devices', '--json'], {encoding: 'utf8'}\n    );\n  } catch (e) {\n    console.log(chalk.red(\n      'xcrun invocation failed. Please check that Xcode is installed.'\n    ));\n    return Promise.reject(e);\n  }\n\n  const { devices } = JSON.parse(rawDevices);\n\n  const device = _findAvailableDevice(devices);\n  if (device === undefined) {\n    console.log(chalk.red(\n      'No active iOS device found'\n    ));\n    return Promise.reject();\n  }\n\n  return tailDeviceLogs(device.udid);\n}\n\nfunction _findAvailableDevice(devices) {\n  for (const key of Object.keys(devices)) {\n    for (const device of devices[key]) {\n      if (device.availability === '(available)' && device.state === 'Booted') {\n        return device;\n      }\n    }\n  }\n}\n\nfunction tailDeviceLogs(udid) {\n  const logDir = path.join(\n    os.homedir(),\n    'Library',\n    'Logs',\n    'CoreSimulator',\n    udid,\n    'asl',\n  );\n\n  const log =\n    child_process.spawnSync('syslog', ['-w', '-F', 'std', '-d', logDir], {stdio: 'inherit'});\n\n  if (log.error !== null) {\n    console.log(chalk.red(\n      'syslog invocation failed.'\n    ));\n    return Promise.reject(log.error);\n  }\n}\n\nmodule.exports = {\n  name: 'log-ios',\n  description: 'starts iOS device syslog tail',\n  func: logIOS,\n};\n"
  },
  {
    "path": "local-cli/runAndroid/adb.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @flow\n */\n\nconst child_process = require('child_process');\n\n/**\n * Parses the output of the 'adb devices' command\n */\nfunction parseDevicesResult(result: string): Array<string> {\n  if (!result) {\n    return [];\n  }\n\n  const devices = [];\n  const lines = result.trim().split(/\\r?\\n/);\n\n  for (let i=0; i < lines.length; i++) {\n    let words = lines[i].split(/[ ,\\t]+/).filter((w) => w !== '');\n\n    if (words[1] === 'device') {\n      devices.push(words[0]);\n    }\n  }\n  return devices;\n}\n\n/**\n * Executes the commands needed to get a list of devices from ADB\n */\nfunction getDevices(): Array<string> {\n  try {\n    const devicesResult = child_process.execSync('adb devices');\n    return parseDevicesResult(devicesResult.toString());\n  } catch (e) {\n    return [];\n  }\n\n\n}\n\nmodule.exports = {\n  parseDevicesResult: parseDevicesResult,\n  getDevices: getDevices\n};"
  },
  {
    "path": "local-cli/runAndroid/runAndroid.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst chalk = require('chalk');\nconst child_process = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\nconst isPackagerRunning = require('../util/isPackagerRunning');\nconst Promise = require('promise');\nconst adb = require('./adb');\n\n// Verifies this is an Android project\nfunction checkAndroid(root) {\n  return fs.existsSync(path.join(root, 'android/gradlew'));\n}\n\n/**\n * Starts the app on a connected Android emulator or device.\n */\nfunction runAndroid(argv, config, args) {\n  if (!checkAndroid(args.root)) {\n    console.log(chalk.red('Android project not found. Maybe run react-native android first?'));\n    return;\n  }\n\n  return isPackagerRunning().then(result => {\n    if (result === 'running') {\n      console.log(chalk.bold('JS server already running.'));\n    } else if (result === 'unrecognized') {\n      console.warn(chalk.yellow('JS server not recognized, continuing with build...'));\n    } else {\n      // result == 'not_running'\n      console.log(chalk.bold('Starting JS server...'));\n      startServerInNewWindow();\n    }\n    return buildAndRun(args);\n  });\n}\n\nfunction getAdbPath() {\n  return process.env.ANDROID_HOME\n    ? process.env.ANDROID_HOME + '/platform-tools/adb'\n    : 'adb';\n}\n\n// Runs ADB reverse tcp:8081 tcp:8081 to allow loading the jsbundle from the packager\nfunction tryRunAdbReverse(device) {\n  try {\n    const adbPath = getAdbPath();\n    const adbArgs = ['reverse', 'tcp:8081', 'tcp:8081'];\n\n    // If a device is specified then tell adb to use it\n    if (device) {\n      adbArgs.unshift('-s', device);\n    }\n\n    console.log(chalk.bold(\n      `Running ${adbPath} ${adbArgs.join(' ')}`\n    ));\n\n    child_process.execFileSync(adbPath, adbArgs, {\n      stdio: [process.stdin, process.stdout, process.stderr],\n    });\n  } catch (e) {\n    console.log(chalk.yellow(\n      `Could not run adb reverse: ${e.message}`\n    ));\n  }\n}\n\n// Builds the app and runs it on a connected emulator / device.\nfunction buildAndRun(args) {\n  process.chdir(path.join(args.root, 'android'));\n  try {\n    adb.getDevices().map((device) => tryRunAdbReverse(device));\n\n    const cmd = process.platform.startsWith('win')\n      ? 'gradlew.bat'\n      : './gradlew';\n\n    const gradleArgs = [];\n    if (args.variant) {\n      gradleArgs.push('install' +\n        args.variant[0].toUpperCase() + args.variant.slice(1)\n      );\n    } else if (args.flavor) {\n      console.warn(chalk.yellow(\n        '--flavor has been deprecated. Use --variant instead'\n      ));\n      gradleArgs.push('install' +\n        args.flavor[0].toUpperCase() + args.flavor.slice(1)\n      );\n    } else {\n      gradleArgs.push('installDebug');\n    }\n\n    if (args.installDebug) {\n      gradleArgs.push(args.installDebug);\n    }\n\n    console.log(chalk.bold(\n      `Building and installing the app on the device (cd android && ${cmd} ${gradleArgs.join(' ')}...`\n    ));\n\n    child_process.execFileSync(cmd, gradleArgs, {\n      stdio: [process.stdin, process.stdout, process.stderr],\n    });\n  } catch (e) {\n    console.log(chalk.red(\n      'Could not install the app on the device, read the error above for details.\\n' +\n      'Make sure you have an Android emulator running or a device connected and have\\n' +\n      'set up your Android development environment:\\n' +\n      'https://facebook.github.io/react-native/docs/android-setup.html'\n    ));\n    // stderr is automatically piped from the gradle process, so the user\n    // should see the error already, there is no need to do\n    // `console.log(e.stderr)`\n    return Promise.reject();\n  }\n\n  try {\n    const packageName = fs.readFileSync(\n      'app/src/main/AndroidManifest.xml',\n      'utf8'\n    ).match(/package=\"(.+?)\"/)[1];\n\n    const adbPath = getAdbPath();\n\n    const devices = adb.getDevices();\n\n    if (devices && devices.length > 0) {\n      devices.forEach((device) => {\n\n        const adbArgs = ['-s', device, 'shell', 'am', 'start', '-n', packageName + '/.MainActivity'];\n\n        console.log(chalk.bold(\n          `Starting the app on ${device} (${adbPath} ${adbArgs.join(' ')})...`\n        ));\n\n        child_process.spawnSync(adbPath, adbArgs, {stdio: 'inherit'});\n      });\n    } else {\n      // If we cannot execute based on adb devices output, fall back to\n      // shell am start\n      const fallbackAdbArgs = [\n        'shell', 'am', 'start', '-n', packageName + '/.MainActivity'\n      ];\n      console.log(chalk.bold(\n        `Starting the app (${adbPath} ${fallbackAdbArgs.join(' ')}...`\n      ));\n      child_process.spawnSync(adbPath, fallbackAdbArgs, {stdio: 'inherit'});\n    }\n\n  } catch (e) {\n    console.log(chalk.red(\n      'adb invocation failed. Do you have adb in your PATH?'\n    ));\n    // stderr is automatically piped from the gradle process, so the user\n    // should see the error already, there is no need to do\n    // `console.log(e.stderr)`\n    return Promise.reject();\n  }\n}\n\nfunction startServerInNewWindow() {\n  const yargV = require('yargs').argv;\n  const scriptFile = /^win/.test(process.platform) ?\n    'launchPackager.bat' :\n    'launchPackager.command';\n  const packagerDir = path.resolve(__dirname, '..', '..', 'packager');\n  const launchPackagerScript = path.resolve(packagerDir, scriptFile);\n  const procConfig = {cwd: packagerDir};\n\n  if (process.platform === 'darwin') {\n    if (yargV.open) {\n      return child_process.spawnSync('open', ['-a', yargV.open, launchPackagerScript], procConfig);\n    }\n    return child_process.spawnSync('open', [launchPackagerScript], procConfig);\n\n  } else if (process.platform === 'linux') {\n    procConfig.detached = true;\n    if (yargV.open){\n      return child_process.spawn(yargV.open,['-e', 'sh', launchPackagerScript], procConfig);\n    }\n    return child_process.spawn('sh', [launchPackagerScript], procConfig);\n\n  } else if (/^win/.test(process.platform)) {\n    procConfig.detached = true;\n    procConfig.stdio = 'ignore';\n    return child_process.spawn('cmd.exe', ['/C', 'start', launchPackagerScript], procConfig);\n  } else {\n    console.log(chalk.red(`Cannot start the packager. Unknown platform ${process.platform}`));\n  }\n}\n\nmodule.exports = {\n  name: 'run-android',\n  description: 'builds your app and starts it on a connected Android emulator or device',\n  func: runAndroid,\n  options: [{\n    command: '--install-debug',\n  }, {\n    command: '--root [string]',\n    description: 'Override the root directory for the android build (which contains the android directory)',\n    default: '',\n  }, {\n    command: '--flavor [string]',\n    description: '--flavor has been deprecated. Use --variant instead',\n  }, {\n    command: '--variant [string]',\n  }],\n};\n"
  },
  {
    "path": "local-cli/runIOS/findMatchingSimulator.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.*\n */\n'use strict';\n\n/**\n * Takes in a parsed simulator list and a desired name, and returns an object with the matching simulator.\n *\n * If the simulatorName argument is null, we'll go into default mode and return the currently booted simulator, or if\n * none is booted, it will be the first in the list.\n *\n * @param Object simulators a parsed list from `xcrun simctl list --json devices` command\n * @param String|null simulatorName the string with the name of desired simulator. If null, it will use the currently\n *        booted simulator, or if none are booted, the first in the list.\n * @returns {Object} {udid, name, version}\n */\nfunction findMatchingSimulator(simulators, simulatorName) {\n  if (!simulators.devices) {\n    return null;\n  }\n  const devices = simulators.devices;\n  var match;\n  for (let version in devices) {\n    // Making sure the version of the simulator is an iOS (Removes Apple Watch, etc)\n    if (version.indexOf('iOS') !== 0) {\n      continue;\n    }\n    for (let i in devices[version]) {\n      let simulator = devices[version][i];\n      // Skipping non-available simulator\n      if (simulator.availability !== '(available)') {\n        continue;\n      }\n      // If there is a booted simulator, we'll use that as instruments will not boot a second simulator\n      if (simulator.state === 'Booted') {\n        if (simulatorName !== null) {\n          console.warn(\"We couldn't boot your defined simulator due to an already booted simulator. We are limited to one simulator launched at a time.\");\n        }\n        return {\n          udid: simulator.udid,\n          name: simulator.name,\n          version\n        };\n      }\n      if (simulator.name === simulatorName) {\n        return {\n          udid: simulator.udid,\n          name: simulator.name,\n          version\n        };\n      }\n      // Keeps track of the first available simulator for use if we can't find one above.\n      if (simulatorName === null && !match) {\n        match = {\n          udid: simulator.udid,\n          name: simulator.name,\n          version\n        };\n      }\n    }\n  }\n  if (match) {\n    return match;\n  }\n  return null;\n}\n\nmodule.exports = findMatchingSimulator;\n"
  },
  {
    "path": "local-cli/runIOS/findXcodeProject.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @flow\n */\n'use strict';\n\nconst path = require('path');\n\ntype ProjectInfo = {\n  name: string;\n  isWorkspace: boolean;\n}\n\nfunction findXcodeProject(files: Array<string>): ?ProjectInfo {\n  const sortedFiles = files.sort();\n  for (let i = sortedFiles.length - 1; i >= 0; i--) {\n    const fileName = files[i];\n    const ext = path.extname(fileName);\n\n    if (ext === '.xcworkspace') {\n      return {\n        name: fileName,\n        isWorkspace: true,\n      };\n    }\n    if (ext === '.xcodeproj') {\n      return {\n        name: fileName,\n        isWorkspace: false,\n      };\n    }\n  }\n\n  return null;\n}\n\nmodule.exports = findXcodeProject;\n"
  },
  {
    "path": "local-cli/runIOS/parseIOSDevicesList.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * @flow\n */\n'use strict';\n\ntype IOSDeviceInfo = {\n  name: string;\n  udid: string;\n  version: string;\n}\n\n/**\n * Parses the output of `xcrun simctl list devices` command\n */\nfunction parseIOSDevicesList(text: string): Array<IOSDeviceInfo> {\n  const devices = [];\n  text.split('\\n').forEach((line) => {\n    const device = line.match(/(.*?) \\((.*?)\\) \\[(.*?)\\]/);\n    const noSimulator = line.match(/(.*?) \\((.*?)\\) \\[(.*?)\\] \\((.*?)\\)/);\n    if (device != null && noSimulator == null){\n      var name = device[1];\n      var version = device[2];\n      var udid = device[3];\n      devices.push({udid, name, version});\n    }\n  });\n\n  return devices;\n}\n\nmodule.exports = parseIOSDevicesList;\n"
  },
  {
    "path": "local-cli/runIOS/runIOS.js",
    "content": "/**\n* Copyright (c) 2015-present, Facebook, Inc.\n* All rights reserved.\n*\n* This source code is licensed under the BSD-style license found in the\n* LICENSE file in the root directory of this source tree. An additional grant\n* of patent rights can be found in the PATENTS file in the same directory.\n*/\n'use strict';\n\nconst child_process = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\nconst findXcodeProject = require('./findXcodeProject');\nconst parseIOSDevicesList = require('./parseIOSDevicesList');\nconst findMatchingSimulator = require('./findMatchingSimulator');\n\nfunction runIOS(argv, config, args) {\n  process.chdir(args.projectPath);\n  const xcodeProject = findXcodeProject(fs.readdirSync('.'));\n  if (!xcodeProject) {\n    throw new Error('Could not find Xcode project files in ios folder');\n  }\n\n  const inferredSchemeName = path.basename(xcodeProject.name, path.extname(xcodeProject.name));\n  const scheme = args.scheme || inferredSchemeName;\n  console.log(`Found Xcode ${xcodeProject.isWorkspace ? 'workspace' : 'project'} ${xcodeProject.name}`);\n  const devices = parseIOSDevicesList(\n    child_process.execFileSync('xcrun', ['instruments', '-s'], {encoding: 'utf8'})\n  );\n  if (args.device) {\n    const selectedDevice = matchingDevice(devices, args.device);\n    if (selectedDevice){\n      runOnDevice(selectedDevice, scheme, xcodeProject);\n    } else {\n      if (devices){\n        console.log('Could not find device with the name: \"' + args.device + '\".');\n        console.log('Choose one of the following:');\n        printFoundDevices(devices);\n      } else {\n        console.log('No iOS devices connected.');\n      }\n    }\n  } else if (args.udid) {\n    runOnDeviceByUdid(args.udid, scheme, xcodeProject, devices);\n  } else {\n    runOnSimulator(xcodeProject, args, inferredSchemeName, scheme);\n  }\n}\n\nfunction runOnDeviceByUdid(udid, scheme, xcodeProject, devices) {\n  const selectedDevice = matchingDeviceByUdid(devices, udid);\n  if (selectedDevice){\n    runOnDevice(selectedDevice, scheme, xcodeProject);\n  } else {\n    if (devices){\n      console.log('Could not find device with the udid: \"' + udid + '\".');\n      console.log('Choose one of the following:');\n      printFoundDevices(devices);\n    } else {\n      console.log('No iOS devices connected.');\n    }\n  }\n}\n\nfunction runOnSimulator(xcodeProject, args, inferredSchemeName, scheme){\n  try {\n    var simulators = JSON.parse(\n    child_process.execFileSync('xcrun', ['simctl', 'list', '--json', 'devices'], {encoding: 'utf8'})\n    );\n  } catch (e) {\n    throw new Error('Could not parse the simulator list output');\n  }\n\n  const selectedSimulator = findMatchingSimulator(simulators, args.simulator);\n  if (!selectedSimulator) {\n    throw new Error(`Cound't find ${args.simulator} simulator`);\n  }\n\n  const simulatorFullName = formattedDeviceName(selectedSimulator);\n  console.log(`Launching ${simulatorFullName}...`);\n  try {\n    child_process.spawnSync('xcrun', ['instruments', '-w', selectedSimulator.udid]);\n  } catch (e) {\n    // instruments always fail with 255 because it expects more arguments,\n    // but we want it to only launch the simulator\n  }\n\n  buildProject(xcodeProject, selectedSimulator.udid, scheme);\n\n  const appPath = `build/Build/Products/Debug-iphonesimulator/${inferredSchemeName}.app`;\n  console.log(`Installing ${appPath}`);\n  child_process.spawnSync('xcrun', ['simctl', 'install', 'booted', appPath], {stdio: 'inherit'});\n\n  const bundleID = child_process.execFileSync(\n    '/usr/libexec/PlistBuddy',\n    ['-c', 'Print:CFBundleIdentifier', path.join(appPath, 'Info.plist')],\n    {encoding: 'utf8'}\n  ).trim();\n\n  console.log(`Launching ${bundleID}`);\n  child_process.spawnSync('xcrun', ['simctl', 'launch', 'booted', bundleID], {stdio: 'inherit'});\n}\n\nfunction runOnDevice(selectedDevice, scheme, xcodeProject){\n  buildProject(xcodeProject, selectedDevice.udid, scheme);\n  const iosDeployInstallArgs = [\n    '--bundle', 'build/Build/Products/Debug-iphoneos/' + scheme + '.app',\n    '--id' , selectedDevice.udid,\n    '--justlaunch'\n  ];\n  console.log(`installing and launching your app on ${selectedDevice.name}...`);\n  var iosDeployOutput = child_process.spawnSync('ios-deploy', iosDeployInstallArgs, {encoding: 'utf8'});\n  if (iosDeployOutput.error) {\n    console.log('');\n    console.log('** INSTALLATION FAILED **');\n    console.log('Make sure you have ios-deploy installed globally.');\n    console.log('(e.g \"npm install -g ios-deploy\")');\n  } else {\n    console.log('** INSTALLATION SUCCEEDED **');\n  }\n}\n\nfunction buildProject(xcodeProject, udid, scheme) {\n  const xcodebuildArgs = [\n    xcodeProject.isWorkspace ? '-workspace' : '-project', xcodeProject.name,\n    '-scheme', scheme,\n    '-destination', `id=${udid}`,\n    '-derivedDataPath', 'build',\n  ];\n  console.log(`Building using \"xcodebuild ${xcodebuildArgs.join(' ')}\"`);\n  child_process.spawnSync('xcodebuild', xcodebuildArgs, {stdio: 'inherit'});\n}\n\nfunction matchingDevice(devices, deviceName) {\n  for (let i = devices.length - 1; i >= 0; i--) {\n    if (devices[i].name === deviceName || formattedDeviceName(devices[i]) === deviceName) {\n      return devices[i];\n    }\n  }\n}\n\nfunction matchingDeviceByUdid(devices, udid) {\n  for (let i = devices.length - 1; i >= 0; i--) {\n    if (devices[i].udid === udid) {\n      return devices[i];\n    }\n  }\n}\n\nfunction formattedDeviceName(simulator) {\n  return `${simulator.name} (${simulator.version})`;\n}\n\nfunction printFoundDevices(devices){\n  for (let i = devices.length - 1; i >= 0; i--) {\n    console.log(devices[i].name + ' Udid: ' + devices[i].udid);\n  }\n}\n\nmodule.exports = {\n  name: 'run-ios',\n  description: 'builds your app and starts it on iOS simulator',\n  func: runIOS,\n  examples: [\n  {\n    desc: 'Run on a different simulator, e.g. iPhone 5',\n    cmd: 'react-native run-ios --simulator \"iPhone 5\"',\n  },\n  {\n    desc: 'Pass a non-standard location of iOS directory',\n    cmd: 'react-native run-ios --project-path \"./app/ios\"',\n  },\n  {\n    desc: \"Run on a connected device, e.g. Max's iPhone\",\n    cmd: \"react-native run-ios --device 'Max's iPhone'\",\n  },\n  ],\n  options: [{\n    command: '--simulator [string]',\n    description: 'Explicitly set simulator to use',\n    default: 'iPhone 6',\n  }, {\n    command: '--scheme [string]',\n    description: 'Explicitly set Xcode scheme to use',\n  }, {\n    command: '--project-path [string]',\n    description: 'Path relative to project root where the Xcode project '\n      + '(.xcodeproj) lives. The default is \\'ios\\'.',\n    default: 'ios',\n  }, {\n    command: '--device [string]',\n    description: 'Explicitly set device to use by name',\n  },{\n    command: '--udid [string]',\n    description: 'Explicitly set device to use by udid',\n  }]\n};\n"
  },
  {
    "path": "local-cli/server/checkNodeVersion.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar chalk = require('chalk');\nvar formatBanner = require('./formatBanner');\nvar semver = require('semver');\n\nmodule.exports = function() {\n  if (!semver.satisfies(process.version, '>=4')) {\n    var engine = semver.satisfies(process.version, '<1')\n      ? 'Node'\n      : 'io.js';\n\n    var message = 'You are currently running ' + engine + ' ' +\n      process.version + '.\\n' +\n      '\\n' +\n      'React Native runs on Node 4.0 or newer. There are several ways to ' +\n      'upgrade Node.js depending on your preference.\\n' +\n      '\\n' +\n      'nvm:       nvm install node && nvm alias default node\\n' +\n      'Homebrew:  brew unlink iojs; brew install node\\n' +\n      'Installer: download the Mac .pkg from https://nodejs.org/\\n' +\n      '\\n' +\n      'About Node.js:   https://nodejs.org\\n' +\n      'Follow along at: https://github.com/facebook/react-native/issues/2545';\n    console.log(formatBanner(message, {\n      chalkFunction: chalk.green,\n      marginLeft: 1,\n      marginRight: 1,\n      paddingBottom: 1,\n    }));\n    process.exit(1);\n  }\n};\n"
  },
  {
    "path": "local-cli/server/findSymlinksPaths.js",
    "content": "const path = require('path');\nconst fs = require('fs');\n\n/**\n * Find and resolve symlinks in `lookupFolder`.\n * Ignore any descendants of the paths in `ignoredRoots`.\n */\nmodule.exports = function findSymlinksPaths(lookupFolder, ignoredRoots) {\n  const timeStart = Date.now();\n  const folders = fs.readdirSync(lookupFolder);\n\n  const resolvedSymlinks = [];\n  folders.forEach(folder => {\n    const visited = [];\n\n    let symlink = path.resolve(lookupFolder, folder);\n    while (fs.lstatSync(symlink).isSymbolicLink()) {\n      const index = visited.indexOf(symlink);\n      if (index !== -1) {\n        throw Error(\n          `Infinite symlink recursion detected:\\n  ` +\n            visited.slice(index).join(`\\n  `)\n        );\n      }\n\n      visited.push(symlink);\n      symlink = path.resolve(\n        path.dirname(symlink),\n        fs.readlinkSync(symlink)\n      );\n    }\n\n    if (visited.length && !rootExists(ignoredRoots, symlink)) {\n      resolvedSymlinks.push(symlink);\n    }\n  });\n\n  const timeEnd = Date.now();\n  console.log(`Scanning ${folders.length} folders for symlinks in ${lookupFolder} (${timeEnd - timeStart}ms)`);\n\n  return resolvedSymlinks;\n};\n\nfunction rootExists(roots, child) {\n  return roots.some(root => isDescendant(root, child));\n}\n\nfunction isDescendant(root, child) {\n  return root === child || child.startsWith(root + path.sep);\n}\n"
  },
  {
    "path": "local-cli/server/formatBanner.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar _ = require('lodash');\nvar wordwrap = require('wordwrap');\n\nvar HORIZONTAL_LINE = '\\u2500';\nvar VERTICAL_LINE = '\\u2502';\nvar TOP_LEFT = '\\u250c';\nvar TOP_RIGHT = '\\u2510';\nvar BOTTOM_LEFT = '\\u2514';\nvar BOTTOM_RIGHT = '\\u2518';\n\n/**\n * Prints a banner with a border around it containing the given message. The\n * following options are supported:\n *\n * type Options = {\n *   // A function to apply to each line of text to decorate it\n *   chalkFunction: (string: message) => string;\n *   // The total width (max line length) of the banner, including margin and\n *   // padding (default = 80)\n *   width: number;\n *   // How much leading space to prepend to each line (default = 0)\n *   marginLeft: number;\n *   // How much trailing space to append to each line (default = 0)\n *   marginRight: number;\n *   // Space between the top banner border and the text (default = 0)\n *   paddingTop: number;\n *   // Space between the bottom banner border and the text (default = 0)\n *   paddingBottom: number;\n *   // Space between the left banner border and the text (default = 2)\n *   paddingLeft: number;\n *   // Space between the right banner border and the text (default = 2)\n *   paddingRight: number;\n * };\n */\nfunction formatBanner(message, options) {\n  options = options || {};\n  _.defaults(options, {\n    chalkFunction: _.identity,\n    width: 80,\n    marginLeft: 0,\n    marginRight: 0,\n    paddingTop: 0,\n    paddingBottom: 0,\n    paddingLeft: 2,\n    paddingRight: 2,\n  });\n\n  var width = options.width;\n  var marginLeft = options.marginLeft;\n  var marginRight = options.marginRight;\n  var paddingTop = options.paddingTop;\n  var paddingBottom = options.paddingBottom;\n  var paddingLeft = options.paddingLeft;\n  var paddingRight = options.paddingRight;\n\n  var horizSpacing = marginLeft + paddingLeft + paddingRight + marginRight;\n  // 2 for the banner borders\n  var maxLineWidth = width - horizSpacing - 2;\n  var wrap = wordwrap(maxLineWidth);\n  var body = wrap(message);\n\n  var left = spaces(marginLeft) + VERTICAL_LINE + spaces(paddingLeft);\n  var right = spaces(paddingRight) + VERTICAL_LINE + spaces(marginRight);\n  var bodyLines = _.flattenDeep([\n    arrayOf('', paddingTop),\n    body.split('\\n'),\n    arrayOf('', paddingBottom),\n  ]).map(function(line) {\n    var padding = spaces(Math.max(0, maxLineWidth - line.length));\n    return left + options.chalkFunction(line) + padding + right;\n  });\n\n  var horizontalBorderLine = repeatString(\n    HORIZONTAL_LINE,\n    width - marginLeft - marginRight - 2\n  );\n  var top = spaces(marginLeft) + TOP_LEFT + horizontalBorderLine + TOP_RIGHT +\n    spaces(marginRight);\n  var bottom = spaces(marginLeft) + BOTTOM_LEFT + horizontalBorderLine +\n    BOTTOM_RIGHT + spaces(marginRight);\n  return _.flattenDeep([top, bodyLines, bottom]).join('\\n');\n}\n\nfunction spaces(number) {\n  return repeatString(' ', number);\n}\n\nfunction repeatString(string, number) {\n  return new Array(number + 1).join(string);\n}\n\nfunction arrayOf(value, number) {\n  return _.range(number).map(function() {\n    return value;\n  });\n}\n\nmodule.exports = formatBanner;\n"
  },
  {
    "path": "local-cli/server/middleware/copyToClipBoardMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst copyToClipBoard = require('../util/copyToClipBoard');\nvar chalk = require('chalk');\n\n/**\n * Handle the request from JS to copy contents onto host system clipboard.\n * This is only supported on Mac for now.\n */\nmodule.exports = function(req, res, next) {\n  if (req.url === '/copy-to-clipboard') {\n    var ret = copyToClipBoard(req.rawBody);\n    if (!ret) {\n      console.warn(chalk.red('Copy button is not supported on this platform!'));\n    }\n    res.end('OK');\n  } else {\n    next();\n  }\n};\n"
  },
  {
    "path": "local-cli/server/middleware/cpuProfilerMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst execFile = require('child_process').execFile;\nconst fs = require('fs');\nconst path = require('path');\n\nmodule.exports = function(req, res, next) {\n  if (req.url !== '/cpu-profile') {\n    next();\n    return;\n  }\n\n  console.log('Dumping CPU profile information...');\n  var dumpName = '/tmp/cpu-profile_' + Date.now();\n  fs.writeFileSync(dumpName + '.json', req.rawBody);\n\n  var cmdPath = path.join(\n    __dirname,\n    '../../../JSCLegacyProfiler/json2trace'\n  );\n  execFile(\n    cmdPath,\n    [\n      '-cpuprofiler',\n      dumpName + '.cpuprofile',\n      dumpName + '.json',\n    ],\n    function(error) {\n      if (error) {\n        console.error(error);\n        res.end('Unknown error: ' + error.message);\n      } else {\n        var response = 'Your profile was generated at\\n\\n' + dumpName + '.cpuprofile\\n\\n' +\n          'Open `Chrome Dev Tools > Profiles > Load` and select the profile to visualize it.';\n        console.log(response);\n        res.end(response);\n      }\n    }\n  );\n};\n"
  },
  {
    "path": "local-cli/server/middleware/getDevToolsMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar child_process = require('child_process');\nvar execFile = require('child_process').execFile;\nvar fs = require('fs');\nvar opn = require('opn');\nvar path = require('path');\n\nfunction getChromeAppName() {\n  switch (process.platform) {\n  case 'darwin':\n    return 'google chrome';\n  case 'win32':\n    return 'chrome';\n  default:\n    return 'google-chrome';\n  }\n}\n\nfunction launchChromeDevTools(port) {\n  var debuggerURL = 'http://localhost:' + port + '/debugger-ui';\n  console.log('Launching Dev Tools...');\n  opn(debuggerURL, {app: [getChromeAppName()]}, function(err) {\n    if (err) {\n      console.error('Google Chrome exited with error:', err);\n    }\n  });\n}\n\nfunction escapePath(path) {\n  return '\"' + path + '\"'; // \" Can escape paths with spaces in OS X, Windows, and *nix\n}\n\nfunction launchDevTools(options, isChromeConnected) {\n  // Explicit config always wins\n  var customDebugger = process.env.REACT_DEBUGGER;\n  if (customDebugger) {\n    var projects = options.projectRoots.map(escapePath).join(' ');\n    var command = customDebugger + ' ' + projects;\n    console.log('Starting custom debugger by executing: ' + command);\n    child_process.exec(command, function (error, stdout, stderr) {\n      if (error !== null) {\n        console.log('Error while starting custom debugger: ' + error);\n      }\n    });\n  } else if (!isChromeConnected()) {\n    // Dev tools are not yet open; we need to open a session\n    launchChromeDevTools(options.port);\n  }\n}\n\nmodule.exports = function(options, isChromeConnected) {\n  return function(req, res, next) {\n    if (req.url === '/debugger-ui') {\n      var debuggerPath = path.join(__dirname, '..', 'util', 'debugger.html');\n      res.writeHead(200, {'Content-Type': 'text/html'});\n      fs.createReadStream(debuggerPath).pipe(res);\n    } else if (req.url === '/debuggerWorker.js') {\n      var workerPath = path.join(__dirname, '..', 'util', 'debuggerWorker.js');\n      res.writeHead(200, {'Content-Type': 'application/javascript'});\n      fs.createReadStream(workerPath).pipe(res);\n    } else if (req.url === '/launch-safari-devtools') {\n      // TODO: remove `console.log` and dev tools binary\n      console.log(\n        'We removed support for Safari dev-tools. ' +\n        'If you still need this, please let us know.'\n      );\n    } else if (req.url === '/launch-chrome-devtools') {\n      // TODO: Remove this case in the future\n      console.log(\n        'The method /launch-chrome-devtools is deprecated. You are ' +\n        ' probably using an application created with an older CLI with the ' + \n        ' packager of a newer CLI. Please upgrade your application: ' +\n        'https://facebook.github.io/react-native/docs/upgrading.html');\n        launchDevTools(options, isChromeConnected);\n        res.end('OK');\n    } else if (req.url === '/launch-js-devtools') {\n      launchDevTools(options, isChromeConnected);\n      res.end('OK');\n    } else {\n      next();\n    }\n  };\n};\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/.npmignore",
    "content": "/captures/*\npreLoadedCapture.js\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/Makefile",
    "content": "SHELL := /bin/bash\n\nall:\n\tNODE_PATH=\"../../../../node_modules/\" babel --presets babel-preset-react-native -d out src\n\tfor f in out/*.js; do echo \"// @generated\" >> $$f; done\n\nwatch:\n\tNODE_PATH=\"../../../../node_modules/\" babel --watch --presets babel-preset-react-native -d out src\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/heapCapture.html",
    "content": "<!doctype html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" style=\"height: 100%;\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>JSC Heap Capture</title>\n  <script src=\"https://cdnjs.cloudflare.com/ajax/libs/react/0.14.1/react.min.js\"></script>\n  <script src=\"https://cdnjs.cloudflare.com/ajax/libs/react/0.14.1/react-dom.min.js\"></script>\n  <script src=\"out/aggrow.js\"></script>\n  <script src=\"out/table.js\"></script>\n</head>\n<body style=\"margin:0px; height: 100%\">\n  Loading... This could take a while depending on how big the profile is. Check devtools console for errors.\n</body>\n<script src=\"preLoadedCapture.js\"></script>\n<script src=\"out/heapCapture.js\"></script>\n</html>\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/out/aggrow.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n/*eslint no-bitwise: \"off\"*/\n/*eslint no-console-disallow: \"off\"*/\n\n// TODO: future features\n// put in a module.exports\n// filtering / search\n// pivot around frames in the middle of a stack by callers / callees\n// graphing?\n\nfunction stringInterner(){// eslint-disable-line no-unused-vars\nvar strings=[];\nvar ids={};\nreturn{\nintern:function internString(s){\nvar find=ids[s];\nif(find===undefined){\nvar id=strings.length;\nids[s]=id;\nstrings.push(s);\nreturn id;\n}else{\nreturn find;\n}\n},\nget:function getString(id){\nreturn strings[id];\n}};\n\n}\n\nfunction stackData(stackIdMap,maxDepth){// eslint-disable-line no-unused-vars\nreturn{\nmaxDepth:maxDepth,\nget:function getStack(id){\nreturn stackIdMap[id];\n}};\n\n}\n\nfunction stackRegistry(interner){// eslint-disable-line no-unused-vars\nreturn{\nroot:{id:0},\nnodeCount:1,\ninsert:function insertNode(parent,label){\nvar labelId=interner.intern(label);\nvar node=parent[labelId];\nif(node===undefined){\nnode={id:this.nodeCount};\nthis.nodeCount++;\nparent[labelId]=node;\n}\nreturn node;\n},\nflatten:function flattenStacks(){\nvar stackFrameCount=0;\nfunction countStacks(tree,depth){\nvar leaf=true;\nfor(var frameId in tree){\nif(frameId!=='id'){\nleaf=countStacks(tree[frameId],depth+1);\n}\n}\nif(leaf){\nstackFrameCount+=depth;\n}\nreturn false;\n}\ncountStacks(this.root,0);\nconsole.log('size needed to store stacks: '+(stackFrameCount*4).toString()+'B');\nvar stackIdMap=new Array(this.nodeCount);\nvar stackArray=new Int32Array(stackFrameCount);\nvar maxStackDepth=0;\nstackFrameCount=0;\nfunction flattenStacksImpl(tree,stack){\nvar childStack=void 0;\nmaxStackDepth=Math.max(maxStackDepth,stack.length);\nfor(var frameId in tree){\nif(frameId!=='id'){\nstack.push(Number(frameId));\nchildStack=flattenStacksImpl(tree[frameId],stack);\nstack.pop();\n}\n}\n\nvar id=tree.id;\nif(id<0||id>=stackIdMap.length||stackIdMap[id]!==undefined){\nthrow'invalid stack id!';\n}\n\nif(childStack!==undefined){\n// each child must have our stack as a prefix, so just use that\nstackIdMap[id]=childStack.subarray(0,stack.length);\n}else{\nvar newStack=stackArray.subarray(stackFrameCount,stackFrameCount+stack.length);\nstackFrameCount+=stack.length;\nfor(var i=0;i<stack.length;i++){\nnewStack[i]=stack[i];\n}\nstackIdMap[id]=newStack;\n}\nreturn stackIdMap[id];\n}\nflattenStacksImpl(this.root,[]);\n\nreturn new stackData(stackIdMap,maxStackDepth);\n}};\n\n}\n\nfunction aggrow(strings,stacks,numRows){// eslint-disable-line no-unused-vars\n// expander ID definitions\nvar FIELD_EXPANDER_ID_MIN=0x0000;\nvar FIELD_EXPANDER_ID_MAX=0x7fff;\nvar STACK_EXPANDER_ID_MIN=0x8000;\nvar STACK_EXPANDER_ID_MAX=0xffff;\n\n// used for row.expander which reference state.activeExpanders (with frame index masked in)\nvar INVALID_ACTIVE_EXPANDER=-1;\nvar ACTIVE_EXPANDER_MASK=0xffff;\nvar ACTIVE_EXPANDER_FRAME_SHIFT=16;\n\n// aggregator ID definitions\nvar AGGREGATOR_ID_MAX=0xffff;\n\n// active aggragators can have sort order changed in the reference\nvar ACTIVE_AGGREGATOR_MASK=0xffff;\nvar ACTIVE_AGGREGATOR_ASC_BIT=0x10000;\n\n// tree node state definitions\nvar NODE_EXPANDED_BIT=0x0001;// this row is expanded\nvar NODE_REAGGREGATE_BIT=0x0002;// children need aggregates\nvar NODE_REORDER_BIT=0x0004;// children need to be sorted\nvar NODE_REPOSITION_BIT=0x0008;// children need position\nvar NODE_INDENT_SHIFT=16;\n\nfunction calleeFrameGetter(stack,depth){\nreturn stack[depth];\n}\n\nfunction callerFrameGetter(stack,depth){\nreturn stack[stack.length-depth-1];\n}\n\nfunction createStackComparers(stackGetter,frameGetter){\nvar comparers=new Array(stacks.maxDepth);var _loop=function _loop(\ndepth){\nvar captureDepth=depth;// NB: to capture depth per loop iteration\ncomparers[depth]=function calleeStackComparer(rowA,rowB){\nvar a=stackGetter(rowA);\nvar b=stackGetter(rowB);\n// NB: we put the stacks that are too short at the top,\n// so they can be grouped into the '<exclusive>' bucket\nif(a.length<=captureDepth&&b.length<=captureDepth){\nreturn 0;\n}else if(a.length<=captureDepth){\nreturn-1;\n}else if(b.length<=captureDepth){\nreturn 1;\n}\nreturn frameGetter(a,captureDepth)-frameGetter(b,captureDepth);\n};};for(var depth=0;depth<stacks.maxDepth;depth++){_loop(depth);\n}\nreturn comparers;\n}\n\nfunction createTreeNode(parent,label,indices,expander){\nvar indent=parent===null?0:(parent.state>>>NODE_INDENT_SHIFT)+1;\nvar state=NODE_REPOSITION_BIT|\nNODE_REAGGREGATE_BIT|\nNODE_REORDER_BIT|\nindent<<NODE_INDENT_SHIFT;\nreturn{\nparent:parent,// null if root\nchildren:null,// array of children nodes\nlabel:label,// string to show in UI\nindices:indices,// row indices under this node\naggregates:null,// result of aggregate on indices\nexpander:expander,// index into state.activeExpanders\ntop:0,// y position of top row (in rows)\nheight:1,// number of rows including children\nstate:state};\n\n}\n\nfunction noSortOrder(a,b){\nreturn 0;\n}\n\nvar indices=new Int32Array(numRows);\nfor(var i=0;i<numRows;i++){\nindices[i]=i;\n}\n\nvar state={\nfieldExpanders:[],// tree expanders that expand on simple values\nstackExpanders:[],// tree expanders that expand stacks\nactiveExpanders:[],// index into field or stack expanders, hierarchy of tree\naggregators:[],// all available aggregators, might not be used\nactiveAggregators:[],// index into aggregators, to actually compute\nsorter:noSortOrder,// compare function that uses sortOrder to sort row.children\nroot:createTreeNode(null,'<root>',indices,INVALID_ACTIVE_EXPANDER)};\n\n\nfunction evaluateAggregate(row){\nvar activeAggregators=state.activeAggregators;\nvar aggregates=new Array(activeAggregators.length);\nfor(var j=0;j<activeAggregators.length;j++){\nvar aggregator=state.aggregators[activeAggregators[j]];\naggregates[j]=aggregator.aggregator(row.indices);\n}\nrow.aggregates=aggregates;\nrow.state|=NODE_REAGGREGATE_BIT;\n}\n\nfunction evaluateAggregates(row){\nif((row.state&NODE_EXPANDED_BIT)!==0){\nvar children=row.children;\nfor(var _i=0;_i<children.length;_i++){\nevaluateAggregate(children[_i]);\n}\nrow.state|=NODE_REORDER_BIT;\n}\nrow.state^=NODE_REAGGREGATE_BIT;\n}\n\nfunction evaluateOrder(row){\nif((row.state&NODE_EXPANDED_BIT)!==0){\nvar children=row.children;\nfor(var _i2=0;_i2<children.length;_i2++){\nvar child=children[_i2];\nchild.state|=NODE_REORDER_BIT;\n}\nchildren.sort(state.sorter);\nrow.state|=NODE_REPOSITION_BIT;\n}\nrow.state^=NODE_REORDER_BIT;\n}\n\nfunction evaluatePosition(row){\nif((row.state&NODE_EXPANDED_BIT)!==0){\nvar children=row.children;\nvar childTop=row.top+1;\nfor(var _i3=0;_i3<children.length;_i3++){\nvar child=children[_i3];\nif(child.top!==childTop){\nchild.top=childTop;\nchild.state|=NODE_REPOSITION_BIT;\n}\nchildTop+=child.height;\n}\n}\nrow.state^=NODE_REPOSITION_BIT;\n}\n\nfunction getRowsImpl(row,top,height,result){\nif((row.state&NODE_REAGGREGATE_BIT)!==0){\nevaluateAggregates(row);\n}\nif((row.state&NODE_REORDER_BIT)!==0){\nevaluateOrder(row);\n}\nif((row.state&NODE_REPOSITION_BIT)!==0){\nevaluatePosition(row);\n}\n\nif(row.top>=top&&row.top<top+height){\nif(result[row.top-top]!=null){\nthrow'getRows put more than one row at position '+row.top+' into result';\n}\nresult[row.top-top]=row;\n}\nif((row.state&NODE_EXPANDED_BIT)!==0){\nvar children=row.children;\nfor(var _i4=0;_i4<children.length;_i4++){\nvar child=children[_i4];\nif(child.top<top+height&&top<child.top+child.height){\ngetRowsImpl(child,top,height,result);\n}\n}\n}\n}\n\nfunction updateHeight(row,heightChange){\nwhile(row!==null){\nrow.height+=heightChange;\nrow.state|=NODE_REPOSITION_BIT;\nrow=row.parent;\n}\n}\n\nfunction addChildrenWithFieldExpander(row,expander,nextActiveIndex){\nvar rowIndices=row.indices;\nvar comparer=expander.comparer;\nrowIndices.sort(comparer);\nvar begin=0;\nvar end=1;\nrow.children=[];\nwhile(end<rowIndices.length){\nif(comparer(rowIndices[begin],rowIndices[end])!==0){\nrow.children.push(createTreeNode(\nrow,\nexpander.name+': '+expander.formatter(rowIndices[begin]),\nrowIndices.subarray(begin,end),\nnextActiveIndex));\nbegin=end;\n}\nend++;\n}\nrow.children.push(createTreeNode(\nrow,\nexpander.name+': '+expander.formatter(rowIndices[begin]),\nrowIndices.subarray(begin,end),\nnextActiveIndex));\n}\n\nfunction addChildrenWithStackExpander(row,expander,activeIndex,depth,nextActiveIndex){\nvar rowIndices=row.indices;\nvar stackGetter=expander.stackGetter;\nvar frameGetter=expander.frameGetter;\nvar comparer=expander.comparers[depth];\nvar expandNextFrame=activeIndex|depth+1<<ACTIVE_EXPANDER_FRAME_SHIFT;\nrowIndices.sort(comparer);\nvar columnName='';\nif(depth===0){\ncolumnName=expander.name+': ';\n}\n\n// put all the too-short stacks under <exclusive>\nvar begin=0;\nvar beginStack=null;\nrow.children=[];\nwhile(begin<rowIndices.length){\nbeginStack=stackGetter(rowIndices[begin]);\nif(beginStack.length>depth){\nbreak;\n}\nbegin++;\n}\nif(begin>0){\nrow.children.push(createTreeNode(\nrow,\ncolumnName+'<exclusive>',\nrowIndices.subarray(0,begin),\nnextActiveIndex));\n}\n// aggregate the rest under frames\nif(begin<rowIndices.length){\nvar end=begin+1;\nwhile(end<rowIndices.length){\nvar endStack=stackGetter(rowIndices[end]);\nif(frameGetter(beginStack,depth)!==frameGetter(endStack,depth)){\nrow.children.push(createTreeNode(\nrow,\ncolumnName+strings.get(frameGetter(beginStack,depth)),\nrowIndices.subarray(begin,end),\nexpandNextFrame));\nbegin=end;\nbeginStack=endStack;\n}\nend++;\n}\nrow.children.push(createTreeNode(\nrow,\ncolumnName+strings.get(frameGetter(beginStack,depth)),\nrowIndices.subarray(begin,end),\nexpandNextFrame));\n}\n}\n\nfunction contractRow(row){\nif((row.state&NODE_EXPANDED_BIT)===0){\nthrow'can not contract row, already contracted';\n}\nrow.state^=NODE_EXPANDED_BIT;\nvar heightChange=1-row.height;\nupdateHeight(row,heightChange);\n}\n\nfunction pruneExpanders(row,oldExpander,newExpander){\nrow.state|=NODE_REPOSITION_BIT;\nif(row.expander===oldExpander){\nrow.state|=NODE_REAGGREGATE_BIT|NODE_REORDER_BIT|NODE_REPOSITION_BIT;\nif((row.state&NODE_EXPANDED_BIT)!==0){\ncontractRow(row);\n}\nrow.children=null;\nrow.expander=newExpander;\n}else{\nrow.state|=NODE_REPOSITION_BIT;\nvar children=row.children;\nif(children!=null){\nfor(var _i5=0;_i5<children.length;_i5++){\nvar child=children[_i5];\npruneExpanders(child,oldExpander,newExpander);\n}\n}\n}\n}\n\nreturn{\naddFieldExpander:function addFieldExpander(name,formatter,comparer){\nif(FIELD_EXPANDER_ID_MIN+state.fieldExpanders.length>=FIELD_EXPANDER_ID_MAX){\nthrow'too many field expanders!';\n}\nstate.fieldExpanders.push({\nname:name,// name for column\nformatter:formatter,// row index -> display string\ncomparer:comparer});\n\nreturn FIELD_EXPANDER_ID_MIN+state.fieldExpanders.length-1;\n},\naddCalleeStackExpander:function addCalleeStackExpander(name,stackGetter){\nif(STACK_EXPANDER_ID_MIN+state.fieldExpanders.length>=STACK_EXPANDER_ID_MAX){\nthrow'too many stack expanders!';\n}\nstate.stackExpanders.push({\nname:name,// name for column\nstackGetter:stackGetter,// row index -> stack array\ncomparers:createStackComparers(stackGetter,calleeFrameGetter),// depth -> comparer\nframeGetter:calleeFrameGetter});\n\nreturn STACK_EXPANDER_ID_MIN+state.stackExpanders.length-1;\n},\naddCallerStackExpander:function addCallerStackExpander(name,stackGetter){\nif(STACK_EXPANDER_ID_MIN+state.fieldExpanders.length>=STACK_EXPANDER_ID_MAX){\nthrow'too many stack expanders!';\n}\nstate.stackExpanders.push({\nname:name,\nstackGetter:stackGetter,\ncomparers:createStackComparers(stackGetter,callerFrameGetter),\nframeGetter:callerFrameGetter});\n\nreturn STACK_EXPANDER_ID_MIN+state.stackExpanders.length-1;\n},\ngetExpanders:function getExpanders(){\nvar expanders=[];\nfor(var _i6=0;_i6<state.fieldExpanders.length;_i6++){\nexpanders.push(FIELD_EXPANDER_ID_MIN+_i6);\n}\nfor(var _i7=0;_i7<state.stackExpanders.length;_i7++){\nexpanders.push(STACK_EXPANDER_ID_MIN+_i7);\n}\nreturn expanders;\n},\ngetExpanderName:function getExpanderName(id){\nif(id>=FIELD_EXPANDER_ID_MIN&&id<=FIELD_EXPANDER_ID_MAX){\nreturn state.fieldExpanders[id-FIELD_EXPANDER_ID_MIN].name;\n}else if(id>=STACK_EXPANDER_ID_MIN&&id<=STACK_EXPANDER_ID_MAX){\nreturn state.stackExpanders[id-STACK_EXPANDER_ID_MIN].name;\n}\nthrow'Unknown expander ID '+id.toString();\n},\nsetActiveExpanders:function setActiveExpanders(ids){\nfor(var _i8=0;_i8<ids.length;_i8++){\nvar id=ids[_i8];\nif(id>=FIELD_EXPANDER_ID_MIN&&id<=FIELD_EXPANDER_ID_MAX){\nif(id-FIELD_EXPANDER_ID_MIN>=state.fieldExpanders.length){\nthrow'field expander for id '+id.toString()+' does not exist!';\n}\n}else if(id>=STACK_EXPANDER_ID_MIN&&id<=STACK_EXPANDER_ID_MAX){\nif(id-STACK_EXPANDER_ID_MIN>=state.stackExpanders.length){\nthrow'stack expander for id '+id.toString()+' does not exist!';\n}\n}\n}\nfor(var _i9=0;_i9<ids.length;_i9++){\nif(state.activeExpanders.length<=_i9){\npruneExpanders(state.root,INVALID_ACTIVE_EXPANDER,_i9);\nbreak;\n}else if(ids[_i9]!==state.activeExpanders[_i9]){\npruneExpanders(state.root,_i9,_i9);\nbreak;\n}\n}\n// TODO: if ids is prefix of activeExpanders, we need to make an expander invalid\nstate.activeExpanders=ids.slice();\n},\ngetActiveExpanders:function getActiveExpanders(){\nreturn state.activeExpanders.slice();\n},\naddAggregator:function addAggregator(name,aggregator,formatter,sorter){\nif(state.aggregators.length>=AGGREGATOR_ID_MAX){\nthrow'too many aggregators!';\n}\nstate.aggregators.push({\nname:name,// name for column\naggregator:aggregator,// index array -> aggregate value\nformatter:formatter,// aggregate value -> display string\nsorter:sorter});\n\nreturn state.aggregators.length-1;\n},\ngetAggregators:function getAggregators(){\nvar aggregators=[];\nfor(var _i10=0;_i10<state.aggregators.length;_i10++){\naggregators.push(_i10);\n}\nreturn aggregators;\n},\ngetAggregatorName:function getAggregatorName(id){\nreturn state.aggregators[id&ACTIVE_AGGREGATOR_MASK].name;\n},\nsetActiveAggregators:function setActiveAggregators(ids){\nfor(var _i11=0;_i11<ids.length;_i11++){\nvar id=ids[_i11]&ACTIVE_AGGREGATOR_MASK;\nif(id<0||id>state.aggregators.length){\nthrow'aggregator id '+id.toString()+' not valid';\n}\n}\nstate.activeAggregators=ids.slice();\n// NB: evaluate root here because dirty bit is for children\n// so someone has to start with root, and it might as well be right away\nevaluateAggregate(state.root);\nvar sorter=noSortOrder;var _loop2=function _loop2(\n_i12){\nvar ascending=(ids[_i12]&ACTIVE_AGGREGATOR_ASC_BIT)!==0;\nvar id=ids[_i12]&ACTIVE_AGGREGATOR_MASK;\nvar comparer=state.aggregators[id].sorter;\nvar captureSorter=sorter;\nvar captureIndex=_i12;\nsorter=function sorter(a,b){\nvar c=comparer(a.aggregates[captureIndex],b.aggregates[captureIndex]);\nif(c===0){\nreturn captureSorter(a,b);\n}\nreturn ascending?-c:c;\n};};for(var _i12=ids.length-1;_i12>=0;_i12--){_loop2(_i12);\n}\nstate.sorter=sorter;\nstate.root.state|=NODE_REORDER_BIT;\n},\ngetActiveAggregators:function getActiveAggregators(){\nreturn state.activeAggregators.slice();\n},\ngetRows:function getRows(top,height){\nvar result=new Array(height);\nfor(var _i13=0;_i13<height;_i13++){\nresult[_i13]=null;\n}\ngetRowsImpl(state.root,top,height,result);\nreturn result;\n},\ngetRowLabel:function getRowLabel(row){\nreturn row.label;\n},\ngetRowIndent:function getRowIndent(row){\nreturn row.state>>>NODE_INDENT_SHIFT;\n},\ngetRowAggregate:function getRowAggregate(row,index){\nvar aggregator=state.aggregators[state.activeAggregators[index]];\nreturn aggregator.formatter(row.aggregates[index]);\n},\ngetHeight:function getHeight(){\nreturn state.root.height;\n},\ncanExpand:function canExpand(row){\nreturn(row.state&NODE_EXPANDED_BIT)===0&&row.expander!==INVALID_ACTIVE_EXPANDER;\n},\ncanContract:function canContract(row){\nreturn(row.state&NODE_EXPANDED_BIT)!==0;\n},\nexpand:function expand(row){\nif((row.state&NODE_EXPANDED_BIT)!==0){\nthrow'can not expand row, already expanded';\n}\nif(row.height!==1){\nthrow'unexpanded row has height '+row.height.toString()+' != 1';\n}\nif(row.children===null){// first expand, generate children\nvar activeIndex=row.expander&ACTIVE_EXPANDER_MASK;\nvar nextActiveIndex=activeIndex+1;// NB: if next is stack, frame is 0\nif(nextActiveIndex>=state.activeExpanders.length){\nnextActiveIndex=INVALID_ACTIVE_EXPANDER;\n}\nif(activeIndex>=state.activeExpanders.length){\nthrow'invalid active expander index '+activeIndex.toString();\n}\nvar exId=state.activeExpanders[activeIndex];\nif(exId>=FIELD_EXPANDER_ID_MIN&&\nexId<FIELD_EXPANDER_ID_MIN+state.fieldExpanders.length){\nvar expander=state.fieldExpanders[exId-FIELD_EXPANDER_ID_MIN];\naddChildrenWithFieldExpander(row,expander,nextActiveIndex);\n}else if(exId>=STACK_EXPANDER_ID_MIN&&\nexId<STACK_EXPANDER_ID_MIN+state.stackExpanders.length){\nvar depth=row.expander>>>ACTIVE_EXPANDER_FRAME_SHIFT;\nvar _expander=state.stackExpanders[exId-STACK_EXPANDER_ID_MIN];\naddChildrenWithStackExpander(row,_expander,activeIndex,depth,nextActiveIndex);\n}else{\nthrow'state.activeIndex '+activeIndex.toString()+\n' has invalid expander'+exId.toString();\n}\n}\nrow.state|=NODE_EXPANDED_BIT|\nNODE_REAGGREGATE_BIT|NODE_REORDER_BIT|NODE_REPOSITION_BIT;\nvar heightChange=0;\nfor(var _i14=0;_i14<row.children.length;_i14++){\nheightChange+=row.children[_i14].height;\n}\nupdateHeight(row,heightChange);\n// if children only contains one node, then expand it as well\nif(row.children.length===1&&this.canExpand(row.children[0])){\nthis.expand(row.children[0]);\n}\n},\ncontract:function contract(row){\ncontractRow(row);\n}};\n\n}// @generated\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/out/heapCapture.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n/*eslint no-console-disallow: \"off\"*/\n/*global React ReactDOM Table stringInterner stackRegistry aggrow preLoadedCapture:true*/\n\nfunction RefVisitor(refs,id){\nthis.refs=refs;\nthis.id=id;\n}\n\nRefVisitor.prototype={\nmoveToEdge:function moveToEdge(name){\nvar ref=this.refs[this.id];\nif(ref&&ref.edges){\nvar edges=ref.edges;\nfor(var edgeId in edges){\nif(edges[edgeId]===name){\nthis.id=edgeId;\nreturn this;\n}\n}\n}\nthis.id=undefined;\nreturn this;\n},\nmoveToFirst:function moveToFirst(callback){\nvar ref=this.refs[this.id];\nif(ref&&ref.edges){\nvar edges=ref.edges;\nfor(var edgeId in edges){\nthis.id=edgeId;\nif(callback(edges[edgeId],this)){\nreturn this;\n}\n}\n}\nthis.id=undefined;\nreturn this;\n},\nforEachEdge:function forEachEdge(callback){\nvar ref=this.refs[this.id];\nif(ref&&ref.edges){\nvar edges=ref.edges;\nvar visitor=new RefVisitor(this.refs,undefined);\nfor(var edgeId in edges){\nvisitor.id=edgeId;\ncallback(edges[edgeId],visitor);\n}\n}\n},\ngetType:function getType(){\nvar ref=this.refs[this.id];\nif(ref){\nreturn ref.type;\n}\nreturn undefined;\n},\ngetRef:function getRef(){\nreturn this.refs[this.id];\n},\nclone:function clone(){\nreturn new RefVisitor(this.refs,this.id);\n},\nisDefined:function isDefined(){\nreturn!!this.id;\n},\ngetValue:function getValue(){var _this=this;\nvar ref=this.refs[this.id];\nif(ref){\nif(ref.type==='string'){\nif(ref.value){\nreturn ref.value;\n}else{var _ret=function(){\nvar rope=[];\n_this.forEachEdge(function(name,visitor){\nif(name&&name.startsWith('[')&&name.endsWith(']')){\nvar index=parseInt(name.substring(1,name.length-1),10);\nrope[index]=visitor.getValue();\n}\n});\nreturn{v:rope.join('')};}();if(typeof _ret===\"object\")return _ret.v;\n}\n}else if(ref.type==='ScriptExecutable'||\nref.type==='EvalExecutable'||\nref.type==='ProgramExecutable'){\nreturn ref.value.url+':'+ref.value.line+':'+ref.value.col;\n}else if(ref.type==='FunctionExecutable'){\nreturn ref.value.name+'@'+ref.value.url+':'+ref.value.line+':'+ref.value.col;\n}else if(ref.type==='NativeExecutable'){\nreturn ref.value.function+' '+ref.value.constructor+' '+ref.value.name;\n}else if(ref.type==='Function'){\nvar executable=this.clone().moveToEdge('@Executable');\nif(executable.id){\nreturn executable.getRef().type+' '+executable.getValue();\n}\n}\n}\nreturn'#none';\n}};\n\n\nfunction forEachRef(refs,callback){\nvar visitor=new RefVisitor(refs,undefined);\nfor(var id in refs){\nvisitor.id=id;\ncallback(visitor);\n}\n}\n\nfunction firstRef(refs,callback){\nfor(var id in refs){\nvar ref=refs[id];\nif(callback(id,ref)){\nreturn new RefVisitor(refs,id);\n}\n}\nreturn new RefVisitor(refs,undefined);\n}\n\nfunction getInternalInstanceName(visitor){\nvar type=visitor.clone().moveToEdge('_currentElement').moveToEdge('type');\nif(type.getType()==='string'){// element.type is string\nreturn type.getValue();\n}else if(type.getType()==='Function'){// element.type is function\nvar displayName=type.clone().moveToEdge('displayName');\nif(displayName.isDefined()){\nreturn displayName.getValue();// element.type.displayName\n}\nvar name=type.clone().moveToEdge('name');\nif(name.isDefined()){\nreturn name.getValue();// element.type.name\n}\ntype.moveToEdge('@Executable');\nif(type.getType()==='FunctionExecutable'){\nreturn type.getRef().value.name;// element.type symbolicated name\n}\n}\nreturn'#unknown';\n}\n\nfunction buildReactComponentTree(visitor,registry){\nvar ref=visitor.getRef();\nif(ref.reactTree||ref.reactParent===undefined){\nreturn;// has one or doesn't need one\n}\nvar parentVisitor=ref.reactParent;\nif(parentVisitor===null){\nref.reactTree=registry.insert(registry.root,getInternalInstanceName(visitor));\n}else if(parentVisitor){\nvar parentRef=parentVisitor.getRef();\nbuildReactComponentTree(parentVisitor,registry);\nvar relativeName=getInternalInstanceName(visitor);\nif(ref.reactKey){\nrelativeName=ref.reactKey+': '+relativeName;\n}\nref.reactTree=registry.insert(parentRef.reactTree,relativeName);\n}else{\nthrow'non react instance parent of react instance';\n}\n}\n\nfunction markReactComponentTree(refs,registry){\n// annotate all refs that are react internal instances with their parent and name\n// ref.reactParent = visitor that points to parent instance,\n//   null if we know it's an instance, but don't have a parent yet\n// ref.reactKey = if a key is used to distinguish siblings\nforEachRef(refs,function(visitor){\nvar visitorClone=visitor.clone();// visitor will get stomped on next iteration\nvar ref=visitor.getRef();\nvisitor.forEachEdge(function(edgeName,edgeVisitor){\nvar edgeRef=edgeVisitor.getRef();\nif(edgeRef){\nif(edgeName==='_renderedChildren'){\nif(ref.reactParent===undefined){\n// ref is react component, even if we don't have a parent yet\nref.reactParent=null;\n}\nedgeVisitor.forEachEdge(function(childName,childVisitor){\nvar childRef=childVisitor.getRef();\nif(childRef&&childName.startsWith('.')){\nchildRef.reactParent=visitorClone;\nchildRef.reactKey=childName;\n}\n});\n}else if(edgeName==='_renderedComponent'){\nif(ref.reactParent===undefined){\nref.reactParent=null;\n}\nedgeRef.reactParent=visitorClone;\n}\n}\n});\n});\n// build tree of react internal instances (since that's what has the structure)\n// fill in ref.reactTree = path registry node\nforEachRef(refs,function(visitor){\nbuildReactComponentTree(visitor,registry);\n});\n// hook in components by looking at their _reactInternalInstance fields\nforEachRef(refs,function(visitor){\nvar ref=visitor.getRef();\nvar instanceRef=visitor.moveToEdge('_reactInternalInstance').getRef();\nif(instanceRef){\nref.reactTree=instanceRef.reactTree;\n}\n});\n}\n\nfunction functionUrlFileName(visitor){\nvar executable=visitor.clone().moveToEdge('@Executable');\nvar ref=executable.getRef();\nif(ref&&ref.value&&ref.value.url){\nvar url=ref.value.url;\nvar file=url.substring(url.lastIndexOf('/')+1);\nif(file.endsWith('.js')){\nfile=file.substring(0,file.length-3);\n}\nreturn file;\n}\nreturn undefined;\n}\n\nfunction markModules(refs){\nvar modules=firstRef(refs,function(id,ref){return ref.type==='CallbackGlobalObject';});\nmodules.moveToEdge('require');\nmodules.moveToFirst(function(name,visitor){return visitor.getType()==='JSActivation';});\nmodules.moveToEdge('modules');\nmodules.forEachEdge(function(name,visitor){\nvar ref=visitor.getRef();\nvisitor.moveToEdge('exports');\nif(visitor.getType()==='Object'){\nvisitor.moveToFirst(function(memberName,member){return member.getType()==='Function';});\nif(visitor.isDefined()){\nref.module=functionUrlFileName(visitor);\n}\n}else if(visitor.getType()==='Function'){\nvar displayName=visitor.clone().moveToEdge('displayName');\nif(displayName.isDefined()){\nref.module=displayName.getValue();\n}\nref.module=functionUrlFileName(visitor);\n}\nif(ref&&!ref.module){\nref.module='#unknown '+name;\n}\n});\n}\n\nfunction registerPathToRoot(refs,registry){\nmarkReactComponentTree(refs,registry);\nmarkModules(refs);\nvar breadth=[];\nforEachRef(refs,function(visitor){\nvar ref=visitor.getRef();\nif(ref.type==='CallbackGlobalObject'){\nref.rootPath=registry.insert(registry.root,ref.type);\nbreadth.push(visitor.clone());\n}\n});var _loop=function _loop(){\n\nvar nextBreadth=[];var _loop2=function _loop2(\ni){\nvar visitor=breadth[i];\nvar ref=visitor.getRef();\nvisitor.forEachEdge(function(edgeName,edgeVisitor){\nvar edgeRef=edgeVisitor.getRef();\nif(edgeRef&&edgeRef.rootPath===undefined){\nvar pathName=edgeRef.type;\nif(edgeName){\npathName=edgeName+': '+pathName;\n}\nedgeRef.rootPath=registry.insert(ref.rootPath,pathName);\nnextBreadth.push(edgeVisitor.clone());\n// copy module and react tree forward\nif(edgeRef.module===undefined){\nedgeRef.module=ref.module;\n}\nif(edgeRef.reactTree===undefined){\nedgeRef.reactTree=ref.reactTree;\n}\n}\n});};for(var i=0;i<breadth.length;i++){_loop2(i);\n}\nbreadth=nextBreadth;};while(breadth.length>0){_loop();\n}\n}\n\nfunction captureRegistry(){\nvar strings=stringInterner();\nvar stacks=stackRegistry(strings);\nvar data=new Int32Array(0);\n\nvar idField=0;\nvar typeField=1;\nvar sizeField=2;\nvar traceField=3;\nvar pathField=4;\nvar reactField=5;\nvar valueField=6;\nvar moduleField=7;\nvar numFields=8;\n\nreturn{\nstrings:strings,\nstacks:stacks,\ndata:data,\nregister:function registerCapture(captureId,capture){var _this2=this;\n// NB: capture.refs is potentially VERY large, so we try to avoid making\n// copies, even of iteration is a bit more annoying.\nvar rowCount=0;\nfor(var id in capture.refs){// eslint-disable-line no-unused-vars\nrowCount++;\n}\nfor(var _id in capture.markedBlocks){// eslint-disable-line no-unused-vars\nrowCount++;\n}\nconsole.log(\n'increasing row data from '+(this.data.length*4).toString()+'B to '+\n(this.data.length*4+rowCount*numFields*4).toString()+'B');\n\nvar newData=new Int32Array(this.data.length+rowCount*numFields);\nnewData.set(data);\nvar dataOffset=this.data.length;\nthis.data=null;\n\nregisterPathToRoot(capture.refs,this.stacks);\nvar internedCaptureId=this.strings.intern(captureId);\nvar noneString=this.strings.intern('#none');\nvar noneStack=this.stacks.insert(this.stacks.root,'#none');\nforEachRef(capture.refs,function(visitor){\nvar ref=visitor.getRef();\nvar id=visitor.id;\nnewData[dataOffset+idField]=parseInt(id,16);\nnewData[dataOffset+typeField]=_this2.strings.intern(ref.type);\nnewData[dataOffset+sizeField]=ref.size;\nnewData[dataOffset+traceField]=internedCaptureId;\nif(ref.rootPath===undefined){\nnewData[dataOffset+pathField]=noneStack.id;\n}else{\nnewData[dataOffset+pathField]=ref.rootPath.id;\n}\nif(ref.reactTree===undefined){\nnewData[dataOffset+reactField]=noneStack.id;\n}else{\nnewData[dataOffset+reactField]=ref.reactTree.id;\n}\nnewData[dataOffset+valueField]=_this2.strings.intern(visitor.getValue());\nif(ref.module){\nnewData[dataOffset+moduleField]=_this2.strings.intern(ref.module);\n}else{\nnewData[dataOffset+moduleField]=noneString;\n}\ndataOffset+=numFields;\n});\nfor(var _id2 in capture.markedBlocks){\nvar block=capture.markedBlocks[_id2];\nnewData[dataOffset+idField]=parseInt(_id2,16);\nnewData[dataOffset+typeField]=this.strings.intern('Marked Block Overhead');\nnewData[dataOffset+sizeField]=block.capacity-block.size;\nnewData[dataOffset+traceField]=internedCaptureId;\nnewData[dataOffset+pathField]=noneStack.id;\nnewData[dataOffset+reactField]=noneStack.id;\nnewData[dataOffset+valueField]=this.strings.intern(\n'capacity: '+block.capacity+\n', size: '+block.size+\n', granularity: '+block.cellSize);\n\nnewData[dataOffset+moduleField]=noneString;\ndataOffset+=numFields;\n}\nthis.data=newData;\n},\ngetAggrow:function getAggrow(){\nvar agStrings=this.strings;\nvar agStacks=this.stacks.flatten();\nvar agData=this.data;\nvar agNumRows=agData.length/numFields;\nvar ag=new aggrow(agStrings,agStacks,agNumRows);\n\nvar idExpander=ag.addFieldExpander('Id',\nfunction getId(row){\nvar id=agData[row*numFields+idField];\nif(id<0){\nid+=0x100000000;// data is int32, id is uint32\n}\nreturn'0x'+id.toString(16);\n},\nfunction compareAddress(rowA,rowB){\nreturn agData[rowA*numFields+idField]-agData[rowB*numFields+idField];\n});\n\nvar typeExpander=ag.addFieldExpander('Type',\nfunction getType(row){return agStrings.get(agData[row*numFields+typeField]);},\nfunction compareType(rowA,rowB){\nreturn agData[rowA*numFields+typeField]-agData[rowB*numFields+typeField];\n});\n\nvar sizeExpander=ag.addFieldExpander('Size',\nfunction getSize(row){return agData[row*numFields+sizeField].toString();},\nfunction compareSize(rowA,rowB){\nreturn agData[rowA*numFields+sizeField]-agData[rowB*numFields+sizeField];\n});\n\nvar traceExpander=ag.addFieldExpander('Trace',\nfunction getSize(row){return agStrings.get(agData[row*numFields+traceField]);},\nfunction compareSize(rowA,rowB){\nreturn agData[rowA*numFields+traceField]-agData[rowB*numFields+traceField];\n});\n\nvar pathExpander=ag.addCalleeStackExpander('Path',\nfunction getStack(row){return agStacks.get(agData[row*numFields+pathField]);});\n\nvar reactExpander=ag.addCalleeStackExpander('React Tree',\nfunction getStack(row){return agStacks.get(agData[row*numFields+reactField]);});\n\nvar valueExpander=ag.addFieldExpander('Value',\nfunction getValue(row){return agStrings.get(agData[row*numFields+valueField]);},\nfunction compareValue(rowA,rowB){\nreturn agData[rowA*numFields+valueField]-agData[rowB*numFields+valueField];\n});\n\nvar moduleExpander=ag.addFieldExpander('Module',\nfunction getModule(row){return agStrings.get(agData[row*numFields+moduleField]);},\nfunction compareModule(rowA,rowB){\nreturn agData[rowA*numFields+moduleField]-agData[rowB*numFields+moduleField];\n});\n\nvar sizeAggregator=ag.addAggregator('Size',\nfunction aggregateSize(indices){\nvar size=0;\nfor(var i=0;i<indices.length;i++){\nvar row=indices[i];\nsize+=agData[row*numFields+sizeField];\n}\nreturn size;\n},\nfunction formatSize(value){return value.toString();},\nfunction sortSize(a,b){return b-a;});\n\nvar countAggregator=ag.addAggregator('Count',\nfunction aggregateCount(indices){\nreturn indices.length;\n},\nfunction formatCount(value){return value.toString();},\nfunction sortCount(a,b){return b-a;});\n\nag.setActiveExpanders([\npathExpander,\nreactExpander,\nmoduleExpander,\ntypeExpander,\nidExpander,\ntraceExpander,\nvalueExpander,\nsizeExpander]);\n\nag.setActiveAggregators([sizeAggregator,countAggregator]);\nreturn ag;\n}};\n\n}\n\nif(preLoadedCapture){\nvar r=new captureRegistry();\nr.register('trace',preLoadedCapture);\npreLoadedCapture=undefined;// let GG clean up the capture\nReactDOM.render(React.createElement(Table,{aggrow:r.getAggrow()}),document.body);\n}// @generated\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/out/table.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n'use strict';\n/*eslint no-console-disallow: \"off\"*/\n/*global React:true*/\n\n// TODO:\n// selection and arrow keys for navigating\nvar _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if(\"value\"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};}();function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError(\"Cannot call a class as a function\");}}function _possibleConstructorReturn(self,call){if(!self){throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");}return call&&(typeof call===\"object\"||typeof call===\"function\")?call:self;}function _inherits(subClass,superClass){if(typeof superClass!==\"function\"&&superClass!==null){throw new TypeError(\"Super expression must either be null or a function, not \"+typeof superClass);}subClass.prototype=Object.create(superClass&&superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__=superClass;}\nvar rowHeight=20;\nvar treeIndent=16;var\n\nDraggable=function(_React$Component){_inherits(Draggable,_React$Component);// eslint-disable-line no-unused-vars\nfunction Draggable(props){_classCallCheck(this,Draggable);return _possibleConstructorReturn(this,Object.getPrototypeOf(Draggable).call(this,\nprops));\n}_createClass(Draggable,[{key:'render',value:function render()\n\n{\nvar id=this.props.id;\nfunction dragStart(e){\ne.dataTransfer.setData('text/plain',id);\n}\nreturn React.cloneElement(\nthis.props.children,\n{draggable:'true',onDragStart:dragStart});\n\n}}]);return Draggable;}(React.Component);\n\nDraggable.propTypes={\nchildren:React.PropTypes.element.isRequired,\nid:React.PropTypes.string.isRequired};var\n\n\nDropTarget=function(_React$Component2){_inherits(DropTarget,_React$Component2);// eslint-disable-line no-unused-vars\nfunction DropTarget(props){_classCallCheck(this,DropTarget);return _possibleConstructorReturn(this,Object.getPrototypeOf(DropTarget).call(this,\nprops));\n}_createClass(DropTarget,[{key:'render',value:function render()\n\n{\nvar thisId=this.props.id;\nvar dropFilter=this.props.dropFilter;\nvar dropAction=this.props.dropAction;\nreturn React.cloneElement(\nthis.props.children,\n{\nonDragOver:function onDragOver(e){\nvar sourceId=e.dataTransfer.getData('text/plain');\nif(dropFilter(sourceId)){\ne.preventDefault();\n}\n},\nonDrop:function onDrop(e){\nvar sourceId=e.dataTransfer.getData('text/plain');\nif(dropFilter(sourceId)){\ne.preventDefault();\ndropAction(sourceId,thisId);\n}\n}});\n\n\n}}]);return DropTarget;}(React.Component);\n\n\nDropTarget.propTypes={\nchildren:React.PropTypes.element.isRequired,\nid:React.PropTypes.string.isRequired,\ndropFilter:React.PropTypes.func.isRequired,\ndropAction:React.PropTypes.func.isRequired};var\n\n\nTableHeader=function(_React$Component3){_inherits(TableHeader,_React$Component3);\nfunction TableHeader(props){_classCallCheck(this,TableHeader);return _possibleConstructorReturn(this,Object.getPrototypeOf(TableHeader).call(this,\nprops));\n}_createClass(TableHeader,[{key:'render',value:function render()\n{\nvar aggrow=this.props.aggrow;\nvar aggregators=aggrow.getActiveAggregators();\nvar expanders=aggrow.getActiveExpanders();\nvar headers=[];\nfor(var i=0;i<aggregators.length;i++){\nvar name=aggrow.getAggregatorName(aggregators[i]);\nheaders.push(\nReact.createElement(DropTarget,{\nid:'aggregate:insert:'+i.toString(),\ndropFilter:function dropFilter(s){return s.startsWith('aggregate');},\ndropAction:this.props.dropAction},\n\nReact.createElement('div',{style:{\nwidth:'16px',\nheight:'inherit',\nbackgroundColor:'darkGray',\nflexShrink:'0'}})));\n\n\nheaders.push(React.createElement(Draggable,{id:'aggregate:active:'+i.toString()},\nReact.createElement('div',{style:{width:'128px',textAlign:'center',flexShrink:'0'}},name)));\n\n}\nheaders.push(\nReact.createElement(DropTarget,{\nid:'divider:insert',\ndropFilter:function dropFilter(s){return s.startsWith('aggregate')||s.startsWith('expander');},\ndropAction:this.props.dropAction},\n\nReact.createElement('div',{style:{\nwidth:'16px',\nheight:'inherit',\nbackgroundColor:'gold',\nflexShrink:'0'}})));\n\n\nfor(var _i=0;_i<expanders.length;_i++){\nvar _name=aggrow.getExpanderName(expanders[_i]);\nvar bg=_i%2===0?'white':'lightGray';\nheaders.push(React.createElement(Draggable,{id:'expander:active:'+_i.toString()},\nReact.createElement('div',{style:{\nwidth:'128px',\ntextAlign:'center',\nbackgroundColor:bg,\nflexShrink:'0'}},\n\n_name)));\n\n\nvar sep=_i+1<expanders.length?'->':'...';\nheaders.push(\nReact.createElement(DropTarget,{\nid:'expander:insert:'+(_i+1).toString(),\ndropFilter:function dropFilter(){return true;},\ndropAction:this.props.dropAction},\n\nReact.createElement('div',{style:{\nheight:'inherit',\nbackgroundColor:'darkGray',\nflexShrink:'0'}},\n\nsep)));\n\n\n\n}\nreturn(\nReact.createElement('div',{style:{\nwidth:'100%',\nheight:'26px',\ndisplay:'flex',\nflexDirection:'row',\nalignItems:'center',\nborderBottom:'2px solid black'}},\n\nheaders));\n\n\n}}]);return TableHeader;}(React.Component);\n\n\nTableHeader.propTypes={\naggrow:React.PropTypes.object.isRequired,\ndropAction:React.PropTypes.func.isRequired};var\n\n\nTable=function(_React$Component4){_inherits(Table,_React$Component4);// eslint-disable-line no-unused-vars\nfunction Table(props){_classCallCheck(this,Table);var _this4=_possibleConstructorReturn(this,Object.getPrototypeOf(Table).call(this,\nprops));\n_this4.state={\naggrow:props.aggrow,\nviewport:{top:0,height:100},\ncursor:0};return _this4;\n\n}_createClass(Table,[{key:'scroll',value:function scroll(\n\ne){\nvar viewport=e.target;\nvar top=Math.floor((viewport.scrollTop-viewport.clientHeight*1.0)/rowHeight);\nvar height=Math.ceil(viewport.clientHeight*3.0/rowHeight);\nif(top!==this.state.viewport.top||height!==this.state.viewport.height){\nthis.setState({viewport:{top:top,height:height}});\n}\n}},{key:'_contractRow',value:function _contractRow(\n\nrow){\nvar newCursor=this.state.cursor;\nif(newCursor>row.top&&newCursor<row.top+row.height){// in contracted section\nnewCursor=row.top;\n}else if(newCursor>=row.top+row.height){// below contracted section\nnewCursor-=row.height-1;\n}\nthis.state.aggrow.contract(row);\nthis.setState({cursor:newCursor});\nconsole.log('-'+row.top);\n}},{key:'_expandRow',value:function _expandRow(\n\nrow){\nvar newCursor=this.state.cursor;\nthis.state.aggrow.expand(row);\nif(newCursor>row.top){// below expanded section\nnewCursor+=row.height-1;\n}\nthis.setState({cursor:newCursor});\nconsole.log('+'+row.top);\n}},{key:'_keepCursorInViewport',value:function _keepCursorInViewport()\n\n\n\n{\nif(this._scrollDiv){\nvar cursor=this.state.cursor;\nvar scrollDiv=this._scrollDiv;\nif(cursor*rowHeight<scrollDiv.scrollTop+scrollDiv.clientHeight*0.1){\nscrollDiv.scrollTop=cursor*rowHeight-scrollDiv.clientHeight*0.1;\n}else if((cursor+1)*rowHeight>scrollDiv.scrollTop+scrollDiv.clientHeight*0.9){\nscrollDiv.scrollTop=(cursor+1)*rowHeight-scrollDiv.clientHeight*0.9;\n}\n}\n}},{key:'keydown',value:function keydown(\n\ne){\nvar aggrow=this.state.aggrow;\nvar cursor=this.state.cursor;\nvar row=aggrow.getRows(cursor,1)[0];\nswitch(e.keyCode){\ncase 38:// up\nif(cursor>0){\nthis.setState({cursor:cursor-1});\nthis._keepCursorInViewport();\n}\ne.preventDefault();\nbreak;\ncase 40:// down\nif(cursor<aggrow.getHeight()-1){\nthis.setState({cursor:cursor+1});\nthis._keepCursorInViewport();\n}\ne.preventDefault();\nbreak;\ncase 37:// left\nif(aggrow.canContract(row)){\nthis._contractRow(row);\n}else if(aggrow.getRowIndent(row)>0){\nvar indent=aggrow.getRowIndent(row)-1;\nwhile(aggrow.getRowIndent(row)>indent){\ncursor--;\nrow=aggrow.getRows(cursor,1)[0];\n}\nthis.setState({cursor:cursor});\nthis._keepCursorInViewport();\n}\ne.preventDefault();\nbreak;\ncase 39:// right\nif(aggrow.canExpand(row)){\nthis._expandRow(row);\n}else if(cursor<aggrow.getHeight()-1){\nthis.setState({cursor:cursor+1});\nthis._keepCursorInViewport();\n}\ne.preventDefault();\nbreak;}\n\n}},{key:'dropAction',value:function dropAction(\n\ns,d){\nvar aggrow=this.state.aggrow;\nconsole.log('dropped '+s+' to '+d);\nif(s.startsWith('aggregate:active:')){\nvar sIndex=parseInt(s.substr(17),10);\nvar dIndex=-1;\nvar active=aggrow.getActiveAggregators();\nvar dragged=active[sIndex];\nif(d.startsWith('aggregate:insert:')){\ndIndex=parseInt(d.substr(17),10);\n}else if(d==='divider:insert'){\ndIndex=active.length;\n}else{\nthrow'not allowed to drag '+s+' to '+d;\n}\nif(dIndex>sIndex){\ndIndex--;\n}\nactive.splice(sIndex,1);\nactive.splice(dIndex,0,dragged);\naggrow.setActiveAggregators(active);\nthis.setState({cursor:0});\n}else if(s.startsWith('expander:active:')){\nvar _sIndex=parseInt(s.substr(16),10);\nvar _dIndex=-1;\nvar _active=aggrow.getActiveExpanders();\nvar _dragged=_active[_sIndex];\nif(d.startsWith('expander:insert:')){\n_dIndex=parseInt(d.substr(16),10);\n}else if(d==='divider:insert'){\n_dIndex=0;\n}else{\nthrow'not allowed to drag '+s+' to '+d;\n}\nif(_dIndex>_sIndex){\n_dIndex--;\n}\n_active.splice(_sIndex,1);\n_active.splice(_dIndex,0,_dragged);\naggrow.setActiveExpanders(_active);\nthis.setState({cursor:0});\n}\n}},{key:'render',value:function render()\n\n{var _this5=this;\nreturn(\nReact.createElement('div',{style:{width:'100%',height:'100%',display:'flex',flexDirection:'column'}},\nReact.createElement(TableHeader,{aggrow:this.state.aggrow,dropAction:function dropAction(s,d){return _this5.dropAction(s,d);}}),\nReact.createElement('div',{\nstyle:{\nwidth:'100%',\nflexGrow:'1',\noverflow:'scroll'},\n\nonScroll:function onScroll(e){return _this5.scroll(e);},\nref:function ref(div){_this5._scrollDiv=div;}},\nReact.createElement('div',{style:{position:'relative'}},\nthis.renderVirtualizedRows()))));\n\n\n\n\n}},{key:'renderVirtualizedRows',value:function renderVirtualizedRows()\n\n{var _this6=this;\nvar aggrow=this.state.aggrow;\nvar viewport=this.state.viewport;\nvar rows=aggrow.getRows(viewport.top,viewport.height);\nreturn(\nReact.createElement('div',{style:{\nposition:'absolute',\nwidth:'100%',\nheight:(rowHeight*(aggrow.getHeight()+20)).toString()+'px'}},\n\nrows.map(function(child){return _this6.renderRow(child);})));\n\n\n}},{key:'renderRow',value:function renderRow(\n\nrow){var _this7=this;\nif(row===null){\nreturn null;\n}\nvar bg='lightGray';\nvar aggrow=this.state.aggrow;\nvar columns=[];\nvar rowText='';\nvar indent=4+aggrow.getRowIndent(row)*treeIndent;\nvar aggregates=aggrow.getActiveAggregators();\nif(row.parent!==null&&row.parent.expander%2===0){\nbg='white';\n}\nif(row.top===this.state.cursor){\nbg='lightblue';\n}\nfor(var i=0;i<aggregates.length;i++){\nvar aggregate=aggrow.getRowAggregate(row,i);\ncolumns.push(\nReact.createElement('div',{style:{\nwidth:'16px',\nheight:'inherit',\nbackgroundColor:'darkGray',\nflexShrink:'0'}}));\n\n\ncolumns.push(\nReact.createElement('div',{style:{\nwidth:'128px',\ntextAlign:'right',\nflexShrink:'0'}},\n\naggregate));\n\n\n}\ncolumns.push(\nReact.createElement('div',{style:{\nwidth:'16px',\nheight:'inherit',\nbackgroundColor:'gold',\nflexShrink:'0'}}));\n\n\nif(aggrow.canExpand(row)){\ncolumns.push(\nReact.createElement('div',{\nstyle:{\nmarginLeft:indent.toString()+'px',\nflexShrink:'0',\nwidth:'12px',\ntextAlign:'center',\nborder:'1px solid gray'},\n\nonClick:function onClick(){return _this7._expandRow(row);}},'+'));\n\n\n}else if(aggrow.canContract(row)){\ncolumns.push(\nReact.createElement('div',{\nstyle:{\nmarginLeft:indent.toString()+'px',\nflexShrink:'0',\nwidth:'12px',\ntextAlign:'center',\nborder:'1px solid gray'},\n\nonClick:function onClick(){return _this7._contractRow(row);}},'-'));\n\n\n}else{\ncolumns.push(\nReact.createElement('div',{\nstyle:{\nmarginLeft:indent.toString()+'px'}}));\n\n\n\n}\nrowText+=aggrow.getRowLabel(row);\ncolumns.push(\nReact.createElement('div',{style:{\nflexShrink:'0',\nwhiteSpace:'nowrap',\nmarginRight:'20px'}},\n\nrowText));\n\n\nreturn(\nReact.createElement('div',{\nkey:row.top,\nstyle:{\nposition:'absolute',\nheight:(rowHeight-1).toString()+'px',\ntop:(rowHeight*row.top).toString()+'px',\ndisplay:'flex',\nflexDirection:'row',\nalignItems:'center',\nbackgroundColor:bg,\nborderBottom:'1px solid gray'},\n\nonClick:function onClick(){\n_this7.setState({cursor:row.top});\n}},\ncolumns));\n\n\n}},{key:'componentDidMount',value:function componentDidMount()\n\n{\nthis.keydown=this.keydown.bind(this);\ndocument.body.addEventListener('keydown',this.keydown);\n}},{key:'componentWillUnmount',value:function componentWillUnmount()\n\n{\ndocument.body.removeEventListener('keydown',this.keydown);\n}}]);return Table;}(React.Component);// @generated\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/src/aggrow.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n/*eslint no-bitwise: \"off\"*/\n/*eslint no-console-disallow: \"off\"*/\n\n// TODO: future features\n// put in a module.exports\n// filtering / search\n// pivot around frames in the middle of a stack by callers / callees\n// graphing?\n\nfunction stringInterner() { // eslint-disable-line no-unused-vars\n  const strings = [];\n  const ids = {};\n  return {\n    intern: function internString(s) {\n      const find = ids[s];\n      if (find === undefined) {\n        const id = strings.length;\n        ids[s] = id;\n        strings.push(s);\n        return id;\n      } else {\n        return find;\n      }\n    },\n    get: function getString(id) {\n      return strings[id];\n    },\n  };\n}\n\nfunction stackData(stackIdMap, maxDepth) { // eslint-disable-line no-unused-vars\n  return {\n    maxDepth: maxDepth,\n    get: function getStack(id) {\n      return stackIdMap[id];\n    },\n  };\n}\n\nfunction stackRegistry(interner) { // eslint-disable-line no-unused-vars\n  return {\n    root: { id: 0 },\n    nodeCount: 1,\n    insert: function insertNode(parent, label) {\n      const labelId = interner.intern(label);\n      let node = parent[labelId];\n      if (node === undefined) {\n        node = { id: this.nodeCount };\n        this.nodeCount++;\n        parent[labelId] = node;\n      }\n      return node;\n    },\n    flatten: function flattenStacks() {\n      let stackFrameCount = 0;\n      function countStacks(tree, depth) {\n        let leaf = true;\n        for (const frameId in tree) {\n          if (frameId !== 'id') {\n            leaf = countStacks(tree[frameId], depth + 1);\n          }\n        }\n        if (leaf) {\n          stackFrameCount += depth;\n        }\n        return false;\n      }\n      countStacks(this.root, 0);\n      console.log('size needed to store stacks: ' + (stackFrameCount * 4).toString() + 'B');\n      const stackIdMap = new Array(this.nodeCount);\n      const stackArray = new Int32Array(stackFrameCount);\n      let maxStackDepth = 0;\n      stackFrameCount = 0;\n      function flattenStacksImpl(tree, stack) {\n        let childStack;\n        maxStackDepth = Math.max(maxStackDepth, stack.length);\n        for (const frameId in tree) {\n          if (frameId !== 'id') {\n            stack.push(Number(frameId));\n            childStack = flattenStacksImpl(tree[frameId], stack);\n            stack.pop();\n          }\n        }\n\n        const id = tree.id;\n        if (id < 0 || id >= stackIdMap.length || stackIdMap[id] !== undefined) {\n          throw 'invalid stack id!';\n        }\n\n        if (childStack !== undefined) {\n          // each child must have our stack as a prefix, so just use that\n          stackIdMap[id] = childStack.subarray(0, stack.length);\n        } else {\n          const newStack = stackArray.subarray(stackFrameCount, stackFrameCount + stack.length);\n          stackFrameCount += stack.length;\n          for (let i = 0; i < stack.length; i++) {\n            newStack[i] = stack[i];\n          }\n          stackIdMap[id] = newStack;\n        }\n        return stackIdMap[id];\n      }\n      flattenStacksImpl(this.root, []);\n\n      return new stackData(stackIdMap, maxStackDepth);\n    },\n  };\n}\n\nfunction aggrow(strings, stacks, numRows) { // eslint-disable-line no-unused-vars\n  // expander ID definitions\n  const FIELD_EXPANDER_ID_MIN       = 0x0000;\n  const FIELD_EXPANDER_ID_MAX       = 0x7fff;\n  const STACK_EXPANDER_ID_MIN       = 0x8000;\n  const STACK_EXPANDER_ID_MAX       = 0xffff;\n\n  // used for row.expander which reference state.activeExpanders (with frame index masked in)\n  const INVALID_ACTIVE_EXPANDER     = -1;\n  const ACTIVE_EXPANDER_MASK        = 0xffff;\n  const ACTIVE_EXPANDER_FRAME_SHIFT = 16;\n\n  // aggregator ID definitions\n  const AGGREGATOR_ID_MAX           = 0xffff;\n\n  // active aggragators can have sort order changed in the reference\n  const ACTIVE_AGGREGATOR_MASK      = 0xffff;\n  const ACTIVE_AGGREGATOR_ASC_BIT   = 0x10000;\n\n  // tree node state definitions\n  const NODE_EXPANDED_BIT           = 0x0001; // this row is expanded\n  const NODE_REAGGREGATE_BIT        = 0x0002; // children need aggregates\n  const NODE_REORDER_BIT            = 0x0004; // children need to be sorted\n  const NODE_REPOSITION_BIT         = 0x0008; // children need position\n  const NODE_INDENT_SHIFT           = 16;\n\n  function calleeFrameGetter(stack, depth) {\n    return stack[depth];\n  }\n\n  function callerFrameGetter(stack, depth) {\n    return stack[stack.length - depth - 1];\n  }\n\n  function createStackComparers(stackGetter, frameGetter) {\n    const comparers = new Array(stacks.maxDepth);\n    for (let depth = 0; depth < stacks.maxDepth; depth++) {\n      const captureDepth = depth; // NB: to capture depth per loop iteration\n      comparers[depth] = function calleeStackComparer(rowA, rowB) {\n        const a = stackGetter(rowA);\n        const b = stackGetter(rowB);\n        // NB: we put the stacks that are too short at the top,\n        // so they can be grouped into the '<exclusive>' bucket\n        if (a.length <= captureDepth && b.length <= captureDepth) {\n            return 0;\n        } else if (a.length <= captureDepth) {\n            return -1;\n        } else if (b.length <= captureDepth) {\n            return 1;\n        }\n        return frameGetter(a, captureDepth) - frameGetter(b, captureDepth);\n      };\n    }\n    return comparers;\n  }\n\n  function createTreeNode(parent, label, indices, expander) {\n    const indent = parent === null ? 0 : (parent.state >>> NODE_INDENT_SHIFT) + 1;\n    const state = NODE_REPOSITION_BIT |\n      NODE_REAGGREGATE_BIT |\n      NODE_REORDER_BIT |\n      (indent << NODE_INDENT_SHIFT);\n    return {\n      parent: parent,     // null if root\n      children: null,     // array of children nodes\n      label: label,       // string to show in UI\n      indices: indices,   // row indices under this node\n      aggregates: null,   // result of aggregate on indices\n      expander: expander, // index into state.activeExpanders\n      top: 0,             // y position of top row (in rows)\n      height: 1,          // number of rows including children\n      state: state,       // see NODE_* definitions above\n    };\n  }\n\n  function noSortOrder(a, b) {\n    return 0;\n  }\n\n  const indices = new Int32Array(numRows);\n  for (let i = 0; i < numRows; i++) {\n    indices[i] = i;\n  }\n\n  const state = {\n    fieldExpanders: [],     // tree expanders that expand on simple values\n    stackExpanders: [],     // tree expanders that expand stacks\n    activeExpanders: [],    // index into field or stack expanders, hierarchy of tree\n    aggregators: [],        // all available aggregators, might not be used\n    activeAggregators: [],  // index into aggregators, to actually compute\n    sorter: noSortOrder,    // compare function that uses sortOrder to sort row.children\n    root: createTreeNode(null, '<root>', indices, INVALID_ACTIVE_EXPANDER),\n  };\n\n  function evaluateAggregate(row) {\n    const activeAggregators = state.activeAggregators;\n    const aggregates = new Array(activeAggregators.length);\n    for (let j = 0; j < activeAggregators.length; j++) {\n      const aggregator = state.aggregators[activeAggregators[j]];\n      aggregates[j] = aggregator.aggregator(row.indices);\n    }\n    row.aggregates = aggregates;\n    row.state |= NODE_REAGGREGATE_BIT;\n  }\n\n  function evaluateAggregates(row) {\n    if ((row.state & NODE_EXPANDED_BIT) !== 0) {\n      const children = row.children;\n      for (let i = 0; i < children.length; i++) {\n        evaluateAggregate(children[i]);\n      }\n      row.state |= NODE_REORDER_BIT;\n    }\n    row.state ^= NODE_REAGGREGATE_BIT;\n  }\n\n  function evaluateOrder(row) {\n    if ((row.state & NODE_EXPANDED_BIT) !== 0) {\n      const children = row.children;\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i];\n        child.state |= NODE_REORDER_BIT;\n      }\n      children.sort(state.sorter);\n      row.state |= NODE_REPOSITION_BIT;\n    }\n    row.state ^= NODE_REORDER_BIT;\n  }\n\n  function evaluatePosition(row) {\n    if ((row.state & NODE_EXPANDED_BIT) !== 0) {\n      const children = row.children;\n      let childTop = row.top + 1;\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i];\n        if (child.top !== childTop) {\n          child.top = childTop;\n          child.state |= NODE_REPOSITION_BIT;\n        }\n        childTop += child.height;\n      }\n    }\n    row.state ^= NODE_REPOSITION_BIT;\n  }\n\n  function getRowsImpl(row, top, height, result) {\n    if ((row.state & NODE_REAGGREGATE_BIT) !== 0) {\n      evaluateAggregates(row);\n    }\n    if ((row.state & NODE_REORDER_BIT) !== 0) {\n      evaluateOrder(row);\n    }\n    if ((row.state & NODE_REPOSITION_BIT) !== 0) {\n      evaluatePosition(row);\n    }\n\n    if (row.top >= top && row.top < top + height) {\n      if (result[row.top - top] != null) {\n        throw 'getRows put more than one row at position ' + row.top + ' into result';\n      }\n      result[row.top - top] = row;\n    }\n    if ((row.state & NODE_EXPANDED_BIT) !== 0) {\n      const children = row.children;\n      for (let i = 0; i < children.length; i++) {\n        const child = children[i];\n        if (child.top < top + height && top < child.top + child.height) {\n          getRowsImpl(child, top, height, result);\n        }\n      }\n    }\n  }\n\n  function updateHeight(row, heightChange) {\n    while (row !== null) {\n      row.height += heightChange;\n      row.state |= NODE_REPOSITION_BIT;\n      row = row.parent;\n    }\n  }\n\n  function addChildrenWithFieldExpander(row, expander, nextActiveIndex) {\n    const rowIndices = row.indices;\n    const comparer = expander.comparer;\n    rowIndices.sort(comparer);\n    let begin = 0;\n    let end = 1;\n    row.children = [];\n    while (end < rowIndices.length) {\n      if (comparer(rowIndices[begin], rowIndices[end]) !== 0) {\n        row.children.push(createTreeNode(\n          row,\n          expander.name + ': ' + expander.formatter(rowIndices[begin]),\n          rowIndices.subarray(begin, end),\n          nextActiveIndex));\n        begin = end;\n      }\n      end++;\n    }\n    row.children.push(createTreeNode(\n      row,\n      expander.name + ': ' + expander.formatter(rowIndices[begin]),\n      rowIndices.subarray(begin, end),\n      nextActiveIndex));\n  }\n\n  function addChildrenWithStackExpander(row, expander, activeIndex, depth, nextActiveIndex) {\n    const rowIndices = row.indices;\n    const stackGetter = expander.stackGetter;\n    const frameGetter = expander.frameGetter;\n    const comparer = expander.comparers[depth];\n    const expandNextFrame = activeIndex | ((depth + 1) << ACTIVE_EXPANDER_FRAME_SHIFT);\n    rowIndices.sort(comparer);\n    let columnName = '';\n    if (depth === 0) {\n      columnName = expander.name + ': ';\n    }\n\n    // put all the too-short stacks under <exclusive>\n    let begin = 0;\n    let beginStack = null;\n    row.children = [];\n    while (begin < rowIndices.length) {\n      beginStack = stackGetter(rowIndices[begin]);\n      if (beginStack.length > depth) {\n        break;\n      }\n      begin++;\n    }\n    if (begin > 0) {\n      row.children.push(createTreeNode(\n        row,\n        columnName + '<exclusive>',\n        rowIndices.subarray(0, begin),\n        nextActiveIndex));\n    }\n    // aggregate the rest under frames\n    if (begin < rowIndices.length) {\n      let end = begin + 1;\n      while (end < rowIndices.length) {\n        const endStack = stackGetter(rowIndices[end]);\n        if (frameGetter(beginStack, depth) !== frameGetter(endStack, depth)) {\n          row.children.push(createTreeNode(\n            row,\n            columnName + strings.get(frameGetter(beginStack, depth)),\n            rowIndices.subarray(begin, end),\n            expandNextFrame));\n          begin = end;\n          beginStack = endStack;\n        }\n        end++;\n      }\n      row.children.push(createTreeNode(\n        row,\n        columnName + strings.get(frameGetter(beginStack, depth)),\n        rowIndices.subarray(begin, end),\n        expandNextFrame));\n    }\n  }\n\n  function contractRow(row) {\n      if ((row.state & NODE_EXPANDED_BIT) === 0) {\n        throw 'can not contract row, already contracted';\n      }\n      row.state ^= NODE_EXPANDED_BIT;\n      const heightChange = 1 - row.height;\n      updateHeight(row, heightChange);\n  }\n\n  function pruneExpanders(row, oldExpander, newExpander) {\n    row.state |= NODE_REPOSITION_BIT;\n    if (row.expander === oldExpander) {\n      row.state |= NODE_REAGGREGATE_BIT | NODE_REORDER_BIT | NODE_REPOSITION_BIT;\n      if ((row.state & NODE_EXPANDED_BIT) !== 0) {\n        contractRow(row);\n      }\n      row.children = null;\n      row.expander = newExpander;\n    } else {\n      row.state |= NODE_REPOSITION_BIT;\n      const children = row.children;\n      if (children != null) {\n        for (let i = 0; i < children.length; i++) {\n          const child = children[i];\n          pruneExpanders(child, oldExpander, newExpander);\n        }\n      }\n    }\n  }\n\n  return {\n    addFieldExpander: function addFieldExpander(name, formatter, comparer) {\n      if (FIELD_EXPANDER_ID_MIN + state.fieldExpanders.length >= FIELD_EXPANDER_ID_MAX) {\n        throw 'too many field expanders!';\n      }\n      state.fieldExpanders.push({\n        name: name, // name for column\n        formatter: formatter, // row index -> display string\n        comparer: comparer, // compares by two row indices\n      });\n      return FIELD_EXPANDER_ID_MIN + state.fieldExpanders.length - 1;\n    },\n    addCalleeStackExpander: function addCalleeStackExpander(name, stackGetter) {\n      if (STACK_EXPANDER_ID_MIN + state.fieldExpanders.length >= STACK_EXPANDER_ID_MAX) {\n        throw 'too many stack expanders!';\n      }\n      state.stackExpanders.push({\n        name: name, // name for column\n        stackGetter: stackGetter, // row index -> stack array\n        comparers: createStackComparers(stackGetter, calleeFrameGetter),  // depth -> comparer\n        frameGetter: calleeFrameGetter, // (stack, depth) -> string id\n      });\n      return STACK_EXPANDER_ID_MIN + state.stackExpanders.length - 1;\n    },\n    addCallerStackExpander: function addCallerStackExpander(name, stackGetter) {\n      if (STACK_EXPANDER_ID_MIN + state.fieldExpanders.length >= STACK_EXPANDER_ID_MAX) {\n        throw 'too many stack expanders!';\n      }\n      state.stackExpanders.push({\n        name: name,\n        stackGetter: stackGetter,\n        comparers: createStackComparers(stackGetter, callerFrameGetter),\n        frameGetter: callerFrameGetter,\n      });\n      return STACK_EXPANDER_ID_MIN + state.stackExpanders.length - 1;\n    },\n    getExpanders: function getExpanders() {\n      const expanders = [];\n      for (let i = 0; i < state.fieldExpanders.length; i++) {\n        expanders.push(FIELD_EXPANDER_ID_MIN + i);\n      }\n      for (let i = 0; i < state.stackExpanders.length; i++) {\n        expanders.push(STACK_EXPANDER_ID_MIN + i);\n      }\n      return expanders;\n    },\n    getExpanderName: function getExpanderName(id) {\n      if (id >= FIELD_EXPANDER_ID_MIN && id <= FIELD_EXPANDER_ID_MAX) {\n        return state.fieldExpanders[id - FIELD_EXPANDER_ID_MIN].name;\n      } else if (id >= STACK_EXPANDER_ID_MIN && id <= STACK_EXPANDER_ID_MAX) {\n        return state.stackExpanders[id - STACK_EXPANDER_ID_MIN].name;\n      }\n      throw 'Unknown expander ID ' + id.toString();\n    },\n    setActiveExpanders: function setActiveExpanders(ids) {\n      for (let i = 0; i < ids.length; i++) {\n        const id = ids[i];\n        if (id >= FIELD_EXPANDER_ID_MIN && id <= FIELD_EXPANDER_ID_MAX) {\n          if (id - FIELD_EXPANDER_ID_MIN >= state.fieldExpanders.length) {\n            throw 'field expander for id ' + id.toString() + ' does not exist!';\n          }\n        } else if (id >= STACK_EXPANDER_ID_MIN && id <= STACK_EXPANDER_ID_MAX) {\n          if (id - STACK_EXPANDER_ID_MIN >= state.stackExpanders.length) {\n            throw 'stack expander for id ' + id.toString() + ' does not exist!';\n          }\n        }\n      }\n      for (let i = 0; i < ids.length; i++) {\n        if (state.activeExpanders.length <= i) {\n          pruneExpanders(state.root, INVALID_ACTIVE_EXPANDER, i);\n          break;\n        } else if (ids[i] !== state.activeExpanders[i]) {\n          pruneExpanders(state.root, i, i);\n          break;\n        }\n      }\n      // TODO: if ids is prefix of activeExpanders, we need to make an expander invalid\n      state.activeExpanders = ids.slice();\n    },\n    getActiveExpanders: function getActiveExpanders() {\n      return state.activeExpanders.slice();\n    },\n    addAggregator: function addAggregator(name, aggregator, formatter, sorter) {\n      if (state.aggregators.length >= AGGREGATOR_ID_MAX) {\n        throw 'too many aggregators!';\n      }\n      state.aggregators.push({\n        name: name,             // name for column\n        aggregator: aggregator, // index array -> aggregate value\n        formatter: formatter,   // aggregate value -> display string\n        sorter: sorter,         // compare two aggregate values\n      });\n      return state.aggregators.length - 1;\n    },\n    getAggregators: function getAggregators() {\n      const aggregators = [];\n      for (let i = 0; i < state.aggregators.length; i++) {\n        aggregators.push(i);\n      }\n      return aggregators;\n    },\n    getAggregatorName: function getAggregatorName(id) {\n      return state.aggregators[id & ACTIVE_AGGREGATOR_MASK].name;\n    },\n    setActiveAggregators: function setActiveAggregators(ids) {\n      for (let i = 0; i < ids.length; i++) {\n        const id = ids[i] & ACTIVE_AGGREGATOR_MASK;\n        if (id < 0 || id > state.aggregators.length) {\n          throw 'aggregator id ' + id.toString() + ' not valid';\n        }\n      }\n      state.activeAggregators = ids.slice();\n      // NB: evaluate root here because dirty bit is for children\n      // so someone has to start with root, and it might as well be right away\n      evaluateAggregate(state.root);\n      let sorter = noSortOrder;\n      for (let i = ids.length - 1; i >= 0; i--) {\n        const ascending = (ids[i] & ACTIVE_AGGREGATOR_ASC_BIT) !== 0;\n        const id = ids[i] & ACTIVE_AGGREGATOR_MASK;\n        const comparer = state.aggregators[id].sorter;\n        const captureSorter = sorter;\n        const captureIndex = i;\n        sorter = function (a, b) {\n          const c = comparer(a.aggregates[captureIndex], b.aggregates[captureIndex]);\n          if (c === 0) {\n            return captureSorter(a, b);\n          }\n          return ascending ? -c : c;\n        };\n      }\n      state.sorter = sorter;\n      state.root.state |= NODE_REORDER_BIT;\n    },\n    getActiveAggregators: function getActiveAggregators() {\n      return state.activeAggregators.slice();\n    },\n    getRows: function getRows(top, height) {\n      const result = new Array(height);\n      for (let i = 0; i < height; i++) {\n        result[i] = null;\n      }\n      getRowsImpl(state.root, top, height, result);\n      return result;\n    },\n    getRowLabel: function getRowLabel(row) {\n      return row.label;\n    },\n    getRowIndent: function getRowIndent(row) {\n      return row.state >>> NODE_INDENT_SHIFT;\n    },\n    getRowAggregate: function getRowAggregate(row, index) {\n      const aggregator = state.aggregators[state.activeAggregators[index]];\n      return aggregator.formatter(row.aggregates[index]);\n    },\n    getHeight: function getHeight() {\n      return state.root.height;\n    },\n    canExpand: function canExpand(row) {\n      return (row.state & NODE_EXPANDED_BIT) === 0 && (row.expander !== INVALID_ACTIVE_EXPANDER);\n    },\n    canContract: function canContract(row) {\n      return (row.state & NODE_EXPANDED_BIT) !== 0;\n    },\n    expand: function expand(row) {\n      if ((row.state & NODE_EXPANDED_BIT) !== 0) {\n        throw 'can not expand row, already expanded';\n      }\n      if (row.height !== 1) {\n        throw 'unexpanded row has height ' + row.height.toString() + ' != 1';\n      }\n      if (row.children === null) {  // first expand, generate children\n        const activeIndex = row.expander & ACTIVE_EXPANDER_MASK;\n        let nextActiveIndex = activeIndex + 1;  // NB: if next is stack, frame is 0\n        if (nextActiveIndex >= state.activeExpanders.length) {\n          nextActiveIndex = INVALID_ACTIVE_EXPANDER;\n        }\n        if (activeIndex >= state.activeExpanders.length) {\n          throw 'invalid active expander index ' + activeIndex.toString();\n        }\n        const exId = state.activeExpanders[activeIndex];\n        if (exId >= FIELD_EXPANDER_ID_MIN &&\n            exId < FIELD_EXPANDER_ID_MIN + state.fieldExpanders.length) {\n          const expander = state.fieldExpanders[exId - FIELD_EXPANDER_ID_MIN];\n          addChildrenWithFieldExpander(row, expander, nextActiveIndex);\n        } else if (exId >= STACK_EXPANDER_ID_MIN &&\n            exId < STACK_EXPANDER_ID_MIN + state.stackExpanders.length) {\n          const depth = row.expander >>> ACTIVE_EXPANDER_FRAME_SHIFT;\n          const expander = state.stackExpanders[exId - STACK_EXPANDER_ID_MIN];\n          addChildrenWithStackExpander(row, expander, activeIndex, depth, nextActiveIndex);\n        } else {\n          throw 'state.activeIndex ' + activeIndex.toString()\n            + ' has invalid expander' + exId.toString();\n        }\n      }\n      row.state |= NODE_EXPANDED_BIT\n        | NODE_REAGGREGATE_BIT | NODE_REORDER_BIT | NODE_REPOSITION_BIT;\n      let heightChange = 0;\n      for (let i = 0; i < row.children.length; i++) {\n        heightChange += row.children[i].height;\n      }\n      updateHeight(row, heightChange);\n      // if children only contains one node, then expand it as well\n      if (row.children.length === 1 && this.canExpand(row.children[0])) {\n        this.expand(row.children[0]);\n      }\n    },\n    contract: function contract(row) {\n      contractRow(row);\n    },\n  };\n}\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/src/heapCapture.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n/*eslint no-console-disallow: \"off\"*/\n/*global React ReactDOM Table stringInterner stackRegistry aggrow preLoadedCapture:true*/\n\nfunction RefVisitor(refs, id) {\n  this.refs = refs;\n  this.id = id;\n}\n\nRefVisitor.prototype = {\n  moveToEdge: function moveToEdge(name) {\n    const ref = this.refs[this.id];\n    if (ref && ref.edges) {\n      const edges = ref.edges;\n      for (const edgeId in edges) {\n        if (edges[edgeId] === name) {\n          this.id = edgeId;\n          return this;\n        }\n      }\n    }\n    this.id = undefined;\n    return this;\n  },\n  moveToFirst: function moveToFirst(callback) {\n    const ref = this.refs[this.id];\n    if (ref && ref.edges) {\n      const edges = ref.edges;\n      for (const edgeId in edges) {\n        this.id = edgeId;\n        if (callback(edges[edgeId], this)) {\n          return this;\n        }\n      }\n    }\n    this.id = undefined;\n    return this;\n  },\n  forEachEdge: function forEachEdge(callback) {\n    const ref = this.refs[this.id];\n    if (ref && ref.edges) {\n      const edges = ref.edges;\n      const visitor = new RefVisitor(this.refs, undefined);\n      for (const edgeId in edges) {\n        visitor.id = edgeId;\n        callback(edges[edgeId], visitor);\n      }\n    }\n  },\n  getType: function getType() {\n    const ref = this.refs[this.id];\n    if (ref) {\n      return ref.type;\n    }\n    return undefined;\n  },\n  getRef: function getRef() {\n    return this.refs[this.id];\n  },\n  clone: function clone() {\n    return new RefVisitor(this.refs, this.id);\n  },\n  isDefined: function isDefined() {\n    return !!this.id;\n  },\n  getValue: function getValue() {\n    const ref = this.refs[this.id];\n    if (ref) {\n      if (ref.type === 'string') {\n        if (ref.value) {\n          return ref.value;\n        } else {\n          const rope = [];\n          this.forEachEdge((name, visitor) => {\n            if (name && name.startsWith('[') && name.endsWith(']')) {\n              const index = parseInt(name.substring(1, name.length - 1), 10);\n              rope[index] = visitor.getValue();\n            }\n          });\n          return rope.join('');\n        }\n      } else if (ref.type === 'ScriptExecutable'\n              || ref.type === 'EvalExecutable'\n              || ref.type === 'ProgramExecutable') {\n        return ref.value.url + ':' + ref.value.line + ':' + ref.value.col;\n      } else if (ref.type === 'FunctionExecutable') {\n        return ref.value.name + '@' + ref.value.url + ':' + ref.value.line + ':' + ref.value.col;\n      } else if (ref.type === 'NativeExecutable') {\n        return ref.value.function + ' ' + ref.value.constructor + ' ' + ref.value.name;\n      } else if (ref.type === 'Function') {\n        const executable = this.clone().moveToEdge('@Executable');\n        if (executable.id) {\n          return executable.getRef().type + ' ' + executable.getValue();\n        }\n      }\n    }\n    return '#none';\n  }\n};\n\nfunction forEachRef(refs, callback) {\n  const visitor = new RefVisitor(refs, undefined);\n  for (const id in refs) {\n    visitor.id = id;\n    callback(visitor);\n  }\n}\n\nfunction firstRef(refs, callback) {\n  for (const id in refs) {\n    const ref = refs[id];\n    if (callback(id, ref)) {\n      return new RefVisitor(refs, id);\n    }\n  }\n  return new RefVisitor(refs, undefined);\n}\n\nfunction getInternalInstanceName(visitor) {\n  const type = visitor.clone().moveToEdge('_currentElement').moveToEdge('type');\n  if (type.getType() === 'string') { // element.type is string\n    return type.getValue();\n  } else if (type.getType() === 'Function') { // element.type is function\n    const displayName = type.clone().moveToEdge('displayName');\n    if (displayName.isDefined()) {\n      return displayName.getValue(); // element.type.displayName\n    }\n    const name = type.clone().moveToEdge('name');\n    if (name.isDefined()) {\n      return name.getValue(); // element.type.name\n    }\n    type.moveToEdge('@Executable');\n    if (type.getType() === 'FunctionExecutable') {\n      return type.getRef().value.name;  // element.type symbolicated name\n    }\n  }\n  return '#unknown';\n}\n\nfunction buildReactComponentTree(visitor, registry) {\n  const ref = visitor.getRef();\n  if (ref.reactTree || ref.reactParent === undefined) {\n    return; // has one or doesn't need one\n  }\n  const parentVisitor = ref.reactParent;\n  if (parentVisitor === null) {\n    ref.reactTree = registry.insert(registry.root, getInternalInstanceName(visitor));\n  } else if (parentVisitor) {\n    const parentRef = parentVisitor.getRef();\n    buildReactComponentTree(parentVisitor, registry);\n    let relativeName = getInternalInstanceName(visitor);\n    if (ref.reactKey) {\n      relativeName = ref.reactKey + ': ' + relativeName;\n    }\n    ref.reactTree = registry.insert(parentRef.reactTree, relativeName);\n  } else {\n    throw 'non react instance parent of react instance';\n  }\n}\n\nfunction markReactComponentTree(refs, registry) {\n  // annotate all refs that are react internal instances with their parent and name\n  // ref.reactParent = visitor that points to parent instance,\n  //   null if we know it's an instance, but don't have a parent yet\n  // ref.reactKey = if a key is used to distinguish siblings\n  forEachRef(refs, (visitor) => {\n    const visitorClone = visitor.clone(); // visitor will get stomped on next iteration\n    const ref = visitor.getRef();\n    visitor.forEachEdge((edgeName, edgeVisitor) => {\n      const edgeRef = edgeVisitor.getRef();\n      if (edgeRef) {\n        if (edgeName === '_renderedChildren') {\n          if (ref.reactParent === undefined) {\n            // ref is react component, even if we don't have a parent yet\n            ref.reactParent = null;\n          }\n          edgeVisitor.forEachEdge((childName, childVisitor) => {\n            const childRef = childVisitor.getRef();\n            if (childRef && childName.startsWith('.')) {\n              childRef.reactParent = visitorClone;\n              childRef.reactKey = childName;\n            }\n          });\n        } else if (edgeName === '_renderedComponent') {\n          if (ref.reactParent === undefined) {\n            ref.reactParent = null;\n          }\n          edgeRef.reactParent = visitorClone;\n        }\n      }\n    });\n  });\n  // build tree of react internal instances (since that's what has the structure)\n  // fill in ref.reactTree = path registry node\n  forEachRef(refs, (visitor) => {\n    buildReactComponentTree(visitor, registry);\n  });\n  // hook in components by looking at their _reactInternalInstance fields\n  forEachRef(refs, (visitor) => {\n    const ref = visitor.getRef();\n    const instanceRef = visitor.moveToEdge('_reactInternalInstance').getRef();\n    if (instanceRef) {\n      ref.reactTree = instanceRef.reactTree;\n    }\n  });\n}\n\nfunction functionUrlFileName(visitor) {\n  const executable = visitor.clone().moveToEdge('@Executable');\n  const ref = executable.getRef();\n  if (ref && ref.value && ref.value.url) {\n    const url = ref.value.url;\n    let file = url.substring(url.lastIndexOf('/') + 1);\n    if (file.endsWith('.js')) {\n      file = file.substring(0, file.length - 3);\n    }\n    return file;\n  }\n  return undefined;\n}\n\nfunction markModules(refs) {\n  const modules = firstRef(refs, (id, ref) => ref.type === 'CallbackGlobalObject');\n  modules.moveToEdge('require');\n  modules.moveToFirst((name, visitor) => visitor.getType() === 'JSActivation');\n  modules.moveToEdge('modules');\n  modules.forEachEdge((name, visitor) => {\n    const ref = visitor.getRef();\n    visitor.moveToEdge('exports');\n    if (visitor.getType() === 'Object') {\n      visitor.moveToFirst((memberName, member) => member.getType() === 'Function');\n      if (visitor.isDefined()) {\n        ref.module = functionUrlFileName(visitor);\n      }\n    } else if (visitor.getType() === 'Function') {\n      const displayName = visitor.clone().moveToEdge('displayName');\n      if (displayName.isDefined()) {\n        ref.module = displayName.getValue();\n      }\n      ref.module = functionUrlFileName(visitor);\n    }\n    if (ref && !ref.module) {\n      ref.module = '#unknown ' + name;\n    }\n  });\n}\n\nfunction registerPathToRoot(refs, registry) {\n  markReactComponentTree(refs, registry);\n  markModules(refs);\n  let breadth = [];\n  forEachRef(refs, (visitor) => {\n    const ref = visitor.getRef();\n    if (ref.type === 'CallbackGlobalObject') {\n      ref.rootPath = registry.insert(registry.root, ref.type);\n      breadth.push(visitor.clone());\n    }\n  });\n  while (breadth.length > 0) {\n    const nextBreadth = [];\n    for (let i = 0; i < breadth.length; i++) {\n      const visitor = breadth[i];\n      const ref = visitor.getRef();\n      visitor.forEachEdge((edgeName, edgeVisitor) => {\n        const edgeRef = edgeVisitor.getRef();\n        if (edgeRef && edgeRef.rootPath === undefined) {\n          let pathName = edgeRef.type;\n          if (edgeName) {\n            pathName = edgeName + ': ' + pathName;\n          }\n          edgeRef.rootPath = registry.insert(ref.rootPath, pathName);\n          nextBreadth.push(edgeVisitor.clone());\n          // copy module and react tree forward\n          if (edgeRef.module === undefined) {\n            edgeRef.module = ref.module;\n          }\n          if (edgeRef.reactTree === undefined) {\n            edgeRef.reactTree = ref.reactTree;\n          }\n        }\n      });\n    }\n    breadth = nextBreadth;\n  }\n}\n\nfunction captureRegistry() {\n  const strings = stringInterner();\n  const stacks = stackRegistry(strings);\n  const data = new Int32Array(0);\n\n  const idField = 0;\n  const typeField = 1;\n  const sizeField = 2;\n  const traceField = 3;\n  const pathField = 4;\n  const reactField = 5;\n  const valueField = 6;\n  const moduleField = 7;\n  const numFields = 8;\n\n  return {\n    strings: strings,\n    stacks: stacks,\n    data: data,\n    register: function registerCapture(captureId, capture) {\n      // NB: capture.refs is potentially VERY large, so we try to avoid making\n      // copies, even of iteration is a bit more annoying.\n      let rowCount = 0;\n      for (const id in capture.refs) { // eslint-disable-line no-unused-vars\n        rowCount++;\n      }\n      for (const id in capture.markedBlocks) { // eslint-disable-line no-unused-vars\n        rowCount++;\n      }\n      console.log(\n        'increasing row data from ' + (this.data.length * 4).toString() + 'B to ' +\n        (this.data.length * 4 + rowCount * numFields * 4).toString() + 'B'\n      );\n      const newData = new Int32Array(this.data.length + rowCount * numFields);\n      newData.set(data);\n      let dataOffset = this.data.length;\n      this.data = null;\n\n      registerPathToRoot(capture.refs, this.stacks);\n      const internedCaptureId = this.strings.intern(captureId);\n      const noneString = this.strings.intern('#none');\n      const noneStack = this.stacks.insert(this.stacks.root, '#none');\n      forEachRef(capture.refs, (visitor) => {\n        const ref = visitor.getRef();\n        const id = visitor.id;\n        newData[dataOffset + idField] = parseInt(id, 16);\n        newData[dataOffset + typeField] = this.strings.intern(ref.type);\n        newData[dataOffset + sizeField] = ref.size;\n        newData[dataOffset + traceField] = internedCaptureId;\n        if (ref.rootPath === undefined) {\n          newData[dataOffset + pathField] = noneStack.id;\n        } else {\n          newData[dataOffset + pathField] = ref.rootPath.id;\n        }\n        if (ref.reactTree === undefined) {\n          newData[dataOffset + reactField] = noneStack.id;\n        } else {\n          newData[dataOffset + reactField] = ref.reactTree.id;\n        }\n        newData[dataOffset + valueField] = this.strings.intern(visitor.getValue());\n        if (ref.module) {\n          newData[dataOffset + moduleField] = this.strings.intern(ref.module);\n        } else {\n          newData[dataOffset + moduleField] = noneString;\n        }\n        dataOffset += numFields;\n      });\n      for (const id in capture.markedBlocks) {\n        const block = capture.markedBlocks[id];\n        newData[dataOffset + idField] = parseInt(id, 16);\n        newData[dataOffset + typeField] = this.strings.intern('Marked Block Overhead');\n        newData[dataOffset + sizeField] = block.capacity - block.size;\n        newData[dataOffset + traceField] = internedCaptureId;\n        newData[dataOffset + pathField] = noneStack.id;\n        newData[dataOffset + reactField] = noneStack.id;\n        newData[dataOffset + valueField] = this.strings.intern(\n          'capacity: ' + block.capacity +\n          ', size: ' + block.size +\n          ', granularity: ' + block.cellSize\n        );\n        newData[dataOffset + moduleField] = noneString;\n        dataOffset += numFields;\n      }\n      this.data = newData;\n    },\n    getAggrow: function getAggrow() {\n      const agStrings = this.strings;\n      const agStacks = this.stacks.flatten();\n      const agData = this.data;\n      const agNumRows = agData.length / numFields;\n      const ag = new aggrow(agStrings, agStacks, agNumRows);\n\n      const idExpander = ag.addFieldExpander('Id',\n        function getId(row) {\n          let id = agData[row * numFields + idField];\n          if (id < 0) {\n            id += 0x100000000; // data is int32, id is uint32\n          }\n          return '0x' + id.toString(16);\n        },\n        function compareAddress(rowA, rowB) {\n          return agData[rowA * numFields + idField] - agData[rowB * numFields + idField];\n        });\n\n      const typeExpander = ag.addFieldExpander('Type',\n        function getType(row) { return agStrings.get(agData[row * numFields + typeField]); },\n        function compareType(rowA, rowB) {\n          return agData[rowA * numFields + typeField] - agData[rowB * numFields + typeField];\n        });\n\n      const sizeExpander = ag.addFieldExpander('Size',\n        function getSize(row) { return agData[row * numFields + sizeField].toString(); },\n        function compareSize(rowA, rowB) {\n          return agData[rowA * numFields + sizeField] - agData[rowB * numFields + sizeField];\n        });\n\n      const traceExpander = ag.addFieldExpander('Trace',\n        function getSize(row) { return agStrings.get(agData[row * numFields + traceField]); },\n        function compareSize(rowA, rowB) {\n          return agData[rowA * numFields + traceField] - agData[rowB * numFields + traceField];\n        });\n\n      const pathExpander = ag.addCalleeStackExpander('Path',\n        function getStack(row) { return agStacks.get(agData[row * numFields + pathField]); });\n\n      const reactExpander = ag.addCalleeStackExpander('React Tree',\n        function getStack(row) { return agStacks.get(agData[row * numFields + reactField]); });\n\n      const valueExpander = ag.addFieldExpander('Value',\n        function getValue(row) { return agStrings.get(agData[row * numFields + valueField]); },\n        function compareValue(rowA, rowB) {\n          return agData[rowA * numFields + valueField] - agData[rowB * numFields + valueField];\n        });\n\n      const moduleExpander = ag.addFieldExpander('Module',\n        function getModule(row) { return agStrings.get(agData[row * numFields + moduleField]); },\n        function compareModule(rowA, rowB) {\n          return agData[rowA * numFields + moduleField] - agData[rowB * numFields + moduleField];\n        });\n\n      const sizeAggregator = ag.addAggregator('Size',\n        function aggregateSize(indices) {\n          let size = 0;\n          for (let i = 0; i < indices.length; i++) {\n            const row = indices[i];\n            size += agData[row * numFields + sizeField];\n          }\n          return size;\n        },\n        function formatSize(value) { return value.toString(); },\n        function sortSize(a, b) { return b - a; } );\n\n      const countAggregator = ag.addAggregator('Count',\n        function aggregateCount(indices) {\n          return indices.length;\n        },\n        function formatCount(value) { return value.toString(); },\n        function sortCount(a, b) { return b - a; } );\n\n      ag.setActiveExpanders([\n        pathExpander,\n        reactExpander,\n        moduleExpander,\n        typeExpander,\n        idExpander,\n        traceExpander,\n        valueExpander,\n        sizeExpander\n      ]);\n      ag.setActiveAggregators([sizeAggregator, countAggregator]);\n      return ag;\n    },\n  };\n}\n\nif (preLoadedCapture) {\n  const r = new captureRegistry();\n  r.register('trace', preLoadedCapture);\n  preLoadedCapture = undefined; // let GG clean up the capture\n  ReactDOM.render(<Table aggrow={r.getAggrow()} />, document.body);\n}\n"
  },
  {
    "path": "local-cli/server/middleware/heapCapture/src/table.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n'use strict';\n/*eslint no-console-disallow: \"off\"*/\n/*global React:true*/\n\n// TODO:\n// selection and arrow keys for navigating\n\nconst rowHeight = 20;\nconst treeIndent = 16;\n\nclass Draggable extends React.Component { // eslint-disable-line no-unused-vars\n  constructor(props) {\n    super(props);\n  }\n\n  render() {\n    const id = this.props.id;\n    function dragStart(e) {\n      e.dataTransfer.setData('text/plain', id);\n    }\n    return React.cloneElement(\n      this.props.children,\n      { draggable: 'true', onDragStart: dragStart }\n    );\n  }\n}\nDraggable.propTypes = {\n  children: React.PropTypes.element.isRequired,\n  id: React.PropTypes.string.isRequired,\n};\n\nclass DropTarget extends React.Component { // eslint-disable-line no-unused-vars\n  constructor(props) {\n    super(props);\n  }\n\n  render() {\n    const thisId = this.props.id;\n    const dropFilter = this.props.dropFilter;\n    const dropAction = this.props.dropAction;\n    return React.cloneElement(\n      this.props.children,\n      {\n        onDragOver: (e) => {\n          const sourceId = e.dataTransfer.getData('text/plain');\n          if (dropFilter(sourceId)) {\n            e.preventDefault();\n          }\n        },\n        onDrop: (e) => {\n          const sourceId = e.dataTransfer.getData('text/plain');\n          if (dropFilter(sourceId)) {\n            e.preventDefault();\n            dropAction(sourceId, thisId);\n          }\n        },\n      }\n    );\n  }\n}\n\nDropTarget.propTypes = {\n  children: React.PropTypes.element.isRequired,\n  id: React.PropTypes.string.isRequired,\n  dropFilter: React.PropTypes.func.isRequired,\n  dropAction: React.PropTypes.func.isRequired,\n};\n\nclass TableHeader extends React.Component {\n  constructor(props) {\n    super(props);\n  }\n  render() {\n    const aggrow = this.props.aggrow;\n    const aggregators = aggrow.getActiveAggregators();\n    const expanders = aggrow.getActiveExpanders();\n    const headers = [];\n    for (let i = 0; i < aggregators.length; i++) {\n      const name = aggrow.getAggregatorName(aggregators[i]);\n      headers.push((\n        <DropTarget\n          id={'aggregate:insert:' + i.toString()}\n          dropFilter={(s) => s.startsWith('aggregate')}\n          dropAction={this.props.dropAction}\n        >\n          <div style={{\n            width: '16px',\n            height: 'inherit',\n            backgroundColor: 'darkGray',\n            flexShrink: '0' }}\n          ></div>\n        </DropTarget>));\n      headers.push((<Draggable id={'aggregate:active:' + i.toString()}>\n          <div style={{ width: '128px', textAlign: 'center', flexShrink: '0' }}>{name}</div>\n        </Draggable>));\n    }\n    headers.push((\n      <DropTarget\n        id=\"divider:insert\"\n        dropFilter={(s) => s.startsWith('aggregate') || s.startsWith('expander')}\n        dropAction={this.props.dropAction}\n      >\n        <div style={{\n          width: '16px',\n          height: 'inherit',\n          backgroundColor: 'gold',\n          flexShrink: '0'\n        }}></div>\n      </DropTarget>));\n    for (let i = 0; i < expanders.length; i++) {\n      const name = aggrow.getExpanderName(expanders[i]);\n      const bg = (i % 2 === 0) ? 'white' : 'lightGray';\n      headers.push((<Draggable id={'expander:active:' + i.toString()}>\n          <div style={{\n            width: '128px',\n            textAlign: 'center',\n            backgroundColor: bg,\n            flexShrink: '0'\n          }}>\n            {name}\n          </div>\n        </Draggable>));\n      const sep = i + 1 < expanders.length ? '->' : '...';\n      headers.push((\n        <DropTarget\n          id={'expander:insert:' + (i + 1).toString()}\n          dropFilter={()=>{return true; }}\n          dropAction={this.props.dropAction}\n        >\n          <div style={{\n            height: 'inherit',\n            backgroundColor: 'darkGray',\n            flexShrink: '0'\n          }}>\n            {sep}\n          </div>\n        </DropTarget>)\n      );\n    }\n    return (\n      <div style={{\n        width: '100%',\n        height: '26px',\n        display: 'flex',\n        flexDirection: 'row',\n        alignItems: 'center',\n        borderBottom: '2px solid black',\n      }}>\n        {headers}\n      </div>\n    );\n  }\n}\n\nTableHeader.propTypes = {\n  aggrow: React.PropTypes.object.isRequired,\n  dropAction: React.PropTypes.func.isRequired,\n};\n\nclass Table extends React.Component { // eslint-disable-line no-unused-vars\n  constructor(props) {\n    super(props);\n    this.state = {\n      aggrow: props.aggrow,\n      viewport: { top: 0, height: 100 },\n      cursor: 0,\n    };\n  }\n\n  scroll(e) {\n    const viewport = e.target;\n    const top = Math.floor((viewport.scrollTop - viewport.clientHeight * 1.0) / rowHeight);\n    const height = Math.ceil(viewport.clientHeight * 3.0 / rowHeight);\n    if (top !== this.state.viewport.top || height !== this.state.viewport.height) {\n      this.setState({viewport: {top, height}});\n    }\n  }\n\n  _contractRow(row) {\n    let newCursor = this.state.cursor;\n    if (newCursor > row.top && newCursor < row.top + row.height) { // in contracted section\n      newCursor = row.top;\n    } else if (newCursor >= row.top + row.height) { // below contracted section\n      newCursor -= row.height - 1;\n    }\n    this.state.aggrow.contract(row);\n    this.setState({cursor: newCursor});\n    console.log('-' + row.top);\n  }\n\n  _expandRow(row) {\n    let newCursor = this.state.cursor;\n    this.state.aggrow.expand(row);\n    if (newCursor > row.top) {  // below expanded section\n      newCursor += row.height - 1;\n    }\n    this.setState({cursor: newCursor});\n    console.log('+' + row.top);\n  }\n\n  _scrollDiv: null;\n\n  _keepCursorInViewport() {\n    if (this._scrollDiv) {\n      const cursor = this.state.cursor;\n      const scrollDiv = this._scrollDiv;\n      if (cursor * rowHeight < scrollDiv.scrollTop + scrollDiv.clientHeight * 0.1) {\n        scrollDiv.scrollTop = cursor * rowHeight - scrollDiv.clientHeight * 0.1;\n      } else if ((cursor + 1) * rowHeight > scrollDiv.scrollTop + scrollDiv.clientHeight * 0.9) {\n        scrollDiv.scrollTop = (cursor + 1) * rowHeight - scrollDiv.clientHeight * 0.9;\n      }\n    }\n  }\n\n  keydown(e) {\n    const aggrow = this.state.aggrow;\n    let cursor = this.state.cursor;\n    let row = aggrow.getRows(cursor, 1)[0];\n    switch (e.keyCode) {\n      case 38: // up\n        if (cursor > 0) {\n          this.setState({cursor: cursor - 1});\n          this._keepCursorInViewport();\n        }\n        e.preventDefault();\n        break;\n      case 40: // down\n        if (cursor < aggrow.getHeight() - 1) {\n          this.setState({cursor: cursor + 1});\n          this._keepCursorInViewport();\n        }\n        e.preventDefault();\n        break;\n      case 37: // left\n        if (aggrow.canContract(row)) {\n          this._contractRow(row);\n        } else if (aggrow.getRowIndent(row) > 0) {\n          const indent = aggrow.getRowIndent(row) - 1;\n          while (aggrow.getRowIndent(row) > indent) {\n            cursor--;\n            row = aggrow.getRows(cursor, 1)[0];\n          }\n          this.setState({cursor: cursor});\n          this._keepCursorInViewport();\n        }\n        e.preventDefault();\n        break;\n      case 39: // right\n        if (aggrow.canExpand(row)) {\n          this._expandRow(row);\n        } else if (cursor < aggrow.getHeight() - 1) {\n          this.setState({cursor: cursor + 1});\n          this._keepCursorInViewport();\n        }\n        e.preventDefault();\n        break;\n    }\n  }\n\n  dropAction(s, d) {\n    const aggrow = this.state.aggrow;\n    console.log('dropped ' + s + ' to ' + d);\n    if (s.startsWith('aggregate:active:')) {\n      const sIndex = parseInt(s.substr(17), 10);\n      let dIndex = -1;\n      const active = aggrow.getActiveAggregators();\n      const dragged = active[sIndex];\n      if (d.startsWith('aggregate:insert:')) {\n        dIndex = parseInt(d.substr(17), 10);\n      } else if (d === 'divider:insert') {\n        dIndex = active.length;\n      } else {\n        throw 'not allowed to drag ' + s + ' to ' + d;\n      }\n      if (dIndex > sIndex) {\n        dIndex--;\n      }\n      active.splice(sIndex, 1);\n      active.splice(dIndex, 0, dragged);\n      aggrow.setActiveAggregators(active);\n      this.setState({cursor:0});\n    } else if (s.startsWith('expander:active:')) {\n      const sIndex = parseInt(s.substr(16), 10);\n      let dIndex = -1;\n      const active = aggrow.getActiveExpanders();\n      const dragged = active[sIndex];\n      if (d.startsWith('expander:insert:')) {\n        dIndex = parseInt(d.substr(16), 10);\n      } else if (d === 'divider:insert') {\n        dIndex = 0;\n      } else {\n        throw 'not allowed to drag ' + s + ' to ' + d;\n      }\n      if (dIndex > sIndex) {\n        dIndex--;\n      }\n      active.splice(sIndex, 1);\n      active.splice(dIndex, 0, dragged);\n      aggrow.setActiveExpanders(active);\n      this.setState({cursor:0});\n    }\n  }\n\n  render() {\n    return (\n      <div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column' }}>\n        <TableHeader aggrow={this.state.aggrow} dropAction={(s, d) => this.dropAction(s, d)} />\n        <div\n          style={{\n            width: '100%',\n            flexGrow: '1',\n            overflow: 'scroll'\n          }}\n          onScroll={ (e) => this.scroll(e) }\n          ref={(div) => { this._scrollDiv = div; } }>\n          <div style={{ position: 'relative' }}>\n            { this.renderVirtualizedRows() }\n          </div>\n        </div>\n      </div>\n    );\n  }\n\n  renderVirtualizedRows() {\n    const aggrow = this.state.aggrow;\n    const viewport = this.state.viewport;\n    const rows = aggrow.getRows(viewport.top, viewport.height);\n    return (\n      <div style={{\n        position: 'absolute',\n        width: '100%',\n        height: (rowHeight * (aggrow.getHeight() + 20)).toString() + 'px'\n      }}>\n        { rows.map(child => this.renderRow(child)) }\n      </div>\n    );\n  }\n\n  renderRow(row) {\n    if (row === null) {\n      return null;\n    }\n    let bg = 'lightGray';\n    const aggrow = this.state.aggrow;\n    const columns = [];\n    let rowText = '';\n    const indent = 4 + aggrow.getRowIndent(row) * treeIndent;\n    const aggregates = aggrow.getActiveAggregators();\n    if (row.parent !== null && (row.parent.expander % 2 === 0)) {\n      bg = 'white';\n    }\n    if (row.top === this.state.cursor) {\n      bg = 'lightblue';\n    }\n    for (let i = 0; i < aggregates.length; i++) {\n      var aggregate = aggrow.getRowAggregate(row, i);\n      columns.push((\n        <div style={{\n          width: '16px',\n          height: 'inherit',\n          backgroundColor: 'darkGray',\n          flexShrink: '0'\n        }}></div>\n      ));\n      columns.push((\n        <div style={{\n          width: '128px',\n          textAlign: 'right',\n          flexShrink: '0'\n        }}>\n          {aggregate}\n        </div>\n      ));\n    }\n    columns.push((\n      <div style={{\n        width: '16px',\n        height: 'inherit',\n        backgroundColor: 'gold',\n        flexShrink: '0'\n      }}></div>\n    ));\n    if (aggrow.canExpand(row)) {\n      columns.push((\n        <div\n          style={{\n            marginLeft: indent.toString() + 'px',\n            flexShrink: '0',\n            width: '12px',\n            textAlign: 'center',\n            border: '1px solid gray',\n          }}\n          onClick={ () => this._expandRow(row) }\n        >+</div>\n      ));\n    } else if (aggrow.canContract(row)) {\n      columns.push((\n        <div\n          style={{\n            marginLeft: indent.toString() + 'px',\n            flexShrink: '0',\n            width: '12px',\n            textAlign: 'center',\n            border: '1px solid gray',\n          }}\n          onClick={ () => this._contractRow(row) }\n        >-</div>\n      ));\n    } else {\n      columns.push((\n        <div\n          style={{\n            marginLeft: indent.toString() + 'px',\n          }}\n        ></div>\n      ));\n    }\n    rowText += aggrow.getRowLabel(row);\n    columns.push((\n      <div style={{\n        flexShrink: '0',\n        whiteSpace: 'nowrap',\n        marginRight: '20px'\n      }}>\n        {rowText}\n      </div>\n    ));\n    return (\n      <div\n        key={row.top}\n        style={{\n          position: 'absolute',\n          height: (rowHeight - 1).toString() + 'px',\n          top: (rowHeight * row.top).toString() + 'px',\n          display: 'flex',\n          flexDirection: 'row',\n          alignItems: 'center',\n          backgroundColor: bg,\n          borderBottom: '1px solid gray',\n        }}\n        onClick={ () => {\n          this.setState({cursor: row.top});\n        }}>\n        {columns}\n      </div>\n    );\n  }\n\n  componentDidMount() {\n    this.keydown = this.keydown.bind(this);\n    document.body.addEventListener('keydown', this.keydown);\n  }\n\n  componentWillUnmount() {\n    document.body.removeEventListener('keydown', this.keydown);\n  }\n}\n"
  },
  {
    "path": "local-cli/server/middleware/heapCaptureMiddleware.js",
    "content": "/**\n * Copyright (c) 2016-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n/*eslint no-console-disallow: \"off\"*/\n\nconst spawn = require('child_process').spawn;\nconst fs = require('fs');\nconst path = require('path');\nconst http = require('http');\nconst urlLib = require('url');\nconst SourceMapConsumer = require('source-map').SourceMapConsumer;\n\n\n// url: string\n// onSuccess: function (SourceMapConsumer)\n// onFailure: function (string)\nfunction getSourceMapForUrl(url, onFailure, onSuccess) {\n  if (!url) {\n    onFailure('must provide a URL');\n    return;\n  }\n\n  if (url === 'assets://default_bundle') {\n    onFailure('Don\\'t know how to symbolicate in-app bundle, please load from server');\n    return;\n  }\n\n  const parsedUrl = urlLib.parse(url);\n  const mapPath = parsedUrl.pathname.replace(/\\.bundle$/, '.map');\n  const options = {\n    host: 'localhost',\n    port: parsedUrl.port,\n    path: mapPath + parsedUrl.search + '&babelSourcemap=true',\n  };\n\n  http.get(options, (res) => {\n    res.setEncoding('utf8');\n    let sawEnd = false;\n    let resBody = '';\n    res.on('data', (chunk) => {\n      resBody += chunk;\n    }).on('end', () => {\n      sawEnd = true;\n      onSuccess(new SourceMapConsumer(resBody));\n    }).on('close', (err) => {\n      if (!sawEnd) {\n        onFailure('Connection terminated prematurely because of: '\n                      + err.code + ' for url: ' + url);\n      }\n    });\n  }).on('error', (err) => {\n    onFailure('Could not get response from: ' + url + ', error: ' + err.message);\n  });\n}\n\n// capture: capture object\n// onSuccess: function (Map of url -> SourceMapConsumer)\n// onFailure: function (string)\nfunction getSourceMapsForCapture(capture, onFailure, onSuccess) {\n  const urls = new Set();\n  const sourcemaps = new Map();\n  for (const id in capture.refs) {\n    const ref = capture.refs[id];\n    if ((ref.type === 'ScriptExecutable' ||\n        ref.type === 'EvalExecutable' ||\n        ref.type === 'ProgramExecutable' ||\n        ref.type === 'FunctionExecutable') && ref.value.url) {\n      urls.add(ref.value.url);\n    }\n  }\n  urls.forEach((url) => {\n    getSourceMapForUrl(url, onFailure, (sourcemap) => {\n      sourcemaps.set(url, sourcemap);\n      urls.delete(url);\n      if (urls.size === 0) {\n        onSuccess(sourcemaps);\n      }\n    });\n  });\n  if (urls.size === 0) {\n    console.warn('No source information found in capture');\n    onSuccess(sourcemaps);\n  }\n}\n\n// capture: capture object\n// onSuccess: function (capture object)\n// onFailure: function (string)\nfunction symbolicateHeapCaptureFunctions(capture, onFailure, onSuccess) {\n  getSourceMapsForCapture(capture, onFailure, (sourcemaps) => {\n    for (const id in capture.refs) {\n      const ref = capture.refs[id];\n      if (ref.type === 'ScriptExecutable' ||\n          ref.type === 'EvalExecutable' ||\n          ref.type === 'ProgramExecutable' ||\n          ref.type === 'FunctionExecutable') {\n        const sourcemap = sourcemaps.get(ref.value.url);\n        if (sourcemap) {\n          const original = sourcemap.originalPositionFor({\n            line: ref.value.line,\n            column: ref.value.col,\n          });\n          if (original.name) {\n            ref.value.name = original.name;\n          } else if (!ref.value.name) {\n            ref.value.name = path.posix.basename(original.source) + ':' + original.line;\n          }\n          ref.value.url = original.source;\n          ref.value.line = original.line;\n          ref.value.col = original.column;\n        }\n      }\n    }\n    onSuccess(capture);\n  });\n}\n\nmodule.exports = function(req, res, next) {\n  if (req.url !== '/jscheapcaptureupload') {\n    next();\n    return;\n  }\n\n  console.log('symbolicating Heap Capture');\n  symbolicateHeapCaptureFunctions(JSON.parse(req.rawBody), (err) => {\n      console.error('Error when symbolicating: ' + err);\n    },\n    (capture) => {\n      res.end();\n      const preload = path.join(__dirname, 'heapCapture/preLoadedCapture.js');\n      fs.writeFileSync(preload, 'var preLoadedCapture = ');\n      fs.appendFileSync(preload, JSON.stringify(capture));\n      fs.appendFileSync(preload, ';');\n      const captureDir = path.join(__dirname, 'heapCapture/captures');\n      if (!fs.existsSync(captureDir)) {\n        fs.mkdirSync(captureDir);\n      }\n      console.log('Packaging Trace');\n      var captureHtml = captureDir + '/capture_' + Date.now() + '.html';\n      var capture = fs.createWriteStream(captureHtml);\n      var inliner = spawn(\n        'inliner',\n        ['--nocompress', 'heapCapture.html'],\n        { cwd: path.join(__dirname, '/heapCapture/'),\n          stdio: [ process.stdin, 'pipe', process.stderr ],\n        });\n      inliner.stdout.pipe(capture);\n      inliner.on('error', (err) => {\n        console.error('Error processing heap capture: ' + err.message);\n        console.error('make sure you have installed inliner with \\'npm install inliner -g\\'');\n      });\n      inliner.on('exit', (code, signal) => {\n        if (code === 0) {\n          console.log('Heap capture written to: ' + captureHtml);\n        } else {\n          console.error('Error processing heap capture, inliner returned code: ' + code);\n        }\n      });\n    }\n  );\n};\n"
  },
  {
    "path": "local-cli/server/middleware/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>React Native</title>\n</head>\n<body>\n  <p>React Native packager is running.</p>\n  <p><a href=\"http://facebook.github.io/react-native/\">Visit documentation</a></p>\n</body>\n</html>\n"
  },
  {
    "path": "local-cli/server/middleware/indexPage.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\n\nmodule.exports = function(req, res, next) {\n  if (req.url === '/') {\n    res.end(fs.readFileSync(path.join(__dirname, 'index.html')));\n  } else {\n    next();\n  }\n};\n"
  },
  {
    "path": "local-cli/server/middleware/jscProfilerMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst SourceMapConsumer = require('source-map').SourceMapConsumer;\nconst fs = require('fs');\nconst http = require('http');\nconst path = require('path');\nconst urlLib = require('url');\n\nclass TreeTransformator {\n  constructor() {\n    this.urlResults = {};\n  }\n\n  transform(tree, callback) {\n    this.afterUrlsCacheBuild(tree, () => {\n      callback(this.transformNode(tree));\n    });\n  }\n\n  // private\n  transformNode(tree) {\n    if (tree.url in this.urlResults) {\n      const original = this.urlResults[tree.url].originalPositionFor({\n        line: tree.lineNumber,\n        column: tree.columnNumber,\n      });\n      tree.functionName = original.name\n        || (path.posix.basename(original.source || '') + ':' + original.line);\n      tree.scriptId = tree.id;\n      tree.url = 'file://' + original.source;\n      tree.lineNumber = original.line;\n      tree.columnNumber = original.column;\n    } else if (tree.deoptReason === 'outside_vm') {\n      tree.functionName = 'OUTSIDE VM';\n    }\n    tree.children = tree.children.map((t) => this.transformNode(t));\n    return tree;\n  }\n\n  // private\n  afterUrlsCacheBuild(tree, callback) {\n    let urls = new Set();\n    this.gatherUrls(tree, urls);\n\n    let size = urls.size;\n    if (size === 0) {\n      callback();\n    } else {\n      urls.forEach((url) => {\n        this.callUrlCached(url, () => {\n          --size;\n          if (size === 0) {\n            callback();\n          }\n        });\n      });\n    }\n  }\n\n  // private\n  gatherUrls(tree, urls) {\n    urls.add(tree.url);\n    tree.children.map((t) => this.gatherUrls(t, urls));\n  }\n\n  // private\n  callUrlCached(url, callback) {\n    if (url === '' || url === null || url in this.urlResults) {\n      callback();\n      return;\n    }\n\n    const parsedUrl = urlLib.parse(url);\n    const mapPath = parsedUrl.pathname.replace(/\\.bundle$/, '.map');\n    const options = {\n      host: 'localhost',\n      port: parsedUrl.port,\n      path: mapPath + parsedUrl.search + '&babelSourcemap=true',\n    };\n\n    http.get(options, (res) => {\n      res.setEncoding('utf8');\n      let sawEnd = false;\n      let resBody = '';\n      res.on('data', (chunk) => {\n        resBody += chunk;\n      }).on('end', () => {\n        sawEnd = true;\n        this.urlResults[url] = new SourceMapConsumer(resBody);\n        callback();\n      }).on('close', (err) => {\n        if (!sawEnd) {\n          console.error('Connection terminated prematurely because of: '\n                        + err.code + ' for url: ' + url);\n          callback();\n        }\n      });\n    }).on('error', (err) => {\n      console.error('Could not get response from: ' + url);\n      callback();\n    });\n  }\n}\n\nmodule.exports = function(req, res, next) {\n  if (req.url !== '/jsc-profile') {\n    next();\n    return;\n  }\n\n  console.log('Received request from JSC profiler, post processing it...');\n  let profile = JSON.parse(req.rawBody);\n  (new TreeTransformator()).transform(profile.head, (newHead) => {\n    profile.head = newHead;\n\n    console.log('Dumping JSC profile information...');\n    const dumpName = '/tmp/jsc-profile_' + Date.now() + '.cpuprofile';\n\n    fs.writeFile(dumpName, JSON.stringify(profile), (err) => {\n      let response = '';\n      if (err) {\n        response =\n          'An error occured when trying to save the profile at ' + dumpName;\n        console.error(response, err);\n      } else {\n        response =\n          'Your profile was generated at\\n\\n' + dumpName + '\\n\\n' +\n          'Open `Chrome/Atom Dev Tools > Profiles > Load` '\n          + 'and select the profile to visualize it.';\n        console.log(response);\n      }\n      res.end(response);\n    });\n  });\n};\n"
  },
  {
    "path": "local-cli/server/middleware/loadRawBodyMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nmodule.exports = function(req, res, next) {\n  req.rawBody = '';\n  req.setEncoding('utf8');\n\n  req.on('data', function(chunk) {\n    req.rawBody += chunk;\n  });\n\n  req.on('end', function() {\n    next();\n  });\n};\n"
  },
  {
    "path": "local-cli/server/middleware/openStackFrameInEditorMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst launchEditor = require('../util/launchEditor');\n\nmodule.exports = function(args) {\n  return function(req, res, next) {\n    if (req.url === '/open-stack-frame') {\n      var frame = JSON.parse(req.rawBody);\n      launchEditor(frame.file, frame.lineNumber, args['projectRoots']);\n      res.end('OK');\n    } else {\n      next();\n    }\n  };\n};\n"
  },
  {
    "path": "local-cli/server/middleware/statusPageMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\n/**\n * Status page so that anyone who needs to can verify that the packager is\n * running on 8081 and not another program / service.\n */\nmodule.exports = function(req, res, next) {\n  if (req.url === '/status') {\n    res.end('packager-status:running');\n  } else {\n    next();\n  }\n};\n"
  },
  {
    "path": "local-cli/server/middleware/systraceProfileMiddleware.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst exec = require('child_process').exec;\nconst fs = require('fs');\nconst path = require('path');\n\nmodule.exports = function(req, res, next) {\n  if (req.url !== '/systrace') {\n    next();\n    return;\n  }\n\n  console.log('Dumping profile information...');\n  var dumpName = '/tmp/dump_' + Date.now() + '.json';\n  var prefix = process.env.TRACE_VIEWER_PATH || '';\n  var cmd = path.join(prefix, 'trace2html') + ' ' + dumpName;\n  fs.writeFileSync(dumpName, req.rawBody);\n  exec(cmd, function(error) {\n    if (error) {\n      if (error.code === 127) {\n        var response = '\\n** Failed executing `' + cmd + '` **\\n\\n' +\n          'Google trace-viewer is required to visualize the data, ' +\n          'You can install it with `brew install trace2html`\\n\\n' +\n          'NOTE: Your profile data was kept at:\\n' + dumpName;\n        console.log(response);\n        res.end(response);\n      } else {\n        console.error(error);\n        res.end('Unknown error: ' + error.message);\n      }\n      return;\n    } else {\n      exec('rm ' + dumpName);\n      exec('open ' + dumpName.replace(/json$/, 'html'), function(err) {\n        if (err) {\n          console.error(err);\n          res.end(err.message);\n        } else {\n          res.end();\n        }\n      });\n    }\n  });\n};\n"
  },
  {
    "path": "local-cli/server/runServer.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst attachHMRServer = require('./util/attachHMRServer');\nconst connect = require('connect');\nconst cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware');\nconst getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware');\nconst http = require('http');\nconst jscProfilerMiddleware = require('./middleware/jscProfilerMiddleware');\nconst loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware');\nconst messageSocket = require('./util/messageSocket.js');\nconst openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware');\nconst copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware');\nconst path = require('path');\nconst ReactPackager = require('../../packager/react-packager');\nconst statusPageMiddleware = require('./middleware/statusPageMiddleware.js');\nconst indexPageMiddleware = require('./middleware/indexPage');\nconst systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js');\nconst heapCaptureMiddleware = require('./middleware/heapCaptureMiddleware.js');\nconst webSocketProxy = require('./util/webSocketProxy.js');\nconst defaultAssetExts = require('../../packager/defaultAssetExts');\n\nfunction runServer(args, config, readyCallback) {\n  var wsProxy = null;\n  var ms = null;\n  const packagerServer = getPackagerServer(args, config);\n  const app = connect()\n    .use(loadRawBodyMiddleware)\n    .use(connect.compress())\n    .use(getDevToolsMiddleware(args, () => wsProxy && wsProxy.isChromeConnected()))\n    .use(getDevToolsMiddleware(args, () => ms && ms.isChromeConnected()))\n    .use(openStackFrameInEditorMiddleware(args))\n    .use(copyToClipBoardMiddleware)\n    .use(statusPageMiddleware)\n    .use(systraceProfileMiddleware)\n    .use(heapCaptureMiddleware)\n    .use(cpuProfilerMiddleware)\n    .use(jscProfilerMiddleware)\n    .use(indexPageMiddleware)\n    .use(packagerServer.processRequest.bind(packagerServer));\n\n  args.projectRoots.forEach(root => app.use(connect.static(root)));\n\n  app.use(connect.logger())\n    .use(connect.errorHandler());\n\n  const serverInstance = http.createServer(app).listen(\n    args.port,\n    args.host,\n    function() {\n      attachHMRServer({\n        httpServer: serverInstance,\n        path: '/hot',\n        packagerServer,\n      });\n\n      wsProxy = webSocketProxy.attachToServer(serverInstance, '/debugger-proxy');\n      ms = messageSocket.attachToServer(serverInstance, '/message');\n      webSocketProxy.attachToServer(serverInstance, '/devtools');\n      readyCallback();\n    }\n  );\n  // Disable any kind of automatic timeout behavior for incoming\n  // requests in case it takes the packager more than the default\n  // timeout of 120 seconds to respond to a request.\n  serverInstance.timeout = 0;\n}\n\nfunction getPackagerServer(args, config) {\n  const transformModulePath =\n    args.transformer ? path.resolve(args.transformer) :\n    typeof config.getTransformModulePath === 'function' ? config.getTransformModulePath() :\n    undefined;\n\n  return ReactPackager.createServer({\n    nonPersistent: args.nonPersistent,\n    projectRoots: args.projectRoots,\n    blacklistRE: config.getBlacklistRE(),\n    cacheVersion: '3',\n    getTransformOptionsModulePath: config.getTransformOptionsModulePath,\n    transformModulePath: transformModulePath,\n    extraNodeModules: config.extraNodeModules,\n    assetRoots: args.assetRoots,\n    assetExts: defaultAssetExts.concat(args.assetExts),\n    resetCache: args.resetCache,\n    verbose: args.verbose,\n  });\n}\n\nmodule.exports = runServer;\n"
  },
  {
    "path": "local-cli/server/server.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst chalk = require('chalk');\nconst formatBanner = require('./formatBanner');\nconst path = require('path');\nconst runServer = require('./runServer');\nconst findSymlinksPaths = require('./findSymlinksPaths');\nconst NODE_MODULES = path.resolve(__dirname, '..', '..', '..');\n\n/**\n * Starts the React Native Packager Server.\n */\nfunction server(argv, config, args) {\n  const roots = args.projectRoots.concat(args.root);\n  args.projectRoots = roots.concat(\n    findSymlinksPaths(NODE_MODULES, roots)\n  );\n\n  console.log(formatBanner(\n    'Running packager on port ' + args.port + '.\\n\\n' +\n    'Keep this packager running while developing on any JS projects. ' +\n    'Feel free to close this tab and run your own packager instance if you ' +\n    'prefer.\\n\\n' +\n    'https://github.com/facebook/react-native', {\n      marginLeft: 1,\n      marginRight: 1,\n      paddingBottom: 1,\n    })\n  );\n\n  console.log(\n    'Looking for JS files in\\n  ',\n    chalk.dim(args.projectRoots.join('\\n   ')),\n    '\\n'\n  );\n\n  process.on('uncaughtException', error => {\n    if (error.code === 'EADDRINUSE') {\n      console.log(\n        chalk.bgRed.bold(' ERROR '),\n        chalk.red('Packager can\\'t listen on port', chalk.bold(args.port))\n      );\n      console.log('Most likely another process is already using this port');\n      console.log('Run the following command to find out which process:');\n      console.log('\\n  ', chalk.bold('lsof -n -i4TCP:' + args.port), '\\n');\n      console.log('You can either shut down the other process:');\n      console.log('\\n  ', chalk.bold('kill -9 <PID>'), '\\n');\n      console.log('or run packager on different port.');\n    } else {\n      console.log(chalk.bgRed.bold(' ERROR '), chalk.red(error.message));\n      const errorAttributes = JSON.stringify(error);\n      if (errorAttributes !== '{}') {\n        console.error(chalk.red(errorAttributes));\n      }\n      console.error(chalk.red(error.stack));\n    }\n    console.log('\\nSee', chalk.underline('http://facebook.github.io/react-native/docs/troubleshooting.html'));\n    console.log('for common problems and solutions.');\n    process.exit(11);\n  });\n\n  runServer(args, config, () => console.log('\\nReact packager ready.\\n'));\n}\n\nmodule.exports = {\n  name: 'start',\n  func: server,\n  description: 'starts the webserver',\n  options: [{\n    command: '--port [number]',\n    default: 8081,\n    parse: (val) => Number(val),\n  }, {\n    command: '--host [string]',\n    default: '',\n  }, {\n    command: '--root [list]',\n    description: 'add another root(s) to be used by the packager in this project',\n    parse: (val) => val.split(',').map(root => path.resolve(root)),\n    default: [],\n  }, {\n    command: '--projectRoots [list]',\n    description: 'override the root(s) to be used by the packager',\n    parse: (val) => val.split(','),\n    default: (config) => config.getProjectRoots(),\n  }, {\n    command: '--assetRoots [list]',\n    description: 'specify the root directories of app assets',\n    parse: (val) => val.split(',').map(dir => path.resolve(process.cwd(), dir)),\n    default: (config) => config.getAssetRoots(),\n  }, {\n    command: '--assetExts [list]',\n    description: 'Specify any additional asset extentions to be used by the packager',\n    parse: (val) => val.split(','),\n    default: (config) => config.getAssetExts(),\n  }, {\n    command: '--skipflow',\n    description: 'Disable flow checks'\n  }, {\n    command: '--nonPersistent',\n    description: 'Disable file watcher'\n  }, {\n    command: '--transformer [string]',\n    description: 'Specify a custom transformer to be used'\n  }, {\n    command: '--reset-cache, --resetCache',\n    description: 'Removes cached files',\n  }, {\n    command: '--verbose',\n    description: 'Enables logging',\n  }],\n};\n"
  },
  {
    "path": "local-cli/server/util/attachHMRServer.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst {getInverseDependencies} = require('../../../packager/react-packager/src/node-haste');\nconst querystring = require('querystring');\nconst url = require('url');\n\nconst blacklist = [\n  'Libraries/Utilities/HMRClient.js',\n];\n\n/**\n * Attaches a WebSocket based connection to the Packager to expose\n * Hot Module Replacement updates to the simulator.\n */\nfunction attachHMRServer({httpServer, path, packagerServer}) {\n  let client = null;\n\n  function disconnect() {\n    client = null;\n    packagerServer.setHMRFileChangeListener(null);\n  }\n\n  // For the give platform and entry file, returns a promise with:\n  //   - The full list of dependencies.\n  //   - The shallow dependencies each file on the dependency list has\n  //   - Inverse shallow dependencies map\n  function getDependencies(platform, bundleEntry) {\n    return packagerServer.getDependencies({\n      platform: platform,\n      dev: true,\n      hot: true,\n      entryFile: bundleEntry,\n    }).then(response => {\n      const {getModuleId} = response;\n\n      // for each dependency builds the object:\n      // `{path: '/a/b/c.js', deps: ['modA', 'modB', ...]}`\n      return Promise.all(Object.values(response.dependencies).map(dep => {\n        return dep.getName().then(depName => {\n          if (dep.isAsset() || dep.isAsset_DEPRECATED() || dep.isJSON()) {\n            return Promise.resolve({path: dep.path, deps: []});\n          }\n          return packagerServer.getShallowDependencies({\n            platform: platform,\n            dev: true,\n            hot: true,\n            entryFile: dep.path\n          })\n            .then(deps => {\n              return {\n                path: dep.path,\n                name: depName,\n                deps,\n              };\n            });\n        });\n      }))\n      .then(deps => {\n        // list with all the dependencies' filenames the bundle entry has\n        const dependenciesCache = response.dependencies.map(dep => dep.path);\n\n        // map from module name to path\n        const moduleToFilenameCache = Object.create(null);\n        deps.forEach(dep => {\n          moduleToFilenameCache[dep.name] = dep.path;\n        });\n\n        // map that indicates the shallow dependency each file included on the\n        // bundle has\n        const shallowDependencies = Object.create(null);\n        deps.forEach(dep => {\n          shallowDependencies[dep.path] = dep.deps;\n        });\n\n        // map from module name to the modules' dependencies the bundle entry\n        // has\n        const dependenciesModulesCache = Object.create(null);\n        response.dependencies.forEach(dep => {\n          dependenciesModulesCache[getModuleId(dep)] = dep;\n        });\n\n\n        const inverseDependenciesCache = Object.create(null);\n        const inverseDependencies = getInverseDependencies(response);\n        for (const [module, dependents] of inverseDependencies) {\n          inverseDependenciesCache[getModuleId(module)] =\n            Array.from(dependents).map(getModuleId);\n        }\n\n        return {\n          dependenciesCache,\n          dependenciesModulesCache,\n          shallowDependencies,\n          inverseDependenciesCache,\n          resolutionResponse: response,\n        };\n      });\n    });\n  }\n\n  const WebSocketServer = require('ws').Server;\n  const wss = new WebSocketServer({\n    server: httpServer,\n    path: path,\n  });\n\n  console.log('[Hot Module Replacement] Server listening on', path);\n  wss.on('connection', ws => {\n    console.log('[Hot Module Replacement] Client connected');\n    const params = querystring.parse(url.parse(ws.upgradeReq.url).query);\n\n    getDependencies(params.platform, params.bundleEntry)\n      .then(({\n        dependenciesCache,\n        dependenciesModulesCache,\n        shallowDependencies,\n        inverseDependenciesCache,\n      }) => {\n        client = {\n          ws,\n          platform: params.platform,\n          bundleEntry: params.bundleEntry,\n          dependenciesCache,\n          dependenciesModulesCache,\n          shallowDependencies,\n          inverseDependenciesCache,\n        };\n\n        packagerServer.setHMRFileChangeListener((filename, stat) => {\n          if (!client) {\n            return;\n          }\n          console.log(\n            `[Hot Module Replacement] File change detected (${time()})`\n          );\n\n          const blacklisted = blacklist.find(blacklistedPath =>\n            filename.indexOf(blacklistedPath) !== -1\n          );\n\n          if (blacklisted) {\n            return;\n          }\n\n          client.ws.send(JSON.stringify({type: 'update-start'}));\n          stat.then(() => {\n            return packagerServer.getShallowDependencies({\n              entryFile: filename,\n              platform: client.platform,\n              dev: true,\n              hot: true,\n            })\n              .then(deps => {\n                if (!client) {\n                  return [];\n                }\n\n                // if the file dependencies have change we need to invalidate the\n                // dependencies caches because the list of files we need to send\n                // to the client may have changed\n                const oldDependencies = client.shallowDependencies[filename];\n                if (arrayEquals(deps, oldDependencies)) {\n                  // Need to create a resolution response to pass to the bundler\n                  // to process requires after transform. By providing a\n                  // specific response we can compute a non recursive one which\n                  // is the least we need and improve performance.\n                  return packagerServer.getDependencies({\n                    platform: client.platform,\n                    dev: true,\n                    hot: true,\n                    entryFile: filename,\n                    recursive: true,\n                  }).then(response => {\n                    const module = packagerServer.getModuleForPath(filename);\n\n                    return response.copy({dependencies: [module]});\n                  });\n                }\n\n                // if there're new dependencies compare the full list of\n                // dependencies we used to have with the one we now have\n                return getDependencies(client.platform, client.bundleEntry)\n                  .then(({\n                    dependenciesCache: depsCache,\n                    dependenciesModulesCache: depsModulesCache,\n                    shallowDependencies: shallowDeps,\n                    inverseDependenciesCache: inverseDepsCache,\n                    resolutionResponse,\n                  }) => {\n                    if (!client) {\n                      return {};\n                    }\n\n                    // build list of modules for which we'll send HMR updates\n                    const modulesToUpdate = [packagerServer.getModuleForPath(filename)];\n                    Object.keys(depsModulesCache).forEach(module => {\n                      if (!client.dependenciesModulesCache[module]) {\n                        modulesToUpdate.push(depsModulesCache[module]);\n                      }\n                    });\n\n                    // Need to send modules to the client in an order it can\n                    // process them: if a new dependency graph was uncovered\n                    // because a new dependency was added, the file that was\n                    // changed, which is the root of the dependency tree that\n                    // will be sent, needs to be the last module that gets\n                    // processed. Reversing the new modules makes sense\n                    // because we get them through the resolver which returns\n                    // a BFS ordered list.\n                    modulesToUpdate.reverse();\n\n                    // invalidate caches\n                    client.dependenciesCache = depsCache;\n                    client.dependenciesModulesCache = depsModulesCache;\n                    client.shallowDependencies = shallowDeps;\n                    client.inverseDependenciesCache = inverseDepsCache;\n\n                    return resolutionResponse.copy({\n                      dependencies: modulesToUpdate\n                    });\n                  });\n              })\n              .then((resolutionResponse) => {\n                if (!client) {\n                  return;\n                }\n\n                // make sure the file was modified is part of the bundle\n                if (!client.shallowDependencies[filename]) {\n                  return;\n                }\n\n                const httpServerAddress = httpServer.address();\n\n                // Sanitize the value from the HTTP server\n                let packagerHost = 'localhost';\n                if (httpServer.address().address &&\n                    httpServer.address().address !== '::' &&\n                    httpServer.address().address !== '') {\n                  packagerHost = httpServerAddress.address;\n                }\n\n                return packagerServer.buildBundleForHMR({\n                  entryFile: client.bundleEntry,\n                  platform: client.platform,\n                  resolutionResponse,\n                }, packagerHost, httpServerAddress.port);\n              })\n              .then(bundle => {\n                if (!client || !bundle || bundle.isEmpty()) {\n                  return;\n                }\n\n                return JSON.stringify({\n                  type: 'update',\n                  body: {\n                    modules: bundle.getModulesIdsAndCode(),\n                    inverseDependencies: client.inverseDependenciesCache,\n                    sourceURLs: bundle.getSourceURLs(),\n                    sourceMappingURLs: bundle.getSourceMappingURLs(),\n                  },\n                });\n              })\n              .catch(error => {\n                // send errors to the client instead of killing packager server\n                let body;\n                if (error.type === 'TransformError' ||\n                    error.type === 'NotFoundError' ||\n                    error.type === 'UnableToResolveError') {\n                  body = {\n                    type: error.type,\n                    description: error.description,\n                    filename: error.filename,\n                    lineNumber: error.lineNumber,\n                  };\n                } else {\n                  console.error(error.stack || error);\n                  body = {\n                    type: 'InternalError',\n                    description: 'react-packager has encountered an internal error, ' +\n                      'please check your terminal error output for more details',\n                  };\n                }\n\n                return JSON.stringify({type: 'error', body});\n              })\n              .then(update => {\n                if (!client || !update) {\n                  return;\n                }\n\n                console.log(\n                  '[Hot Module Replacement] Sending HMR update to client (' +\n                  time() + ')'\n                );\n                client.ws.send(update);\n              });\n            },\n            () => {\n              // do nothing, file was removed\n            },\n          ).then(() => {\n            client.ws.send(JSON.stringify({type: 'update-done'}));\n          });\n        });\n\n        client.ws.on('error', e => {\n          console.error('[Hot Module Replacement] Unexpected error', e);\n          disconnect();\n        });\n\n        client.ws.on('close', () => disconnect());\n      })\n    .done();\n  });\n}\n\nfunction arrayEquals(arrayA, arrayB) {\n  arrayA = arrayA || [];\n  arrayB = arrayB || [];\n  return (\n    arrayA.length === arrayB.length &&\n    arrayA.every((element, index) => {\n      return element === arrayB[index];\n    })\n  );\n}\n\nfunction time() {\n  const date = new Date();\n  return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}:${date.getMilliseconds()}`;\n}\n\nmodule.exports = attachHMRServer;\n"
  },
  {
    "path": "local-cli/server/util/copyToClipBoard.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar child_process = require('child_process');\nvar spawn = child_process.spawn;\n\n/**\n * Copy the content to host system clipboard.\n * This is only supported on Mac for now.\n */\nfunction copyToClipBoard(content) {\n  switch (process.platform) {\n  case 'darwin':\n    var child = spawn('pbcopy', []);\n    child.stdin.end(new Buffer(content, 'utf8'));\n    return true;\n  default:\n    return false;\n  }\n}\n\nmodule.exports = copyToClipBoard;\n"
  },
  {
    "path": "local-cli/server/util/debugger.html",
    "content": "<!doctype html>\n<!--\n  Copyright (c) 2015-present, Facebook, Inc.\n  All rights reserved.\n\n  This source code is licensed under the BSD-style license found in the\n  LICENSE file in the root directory of this source tree. An additional grant\n  of patent rights can be found in the PATENTS file in the same directory.\n-->\n\n<html>\n<head>\n<meta charset=utf-8>\n<!-- Fake favicon, to avoid extra request to server -->\n<link rel=\"icon\" href=\"data:;base64,iVBORw0KGgo=\">\n<title>React Native Debugger</title>\n<script>\n(function() {\n\nfunction setStatus(status) {\n  document.getElementById('status').innerHTML = status;\n}\n\nvar isMacLike = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform);\nvar refresh_shortcut = isMacLike ? '⌘R' : 'Ctrl R';\nwindow.onload = function() {\n  if (!isMacLike) {\n    document.getElementById('dev_tools_shortcut').innerHTML = 'Ctrl⇧J';\n  }\n}\n\nvar INITIAL_MESSAGE = 'Waiting, press <span class=\"shortcut\">' + refresh_shortcut + '</span> in simulator to reload and connect.';\n\nfunction connectToDebuggerProxy() {\n  var worker;\n  var ws = new WebSocket('ws://' + window.location.host + '/debugger-proxy?role=debugger&name=Chrome');\n\n  function createJSRuntime() {\n    // This worker will run the application javascript code,\n    // making sure that it's run in an environment without a global\n    // document, to make it consistent with the JSC executor environment.\n    worker = new Worker('debuggerWorker.js');\n    worker.onmessage = function(message) {\n      ws.send(JSON.stringify(message.data));\n    };\n    window.onbeforeunload = function() {\n      return 'If you reload this page, it is going to break the debugging session. ' +\n        'You should press' + refresh_shortcut + 'in simulator to reload.';\n    };\n  }\n\n  function shutdownJSRuntime() {\n    if (worker) {\n      worker.terminate();\n      worker = null;\n      window.onbeforeunload = null;\n    }\n  }\n\n  ws.onopen = function() {\n    setStatus(INITIAL_MESSAGE);\n  };\n\n  ws.onmessage = function(message) {\n    if (!message.data) {\n      return;\n    }\n    var object = JSON.parse(message.data);\n\n    if (object.$event === 'client-disconnected') {\n      shutdownJSRuntime();\n      setStatus('Waiting, press <span class=\"shortcut\">' + refresh_shortcut + '</span> in simulator to reload and connect.');\n      return;\n    }\n\n    if (!object.method) {\n      return;\n    }\n\n    // Special message that asks for a new JS runtime\n    if (object.method === 'prepareJSRuntime') {\n      shutdownJSRuntime();\n      console.clear();\n      createJSRuntime();\n      ws.send(JSON.stringify({replyID: object.id}));\n      setStatus('Debugger session #' + object.id + ' active.');\n    } else if (object.method === '$disconnected') {\n      shutdownJSRuntime();\n      setStatus(INITIAL_MESSAGE);\n    } else {\n      // Otherwise, pass through to the worker.\n      worker.postMessage(object);\n    }\n  };\n\n  ws.onclose = function(e) {\n    shutdownJSRuntime();\n    setStatus('Disconnected from proxy. Attempting reconnection. Is node server running?');\n    if (e.reason) {\n      setStatus(e.reason);\n      console.warn(e.reason);\n    }\n    setTimeout(connectToDebuggerProxy, 500);\n  };\n}\n\nconnectToDebuggerProxy();\n\n})();\n</script>\n<style type=\"text/css\">\n  body {\n    font-size: large;\n    margin: 0;\n    padding: 0;\n    font-family: Helvetica, Verdana, sans-serif;\n    font-weight: 200;\n  }\n  .shortcut {\n    font-family: \"Monaco\", monospace;\n    font-size: medium;\n    color: #eee;\n    background-color: #333;\n    padding: 4px;\n    border-radius: 4px;\n    letter-spacing: 3px;\n  }\n  .content {\n    padding: 10px;\n  }\n</style>\n</head>\n<body>\n  <div class=\"content\">\n    <p>\n      React Native JS code runs inside this Chrome tab.\n    </p>\n    <p>Press <kbd id='dev_tools_shortcut' class=\"shortcut\">⌘⌥J</kbd> to open Developer Tools. Enable <a href=\"https://stackoverflow.com/a/17324511/232122\" target=\"_blank\">Pause On Caught Exceptions</a> for a better debugging experience.</p>\n    <p>Status: <span id=\"status\">Loading...</span></p>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "local-cli/server/util/debuggerWorker.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n/* global __fbBatchedBridge, self, importScripts, postMessage, onmessage: true */\n/* eslint no-unused-vars: 0 */\n'use strict';\n\nvar messageHandlers = {\n  'executeApplicationScript': function(message, sendReply) {\n    for (var key in message.inject) {\n      self[key] = JSON.parse(message.inject[key]);\n    }\n    let error;\n    try {\n      importScripts(message.url);\n    } catch (err) {\n      error = JSON.stringify(err);\n    }\n    sendReply(null /* result */, error);\n  }\n};\n\nonmessage = function(message) {\n  var object = message.data;\n\n  var sendReply = function(result, error) {\n    postMessage({replyID: object.id, result: result, error: error});\n  };\n\n  var handler = messageHandlers[object.method];\n  if (handler) {\n    // Special cased handlers\n    handler(object, sendReply);\n  } else {\n    // Other methods get called on the bridge\n    var returnValue = [[], [], [], 0];\n    try {\n      if (typeof __fbBatchedBridge === 'object') {\n        returnValue = __fbBatchedBridge[object.method].apply(null, object.arguments);\n      }\n    } finally {\n      sendReply(JSON.stringify(returnValue));\n    }\n  }\n};\n"
  },
  {
    "path": "local-cli/server/util/launchEditor.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar chalk = require('chalk');\nvar fs = require('fs');\nvar path = require('path');\nvar child_process = require('child_process');\nconst isAbsolutePath = require('absolute-path');\n\nfunction isTerminalEditor(editor) {\n  switch (editor) {\n    case 'vim':\n    case 'emacs':\n    case 'nano':\n      return true;\n  }\n  return false;\n}\n\n// Map from full process name to binary that starts the process\n// We can't just re-use full process name, because it will spawn a new instance\n// of the app every time\nvar COMMON_EDITORS = {\n  '/Applications/Atom.app/Contents/MacOS/Atom': 'atom',\n  '/Applications/Sublime Text.app/Contents/MacOS/Sublime Text':\n    '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl',\n  '/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2':\n    '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl',\n  '/Applications/Visual Studio Code.app/Contents/MacOS/Electron': 'code',\n};\n\nfunction addWorkspaceToArgumentsIfExists(args, workspace) {\n  if (workspace) {\n    args.unshift(workspace);\n  }\n  return args;\n}\n\nfunction getArgumentsForLineNumber(editor, fileName, lineNumber, workspace) {\n  switch (path.basename(editor)) {\n    case 'vim':\n    case 'mvim':\n      return [fileName, '+' + lineNumber];\n    case 'atom':\n      return addWorkspaceToArgumentsIfExists([fileName + ':' + lineNumber], workspace);\n    case 'subl':\n    case 'sublime':\n    case 'wstorm':\n    case 'appcode':\n    case 'idea':  \n      return [fileName + ':' + lineNumber];\n    case 'joe':\n    case 'emacs':\n    case 'emacsclient':\n      return ['+' + lineNumber, fileName];\n    case 'rmate':\n    case 'mate':\n    case 'mine':\n      return ['--line', lineNumber, fileName];\n    case 'code':\n      return addWorkspaceToArgumentsIfExists(['-g', fileName + ':' + lineNumber], workspace);\n  }\n\n  // For all others, drop the lineNumber until we have\n  // a mapping above, since providing the lineNumber incorrectly\n  // can result in errors or confusing behavior.\n  return [fileName];\n}\n\nfunction guessEditor() {\n  // Explicit config always wins\n  if (process.env.REACT_EDITOR) {\n    return process.env.REACT_EDITOR;\n  }\n\n  // Using `ps x` on OSX we can find out which editor is currently running.\n  // Potentially we could use similar technique for Windows and Linux\n  if (process.platform === 'darwin') {\n    try {\n      var output = child_process.execSync('ps x').toString();\n      var processNames = Object.keys(COMMON_EDITORS);\n      for (var i = 0; i < processNames.length; i++) {\n        var processName = processNames[i];\n        if (output.indexOf(processName) !== -1) {\n          return COMMON_EDITORS[processName];\n        }\n      }\n    } catch(error) {\n      // Ignore...\n    }\n  }\n\n  // Last resort, use old skool env vars\n  return process.env.VISUAL || process.env.EDITOR;\n}\n\nfunction printInstructions(title) {\n  console.log([\n    '',\n    chalk.bgBlue.white.bold(' ' + title + ' '),\n    '  When you see Red Box with stack trace, you can click any ',\n    '  stack frame to jump to the source file. The packager will launch your ',\n    '  editor of choice. It will first look at REACT_EDITOR environment ',\n    '  variable, then at EDITOR. To set it up, you can add something like ',\n    '  export REACT_EDITOR=atom to your ~/.bashrc or ~/.zshrc depending on ',\n    '  which shell you use.',\n    ''\n  ].join('\\n'));\n}\n\nfunction transformToAbsolutePathIfNeeded(pathName) {\n  if (!isAbsolutePath(pathName)) {\n    pathName = path.resolve(process.cwd(), pathName);\n  }\n  return pathName;\n}\n\nfunction findRootForFile(projectRoots, fileName) {\n  fileName = transformToAbsolutePathIfNeeded(fileName);\n  return projectRoots.find((root) => {\n    root = transformToAbsolutePathIfNeeded(root);\n    return fileName.startsWith(root + path.sep);\n  });\n}\n\nvar _childProcess = null;\nfunction launchEditor(fileName, lineNumber, projectRoots) {\n  if (!fs.existsSync(fileName)) {\n    return;\n  }\n\n  // Sanitize lineNumber to prevent malicious use on win32\n  // via: https://github.com/nodejs/node/blob/c3bb4b1aa5e907d489619fb43d233c3336bfc03d/lib/child_process.js#L333\n  if (lineNumber && isNaN(lineNumber)) {\n    return;\n  }\n\n  var editor = guessEditor();\n  if (!editor) {\n    printInstructions('PRO TIP');\n    return;\n  }\n\n  var workspace = findRootForFile(projectRoots, fileName);\n  var args = [fileName];\n  if (lineNumber) {\n    args = getArgumentsForLineNumber(editor, fileName, lineNumber, workspace);\n  }\n  console.log('Opening ' + chalk.underline(fileName) + ' with ' + chalk.bold(editor));\n\n  if (_childProcess && isTerminalEditor(editor)) {\n    // There's an existing editor process already and it's attached\n    // to the terminal, so go kill it. Otherwise two separate editor\n    // instances attach to the stdin/stdout which gets confusing.\n    _childProcess.kill('SIGKILL');\n  }\n\n  if (process.platform === 'win32') {\n    // On Windows, launch the editor in a shell because spawn can only\n    // launch .exe files.\n    _childProcess = child_process.spawn('cmd.exe', ['/C', editor].concat(args), {stdio: 'inherit'});\n  } else {\n    _childProcess = child_process.spawn(editor, args, {stdio: 'inherit'});\n  }\n  _childProcess.on('exit', function(errorCode) {\n    _childProcess = null;\n\n    if (errorCode) {\n      console.log(chalk.red('Your editor exited with an error!'));\n      printInstructions('Keep these instructions in mind:');\n    }\n  });\n\n  _childProcess.on('error', function(error) {\n    console.log(chalk.red(error.message));\n    printInstructions('How to fix:');\n  });\n}\n\nmodule.exports = launchEditor;\n"
  },
  {
    "path": "local-cli/server/util/messageSocket.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\n\nfunction attachToServer(server, path) {\n  var WebSocketServer = require('ws').Server;\n  var wss = new WebSocketServer({\n    server: server,\n    path: path\n  });\n  var clients = [];\n\n  function sendFrom(source, data) {\n    clients.forEach((client) => {\n      if (client !== source) {\n        try {\n          client.send(data);\n        } catch (e) {\n          // Sometimes this call throws 'not opened'\n        }\n      }\n    });\n  }\n\n  wss.on('connection', function(ws) {\n    clients.push(ws);\n    ws.onclose =\n    ws.onerror = () => {\n      ws.onmessage = null;\n      clients = clients.filter((client) => client !== ws);\n    };\n    ws.onmessage = ({data}) => sendFrom(ws, data);\n  });\n\n  return {\n    broadcast: (message) => {\n      sendFrom(null, JSON.stringify(message));\n    }\n  };\n}\n\nmodule.exports = {\n  attachToServer: attachToServer\n};\n"
  },
  {
    "path": "local-cli/server/util/webSocketProxy.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\n\nfunction attachToServer(server, path) {\n  var WebSocketServer = require('ws').Server;\n  var wss = new WebSocketServer({\n    server: server,\n    path: path\n  });\n  var debuggerSocket, clientSocket;\n\n  function send(dest, message) {\n    if (!dest) {\n      return;\n    }\n\n    try {\n      dest.send(message);\n    } catch(e) {\n      console.warn(e);\n      // Sometimes this call throws 'not opened'\n    }\n  }\n\n  wss.on('connection', function(ws) {\n    const {url} = ws.upgradeReq;\n\n    if (url.indexOf('role=debugger') > -1) {\n      if (debuggerSocket) {\n        ws.close(1011, 'Another debugger is already connected');\n        return;\n      }\n      debuggerSocket = ws;\n      debuggerSocket.onerror =\n      debuggerSocket.onclose = () => {\n        debuggerSocket = null;\n        if (clientSocket) {\n          clientSocket.close(1011, 'Debugger was disconnected');\n        }\n      };\n      debuggerSocket.onmessage = ({data}) => send(clientSocket, data);\n    } else if (url.indexOf('role=client') > -1) {\n      if (clientSocket) {\n        clientSocket.onerror = clientSocket.onclose = clientSocket.onmessage = null;\n        clientSocket.close(1011, 'Another client connected');\n      }\n      clientSocket = ws;\n      clientSocket.onerror =\n      clientSocket.onclose = () => {\n        clientSocket = null;\n        send(debuggerSocket, JSON.stringify({method: '$disconnected'}));\n      };\n      clientSocket.onmessage = ({data}) => send(debuggerSocket, data);\n    } else {\n      ws.close(1011, 'Missing role param');\n    }\n  });\n\n  return {\n    server: wss,\n    isChromeConnected: function() {\n      return !!debuggerSocket;\n    }\n  };\n}\n\nmodule.exports = {\n  attachToServer: attachToServer\n};\n"
  },
  {
    "path": "local-cli/setup_env.bat",
    "content": ":: Copyright (c) 2015-present, Facebook, Inc.\n:: All rights reserved.\n::\n:: This source code is licensed under the BSD-style license found in the\n:: LICENSE file in the root directory of this source tree. An additional grant\n:: of patent rights can be found in the PATENTS file in the same directory.\n"
  },
  {
    "path": "local-cli/setup_env.sh",
    "content": "# Copyright (c) 2015-present, Facebook, Inc.\n# All rights reserved.\n#\n# This source code is licensed under the BSD-style license found in the\n# LICENSE file in the root directory of this source tree. An additional grant\n# of patent rights can be found in the PATENTS file in the same directory.\n\n# 2048 is the max for non root users on Mac\nulimit -n 2048\n"
  },
  {
    "path": "local-cli/upgrade/upgrade.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fs = require('fs');\nconst chalk = require('chalk');\nconst path = require('path');\nconst Promise = require('promise');\nconst yeoman = require('yeoman-environment');\nconst semver = require('semver');\n\nfunction upgrade(args, config) {\n  args = args || process.argv;\n  const env = yeoman.createEnv();\n  const pak = JSON.parse(fs.readFileSync('package.json', 'utf8'));\n  const version = pak.dependencies['react-native'];\n\n  if (version) {\n    if (version === 'latest' || version === '*') {\n      console.warn(\n        chalk.yellow(\n          'Major releases are most likely to introduce breaking changes.\\n' +\n          'Use a proper version number in your \\'package.json\\' file to avoid breakage.\\n' +\n          'e.g. - ^0.18.0'\n        )\n      );\n    } else {\n      const installed = JSON.parse(fs.readFileSync('node_modules/react-native/package.json', 'utf8'));\n\n      if (semver.satisfies(installed.version, version)) {\n        const v = version.replace(/^(~|\\^|=)/, '').replace(/x/i, '0');\n\n        if (semver.valid(v)) {\n          console.log(\n            'Upgrading project to react-native v' + installed.version + '\\n' +\n            'Be sure to read the release notes and breaking changes:\\n' +\n            chalk.blue(\n              'https://github.com/facebook/react-native/releases/tag/v' + semver.major(v) + '.' + semver.minor(v) + '.0'\n            )\n          );\n\n          // >= v0.21.0, we require react to be a peer dependency\n          if (semver.gte(v, '0.21.0') && !pak.dependencies.react) {\n            console.log(\n              chalk.yellow(\n                '\\nYour \\'package.json\\' file doesn\\'t seem to have \\'react\\' as a dependency.\\n' +\n                '\\'react\\' was changed from a dependency to a peer dependency in react-native v0.21.0.\\n' +\n                'Therefore, it\\'s necessary to include \\'react\\' in your project\\'s dependencies.\\n' +\n                'Just run \\'npm install --save react\\', then re-run \\'react-native upgrade\\'.\\n'\n              )\n            );\n            return;\n          }\n\n          if (semver.satisfies(v, '~0.26.0')) {\n            console.log(\n              chalk.yellow(\n                'React Native 0.26 introduced some breaking changes to the native files on iOS. You can\\n' +\n                'perform them manually by checking the release notes or use \\'rnpm\\' to do it automatically.\\n' +\n                'Just run:\\n' +\n                '\\'npm install -g rnpm && npm install rnpm-plugin-upgrade@0.26 --save-dev\\', then run \\'rnpm upgrade\\''\n              )\n            );\n          }\n        } else {\n          console.log(\n            chalk.yellow(\n              'A valid version number for \\'react-native\\' is not specified in your \\'package.json\\' file.'\n            )\n          );\n        }\n      } else {\n        console.warn(\n          chalk.yellow(\n            'react-native version in \\'package.json\\' doesn\\'t match the installed version in \\'node_modules\\'.\\n' +\n            'Try running \\'npm install\\' to fix the issue.'\n          )\n        );\n      }\n    }\n  } else {\n    console.warn(\n      chalk.yellow(\n        'Your \\'package.json\\' file doesn\\'t seem to have \\'react-native\\' as a dependency.'\n      )\n    );\n  }\n\n  const generatorPath = path.join(__dirname, '..', 'generator');\n  env.register(generatorPath, 'react:app');\n  const generatorArgs = ['react:app', pak.name].concat(args);\n  return new Promise((resolve) => env.run(generatorArgs, {upgrade: true}, resolve));\n}\n\nmodule.exports = {\n  name: 'upgrade',\n  description: 'upgrade your app\\'s template files to the latest version; run this after ' +\n    'updating the react-native version in your package.json and running npm install',\n  func: upgrade,\n};\n"
  },
  {
    "path": "local-cli/util/Config.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst assert = require('assert');\nconst fs = require('fs');\nconst path = require('path');\n\nconst RN_CLI_CONFIG = 'rn-cli.config.js';\n\n/**\n * Module capable of getting the configuration that should be used for\n * the `rn-cli`. The configuration file is a JS file named `rn-cli.config.js`.\n * It has to be on any parent directory of the cli.\n *\n * The function will return all the default configuration functions overriden\n * by those found on `rn-cli.config.js`, if any. If no default config is\n * provided and no configuration can be found in the directory hierarchy an\n * error will be thrown.\n */\nconst Config = {\n  get(cwd, defaultConfig, pathToConfig) {\n    let baseConfig;\n\n    // Handle the legacy code path where pathToConfig is unspecified\n    if (pathToConfig === undefined) {\n      const configPath = Config.findConfigPath(cwd);\n      if (!configPath && !defaultConfig) {\n        throw new Error(\n          `Can't find \"${RN_CLI_CONFIG}\" file in any parent folder of \"${cwd}\"`\n        );\n      }\n      baseConfig = require(configPath);\n    } else if (pathToConfig == null) {\n      assert(defaultConfig, 'Must have a default config if config is missing');\n    } else {\n      baseConfig = path.isAbsolute(pathToConfig) ?\n        require(pathToConfig) :\n        require(path.join(cwd, pathToConfig));\n    }\n\n    return {\n      ...defaultConfig,\n      ...baseConfig,\n      cwd,\n    };\n  },\n\n  findConfigPath(cwd) {\n    const parentDir = findParentDirectory(cwd, RN_CLI_CONFIG);\n    return parentDir ? path.join(parentDir, RN_CLI_CONFIG) : null;\n  },\n};\n\n// Finds the most near ancestor starting at `currentFullPath` that has\n// a file named `filename`\nfunction findParentDirectory(currentFullPath, filename) {\n  const root = path.parse(currentFullPath).root;\n  const testDir = (parts) => {\n    if (parts.length === 0) {\n      return null;\n    }\n\n    const fullPath = path.join(root, parts.join(path.sep));\n\n    var exists = fs.existsSync(path.join(fullPath, filename));\n    return exists ? fullPath : testDir(parts.slice(0, -1));\n  };\n\n  return testDir(currentFullPath.substring(root.length).split(path.sep));\n}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "local-cli/util/assertRequiredOptions.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst { Option } = require('commander');\nconst { camelCase } = require('lodash');\n\n// Commander.js has a 2 years old open issue to support <...> syntax\n// for options. Until that gets merged, we run the checks manually\n// https://github.com/tj/commander.js/issues/230\nmodule.exports = function assertRequiredOptions(options, passedOptions) {\n  options.forEach(opt => {\n    const option = new Option(opt.command);\n\n    if (!option.required) {\n      return;\n    }\n\n    const name = camelCase(option.long);\n\n    if (!passedOptions[name]) {\n      // Provide commander.js like error message\n      throw new Error(`error: option '${option.long}' missing`);\n    }\n  });\n};\n"
  },
  {
    "path": "local-cli/util/copyAndReplace.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fs = require('fs');\n\nfunction copyAndReplace(src, dest, replacements) {\n  console.log('src', src);\n  console.log('dest', dest);\n  if (fs.lstatSync(src).isDirectory()) {\n    if (!fs.existsSync(dest)) {\n      fs.mkdirSync(dest);\n    }\n  } else {\n    let content = fs.readFileSync(src, 'utf8');\n    Object.keys(replacements).forEach(regex =>\n      content = content.replace(new RegExp(regex, 'g'), replacements[regex])\n    );\n    fs.writeFileSync(dest, content);\n  }\n}\n\nmodule.exports = copyAndReplace;\n\n"
  },
  {
    "path": "local-cli/util/isPackagerRunning.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fetch = require('node-fetch');\n\n/**\n * Indicates whether or not the packager is running. It returns a promise that\n * when fulfilled can returns one out of these possible values:\n *   - `running`: the packager is running\n *   - `not_running`: the packager nor any process is running on the expected\n *                    port.\n *   - `unrecognized`: one other process is running on the port we expect the\n *                     packager to be running.\n */\nfunction isPackagerRunning() {\n  return fetch('http://localhost:8081/status').then(\n    res => res.text().then(body =>\n      body === 'packager-status:running' ? 'running' : 'unrecognized'\n    ),\n    () => 'not_running'\n  );\n}\n\nmodule.exports = isPackagerRunning;\n"
  },
  {
    "path": "local-cli/util/isValidPackageName.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nfunction isValidPackageName(name) {\n  return name.match(/^[$A-Z_][0-9A-Z_$]*$/i);\n}\n\nmodule.exports = isValidPackageName;\n"
  },
  {
    "path": "local-cli/util/log.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nvar _enabled = true;\n\nfunction disable() {\n  _enabled = false;\n}\n\nfunction log(stream, module) {\n  return function() {\n    if (!_enabled) {\n      return;\n    }\n    const message = Array.prototype.slice.call(arguments).join(' ');\n    stream.write(module + ': ' + message + '\\n');\n  };\n}\n\nmodule.exports.out = log.bind(null, process.stdout);\nmodule.exports.err = log.bind(null, process.stderr);\nmodule.exports.disable = disable;\n"
  },
  {
    "path": "local-cli/util/parseCommandLine.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * Wrapper on-top of `optimist` in order to properly support boolean flags\n * and have a slightly less awkward API.\n *\n * Usage example:\n *   var argv = parseCommandLine([{\n *     command: 'web',\n *     description: 'Run in a web browser instead of iOS',\n *     default: true\n *   }])\n *\n * NOTE: This file is used internally at Facebook and not in `local-cli` itself.\n * No changes should be made to this file without prior discussion with FB team.\n */\n'use strict';\n\nvar optimistModule = require('optimist');\n\nfunction parseCommandLine(config, args) {\n  var optimist = new optimistModule();\n  args = args || process.argv;\n  // optimist default API requires you to write the command name three time\n  // This is a small wrapper to accept an object instead\n  for (var i = 0; i < config.length; ++i) {\n    if (config[i].type === 'string') {\n      optimist.string(config[i].command);\n    } else {\n      optimist.boolean(config[i].command);\n    }\n\n    optimist\n      .default(config[i].command, config[i].default)\n      .describe(config[i].command, config[i].description);\n\n    if (config[i].required) {\n      optimist.demand(config[i].command);\n    }\n  }\n  var argv = optimist.parse(args);\n\n  // optimist doesn't have support for --dev=false, instead it returns 'false'\n  for (var i = 0; i < config.length; ++i) {\n    var command = config[i].command;\n    if (argv[command] === undefined) {\n      argv[command] = config[i].default;\n    }\n    if (argv[command] === 'true') {\n      argv[command] = true;\n    }\n    if (argv[command] === 'false') {\n      argv[command] = false;\n    }\n    if (config[i].type === 'string') {\n      // According to https://github.com/substack/node-optimist#numbers,\n      // every argument that looks like a number should be converted to one.\n      var strValue = argv[command];\n      var numValue = strValue ? Number(strValue) : undefined;\n      if (typeof numValue === 'number' && !isNaN(numValue)) {\n        argv[command] = numValue;\n      }\n    }\n  }\n\n  // Show --help\n  if (argv.help || argv.h) {\n    optimist.showHelp();\n    process.exit();\n  }\n\n  return argv;\n}\n\nmodule.exports = parseCommandLine;\n"
  },
  {
    "path": "local-cli/util/walk.js",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\n\nfunction walk(current) {\n  if (!fs.lstatSync(current).isDirectory()) {\n    return [current];\n  }\n\n  const files = fs.readdirSync(current).map(child => {\n    child = path.join(current, child);\n    return walk(child);\n  });\n  return [].concat.apply([current], files);\n}\n\nmodule.exports = walk;\n"
  },
  {
    "path": "local-cli/wrong-react-native.js",
    "content": "#!/usr/bin/env node\n\n/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nvar script = process.argv[1];\nvar installedGlobally = script.indexOf('node_modules/.bin/react-native') === -1;\n\nif (installedGlobally) {\n  console.error([\n    '\\033[31mLooks like you installed react-native globally, maybe you meant react-native-cli?',\n    'To fix the issue, run:\\033[0m',\n    'npm uninstall -g react-native',\n    'npm install -g react-native-cli'\n  ].join('\\n'));\n  process.exit(1);\n} else {\n  require('./cli').run();\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-native-photos-framework\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/olofd/react-native-photos-framework.git\"\n  },\n  \"version\": \"1.0.8\",\n  \"description\": \"Use Apples Photos Framework with react-native to fetch media from CameraRoll and iCloud\",\n  \"author\": \"Olof Dahlbom olof.dahlbom@me.com\",\n  \"nativePackage\": true,\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/olofd/react-native-photos-framework\",\n  \"keywords\": [\n    \"react-native\",\n    \"react-native-camera-roll\",\n    \"Photos Framework\",\n    \"iCloud\",\n    \"camera-roll\",\n    \"cameraroll\",\n    \"react\",\n    \"native\",\n    \"camera\",\n    \"photo\",\n    \"code\"\n  ],\n  \"files\": [\n    \"LICENSE\",\n    \"ios/\",\n    \"src/\",\n    \"local-cli/\",\n    \"index.js\",\n    \"README.md\",\n    \"install.js\",\n    \"event-emitter.js\",\n    \"react-native-photos-framework.podspec\"\n  ],\n  \"scripts\": {\n    \"postinstall\": \"node install.js\",\n    \"test\": \"jest\",\n    \"test-ios\": \"set -o pipefail && xcodebuild test -verbose -project example/ios/Example.xcodeproj -scheme Example -destination 'id=E40727B3-41FB-4D6E-B4CB-BFA87109EB12' | xcpretty\",\n    \"update\": \"git add . && git commit -m \\\"Updated\\\" && npm version patch && git push --tags && git push origin master && npm publish\",\n    \"update-small\": \"git add . && git commit -m \\\"Updated\\\" && git push origin master\"\n  },\n  \"devDependencies\": {\n    \"babel-cli\": \"^6.23.0\",\n    \"babel-jest\": \"^19.0.0\",\n    \"babel-polyfill\": \"^6.23.0\",\n    \"babel-preset-react-native\": \"^2.0.0\",\n    \"jest\": \"^19.0.2\",\n    \"jest-react-native\": \"^18.0.0\",\n    \"prop-types\": \"^15.5.10\"\n  },\n  \"jest\": {\n    \"testPathIgnorePatterns\": [\n      \"/node_modules/\",\n      \"/example/\",\n      \"local-cli/\"\n    ]\n  }\n}\n"
  },
  {
    "path": "react-native-photos-framework.podspec",
    "content": "require 'json'\npkg = JSON.parse(File.read(\"package.json\"))\n\nPod::Spec.new do |s|\n  s.name         = pkg[\"name\"]\n  s.version      = pkg[\"version\"]\n  s.summary      = pkg[\"description\"]\n  s.requires_arc = true\n  s.license      = pkg[\"license\"]\n  s.homepage     = pkg[\"homepage\"]\n  s.author       = pkg[\"author\"]\n  s.source       = { :git => pkg[\"repository\"][\"url\"],\n                     :tag => \"v\" + pkg[\"version\"] }\n  s.source_files = 'ios/**/*.{h,m}'\n  s.platform     = :ios, \"8.0\"\n  s.dependency 'React/Core'\nend\n"
  },
  {
    "path": "scripts/objc-test-ios.sh",
    "content": "#!/bin/bash\nset -ex\n\nSCRIPTS=$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\nROOT=$(dirname $SCRIPTS)\n\ncd $ROOT\n\nXCODE_WORKSPACE=\"ios/RNPhotosFramework.xcworkspace\"\nXCODE_SCHEME=\"RNPhotosFrameworkTests\"\nXCODE_SDK=\"iphonesimulator\"\nif [ -z ${XCODE_DESTINATION+x} ]; then\n  XCODE_DESTINATION=\"platform=iOS Simulator,name=iPhone 5s,OS=10.0\"\nfi\n\n. ./scripts/objc-test.sh\n"
  },
  {
    "path": "scripts/objc-test.sh",
    "content": "#!/bin/bash\n\n# This script contains common code to be run from scripts/objc-test-ios.sh or scripts/objc-test-tvos.sh\n\nif [ -z \"$XCODE_BUILD_STEPS\" ]; then\n  XCODE_BUILD_STEPS=\"build test\"\nfi\n# TODO: We use xcodebuild because xctool would stall when collecting info about\n# the tests before running them. Switch back when this issue with xctool has\n# been resolved.\nif [ -n \"$XCODE_DESTINATION\" ]; then\n  xcodebuild \\\n    -project $XCODE_PROJECT \\\n    -scheme $XCODE_SCHEME \\\n    -sdk $XCODE_SDK \\\n    -destination \"$XCODE_DESTINATION\" \\\n    $XCODE_BUILD_STEPS\nelse\n  xcodebuild \\\n    -project $XCODE_PROJECT \\\n    -scheme $XCODE_SCHEME \\\n    -sdk $XCODE_SDK \\\n    $XCODE_BUILD_STEPS\nfi\n"
  },
  {
    "path": "src/.watchmanconfig",
    "content": "{\n  \"ignore_dirs\": []\n}\n"
  },
  {
    "path": "src/ajax-helper.js",
    "content": "import Asset from './asset';\nimport NativeApi from './index';\nexport function postAssets(assets, {\n    url,\n    method,  \n    onProgress,\n    onComplete,\n    onError,\n    onFinnished,\n    modifyAssetData,\n    headers\n}) {\n    let totalProgressLoaded = {};\n    let completedItems = [];\n    let lastLoadedProgress;\n    const onTotalProgress = (assetUpdatePorgress) => {\n        if (onProgress) {\n            totalProgressLoaded[assetUpdatePorgress.asset.uri] = assetUpdatePorgress;\n            const loadedProgress = Object.keys(totalProgressLoaded).reduce((loaded, uri) => {\n                const assetProgress = totalProgressLoaded[uri];\n                return (loaded + assetProgress.percentComplete);\n            }, 0);\n            const loadedProgressTotal = Math.ceil(loadedProgress / assets.length);\n            if (lastLoadedProgress && lastLoadedProgress === loadedProgressTotal) {\n                return;\n            }\n            lastLoadedProgress = loadedProgressTotal;\n            onProgress(lastLoadedProgress, totalProgressLoaded);\n        }\n    };\n\n    const onItemComplete = (asset, status, responseText, xhr) => {\n        completedItems.push({\n            asset,\n            status,\n            responseText,\n            xhr\n        });\n        if (status === 200) {\n            onComplete && onComplete(asset, status, responseText, xhr);\n        } else {\n            onError && onError(asset, status, responseText, xhr);\n        }\n        if (completedItems.length === assets.length) {\n            onFinnished && onFinnished(completedItems);\n        }\n    };\n\n    const prepareAssets = (assets) => {\n        return new Promise((resolve, reject) => {\n            const assetsWithoutRoesourceMetaData = assets.filter(asset => asset.resourcesMetadata === undefined);\n            if (assetsWithoutRoesourceMetaData.length) {\n                NativeApi.getAssetsResourcesMetadata(assetsWithoutRoesourceMetaData.map(asset => asset.localIdentifier)).then((result) => {\n                    assetsWithoutRoesourceMetaData.forEach((asset) => {\n                        Object.assign(asset, result[asset.localIdentifier]);\n                    });\n                    resolve(assets);\n                });\n            } else {\n                resolve(assets);\n            }\n        });\n    };\n\n    return prepareAssets(assets).then((preparedAssets) => {\n        const createPostableAsset = (asset) => {\n            const resourceMetaData = asset.resourcesMetadata[0];\n            let postableAsset = {\n                uri: asset.uri,\n                name: resourceMetaData.originalFilename,\n                type: resourceMetaData.mimeType\n            };\n            if (modifyAssetData) {\n                postableAsset = modifyAssetData(postableAsset, asset, resourceMetaData);\n            }\n            return postableAsset;\n        };\n        return Promise.all(preparedAssets.map(createPostableAsset).map((postableAsset) => {\n            return postAsset(postableAsset, {\n                url,\n                method,\n                headers,\n                onProgress: onTotalProgress,\n                onComplete: onItemComplete,\n                onError: onItemComplete,\n            });\n        }));\n    });\n}\n\nexport function postAsset(postableAsset, {\n    url,\n    method,\n    headers,\n    onProgress,\n    onComplete,\n    onError\n}) {\n    return new Promise((resolve, reject) => {\n        const body = new FormData();\n        body.append('asset', postableAsset);\n        const xhr = new XMLHttpRequest();\n        let lastPercentageComplete;\n        xhr.upload.onprogress = (evt) => {\n            if (evt.lengthComputable) {\n                const percentComplete = Math.ceil((evt.loaded / evt.total) * 100);\n                if (lastPercentageComplete && percentComplete === lastPercentageComplete) {\n                    return;\n                }\n                lastPercentageComplete = percentComplete;\n                onProgress({\n                    asset: postableAsset,\n                    percentComplete: percentComplete,\n                    loaded: evt.loaded,\n                    total: evt.total\n                });\n            }\n        };\n        xhr.open(method !== undefined ? method : 'POST', url);\n        xhr.send(body);\n\n        xhr.onreadystatechange = (aEvt) => {\n            if (xhr.readyState === 1) {\n                if (headers) {\n                    Object.keys(headers).map((key) => {\n                        xhr.setRequestHeader(key, headers[key]);\n                    });\n                }\n            }\n            if (xhr.readyState === 4) {\n                if (xhr.status === 200) {\n                    onComplete(postableAsset, xhr.status, xhr.responseText, xhr);\n                    resolve({\n                        postableAsset,\n                        status: xhr.status,\n                        responseText: xhr.responseText,\n                        xhr\n                    });\n                } else {\n                    onError(postableAsset, xhr.status, xhr.responseText, xhr);\n                    reject({\n                        postableAsset,\n                        status: xhr.status,\n                        responseText: xhr.responseText,\n                        xhr\n                    });\n                }\n            }\n        };\n    });\n}"
  },
  {
    "path": "src/album-query-result-base.js",
    "content": "import Album from './album';\nimport photoAppSort from './photo-app-sort';\nimport instagramAppSort from './instagram-app-sort';\nimport EventEmitter from '../event-emitter';\n\nexport default class AlbumQueryResultBase extends EventEmitter {\n\n    instagramAppAlbumSort() {\n        return this.sortAlbumsByTypeObject(instagramAppSort, 'smartAlbum');\n    }\n\n    photoAppAlbumSort() {\n        return this.sortAlbumsByTypeObject(photoAppSort, 'smartAlbum');\n    }\n\n    sortAlbumsByTypeObject(typeArray) {\n        const newAlbumArray = [...this.albums];\n        newAlbumArray\n            .sort((albumOne, albumTwo) => {\n                let albumOneWeight = this.getSortWeigth(albumOne,\n                    typeArray);\n                let albumTwoWeight = this.getSortWeigth(albumTwo,\n                    typeArray);\n                return albumOneWeight > albumTwoWeight ? -1 :\n                    albumOneWeight === albumTwoWeight ? albumOne.title.localeCompare(\n                        albumTwo.title) : 1;\n            });\n        return newAlbumArray;\n    }\n\n    getSortWeigth(albumObj, typeArray) {\n        return typeArray.reduce((weight, typeObj, index) => {\n            if (typeObj.type === albumObj.type && typeObj.subType ==\n                albumObj.subType) {\n                weight = typeArray.length - index;\n            }\n            return weight;\n        }, 0);\n    }\n\n    onChange(changeHandler) {\n      this.addListener('onChange', changeHandler);\n      return () => this.removeListener('onChange', changeHandler);\n    }\n}\n"
  },
  {
    "path": "src/album-query-result-collection.js",
    "content": "import Album from './album';\nimport AlbumQueryResultBase from './album-query-result-base';\n\nexport default class AlbumQueryResultCollection extends AlbumQueryResultBase {\n    constructor(queryFetchResults, fetchParams, eventEmitter) {\n        super();\n        this.queryFetchResults = queryFetchResults;\n        this.onChangeHandlers = this.queryFetchResults.map(qfr => qfr.onChange(\n            this.onQueryResultChange.bind(this)));\n    }\n\n    get albums() {\n        return this\n            .queryFetchResults\n            .reduce((arr, qfr) => {\n                return arr.concat(qfr.albums);\n            }, []);\n    }\n\n    onQueryResultChange(changeDetails, updateFunc, queryResult) {\n        this.emit('onChange', changeDetails, (callback) => {\n            updateFunc();\n            callback && callback(this);\n        }, queryResult);\n    }\n\n    stopTracking() {\n      return Promise.all(this.queryFetchResults.map(qfr => qfr.stopTracking()));\n    }\n}\n"
  },
  {
    "path": "src/album-query-result.js",
    "content": "import Album from './album';\nimport AlbumQueryResultBase from './album-query-result-base';\nimport {collectionArrayObserverHandler} from './change-observer-handler';\nimport NativeApi from './index';\n\nexport default class AlbumQueryResult extends AlbumQueryResultBase {\n    constructor(obj, fetchParams, eventEmitter) {\n        super();\n        this.eventEmitter = eventEmitter;\n        this._fetchParams = fetchParams || {};\n        Object.assign(this, obj);\n        this._albumNativeObjs = this.albums;\n        this.albums = this\n            ._albumNativeObjs\n            .map(albumObj => new Album(albumObj, this._fetchParams.assetFetchOptions,\n                eventEmitter));\n        eventEmitter.addListener('onObjectChange', (changeDetails) => {\n            if (this._cacheKey === changeDetails._cacheKey) {\n                this.emit('onChange', changeDetails, (callback) => {\n                    this.applyChangeDetails(changeDetails, callback);\n                }, this);\n            }\n        });\n    }\n\n    stopTracking() {\n        return NativeApi.stopTracking(this._cacheKey);\n    }\n\n    applyChangeDetails(changeDetails, callback) {\n        return collectionArrayObserverHandler(changeDetails, this.albums, (\n            nativeObj) => {\n            return new Album(nativeObj, this._fetchParams.fetchOptions,\n                this.eventEmitter);\n        }).then((albums) => {\n            this.albums = albums;\n            callback && callback(this);\n        });\n    }\n}\n"
  },
  {
    "path": "src/album.js",
    "content": "import NativeApi from './index';\nimport Asset from './asset';\nimport uuidGenerator from './uuid-generator';\nimport changeObserverHandler, {\n    assetArrayObserverHandler\n} from './change-observer-handler';\nimport EventEmitter from '../event-emitter';\n\n\nexport default class Album extends EventEmitter {\n\n    constructor(obj, fetchOptions, eventEmitter) {\n        super();\n        this._fetchOptions = fetchOptions;\n        Object.assign(this, obj);\n        if (this.previewAssets) {\n            this.previewAssets = this\n                .previewAssets\n                .map(NativeApi.createJsAsset);\n            if (this.previewAssets.length) {\n                this.previewAsset = this.previewAssets[0];\n            }\n        }\n\n        eventEmitter.addListener('onObjectChange', (changeDetails) => {\n            if (changeDetails._cacheKey === this._cacheKey) {\n                this._emitChange(changeDetails, (assetArray, callback, fetchOptions) => {\n                    if (assetArray) {\n                        return assetArrayObserverHandler(\n                            changeDetails, assetArray,\n                            NativeApi.createJsAsset, (indecies, callback) => {\n                                //The update algo has requested new assets.\n                                return this.newAssetsRequested(indecies, fetchOptions, callback);\n                            }, this.perferedSortOrder).then(updatedArray => {\n                            callback && callback(updatedArray);\n                            return updatedArray;\n                        });\n                    }\n                    return assetArray;\n                }, this);\n            }\n        });\n    }\n\n    newAssetsRequested(indecies, fetchOptions, callback) {\n        const fetchOptionsWithIndecies = {...fetchOptions, indecies : [...indecies]};\n        return this.getAssetsWithIndecies(fetchOptionsWithIndecies).then((assets) => {\n            callback && callback(assets);\n            return assets;\n        });\n    }\n\n    deleteContentPermitted() {\n        return this._canPerformOperation(0);\n    }\n\n    removeContentPermitted() {\n        return this._canPerformOperation(1);\n    }\n\n    addContentPermitted() {\n        return this._canPerformOperation(2);\n    }\n\n    createContentPermitted() {\n        return this._canPerformOperation(3);\n    }\n\n    reArrangeContentPermitted() {\n        return this._canPerformOperation(4);\n    }\n\n    deletePermitted() {\n        return this._canPerformOperation(5);\n    }\n\n    renamePermitted() {\n        return this._canPerformOperation(6);\n    }\n\n    _canPerformOperation(index) {\n        return this.permittedOperations && this.permittedOperations[index];\n    }\n\n    stopTracking() {\n        return NativeApi.stopTracking(this._cacheKey);\n    }\n\n    getAssets(params) {\n        this.perferedSortOrder = params.assetDisplayBottomUp === params.assetDisplayStartToEnd ? 'reversed' : 'normal';\n        const trackAssets = params.trackInsertsAndDeletes || params.trackAssetsChanges;\n        if (trackAssets && !this._cacheKey) {\n            this._cacheKey = uuidGenerator();\n        }\n        return NativeApi.getAssets({\n            fetchOptions: this._fetchOptions,\n            ...params,\n            _cacheKey: this._cacheKey,\n            albumLocalIdentifier: this.localIdentifier\n        });\n    }\n\n    getAssetsWithIndecies(params) {\n        const trackAssets = params.trackInsertsAndDeletes || params.trackAssetsChanges;\n        if (trackAssets && !this._cacheKey) {\n            this._cacheKey = uuidGenerator();\n        }\n        return NativeApi.getAssetsWithIndecies({\n            fetchOptions: this._fetchOptions,\n            ...params,\n            _cacheKey: this._cacheKey,\n            albumLocalIdentifier: this.localIdentifier\n        });\n    }\n\n    addAsset(asset) {\n        return this.addAssets([asset]);\n    }\n\n    addAssets(assets) {\n        return NativeApi.addAssetsToAlbum({\n            assets: assets.map(asset => asset.localIdentifier),\n            _cacheKey: this._cacheKey,\n            albumLocalIdentifier: this.localIdentifier\n        });\n    }\n\n    removeAsset(asset) {\n        return this.removeAssets([asset]);\n    }\n\n    removeAssets(assets) {\n        return NativeApi.removeAssetsFromAlbum({\n            assets: assets.map(asset => asset.localIdentifier),\n            _cacheKey: this._cacheKey,\n            albumLocalIdentifier: this.localIdentifier\n        });\n    }\n\n    updateTitle(newTitle) {\n        return NativeApi.updateAlbumTitle({\n            newTitle: newTitle,\n            _cacheKey: this._cacheKey,\n            albumLocalIdentifier: this.localIdentifier\n        });\n    }\n\n    delete() {\n        return NativeApi.deleteAlbums([this]);\n    }\n\n    onChange(cb) {\n        this.addListener('onChange', cb);\n        return () => this.removeListener('onChange', cb);\n    }\n\n    _emitChange(...args) {\n        this.emit('onChange', ...args);\n    }\n}\n"
  },
  {
    "path": "src/asset.js",
    "content": "import NativeApi from './index';\nexport default class Asset {\n    static scheme = \"photos://\";\n    constructor(assetObj) {\n        Object.assign(this, assetObj);\n        this._assetObj = assetObj;\n    }\n\n    get uri() {\n        if (this.lastOptions === this.currentOptions && this._uri) {\n            return this._uri;\n        }\n        let queryString;\n        if (this.currentOptions) {\n            this.lastOptions = this.currentOptions;\n            queryString = this.serialize(this.currentOptions);\n        }\n        this._uri = Asset.scheme + this.localIdentifier;\n        if (queryString) {\n            this._uri = this._uri + `?${queryString}`;\n        }\n        return this._uri;\n    }\n\n    //This is here in base-class, videos can display thumb.\n    get image() {\n        if (this._imageRef) {\n            return this._imageRef;\n        }\n        const {\n            width,\n            height,\n            uri\n        } = this;\n        this._imageRef = {\n            width,\n            height,\n            uri,\n            name: 'test.jpg'\n        };\n        return this._imageRef;\n    }\n\n    get creationDate() {\n        return this.toJsDate('creationDateUTCSeconds', '_creationDate');\n    }\n\n    get modificationDate() {\n        return this.toJsDate('modificationDateUTCSeconds', '_modificationDate');\n    }\n\n    toJsDate(UTCProperty, cachedProperty) {\n        if (!this[UTCProperty]) {\n            return undefined;\n        }\n        if (!this[cachedProperty]) {\n            const utcSecondsCreated = this[UTCProperty];\n            this[cachedProperty] = new Date(0);\n            this[cachedProperty].setUTCSeconds(utcSecondsCreated);\n        }\n        return this[cachedProperty];\n    }\n\n    getMetadata() {\n        return this._fetchExtraData('getAssetsMetadata', 'creationDate');\n    }\n\n    refreshMetadata() {\n        return this._fetchExtraData('getAssetsMetadata', 'creationDate', true);\n    }\n\n    getResourcesMetadata() {\n        return this._fetchExtraData('getAssetsResourcesMetadata', 'resourcesMetadata');\n    }\n\n    _fetchExtraData(nativeMethod, alreadyLoadedProperty, force) {\n        return new Promise((resolve, reject) => {\n            if (!force && this[alreadyLoadedProperty]) {\n                //This means we alread have fetched metadata.\n                //Resolve directly\n                resolve(this);\n                return;\n            }\n            return resolve(NativeApi[nativeMethod]([this.localIdentifier])\n                .then((metadataObjs) => {\n                    if (metadataObjs && metadataObjs[this.localIdentifier]) {\n                        Object.assign(this, metadataObjs[this.localIdentifier]);\n                    }\n                    return this;\n                }));\n        });\n    }\n\n    serialize(obj) {\n        var str = [];\n        for (var p in obj) {\n            if (obj.hasOwnProperty(p)) {\n                str.push(encodeURIComponent(p) + \"=\" + encodeURIComponent(\n                    obj[p]));\n            }\n        }\n        return str.join(\"&\");\n    }\n\n    withOptions(options) {\n        this.currentOptions = options;\n        return this;\n    }\n\n    delete() {\n        return NativeApi.deleteAssets([this]);\n    }\n\n    setHidden(hidden) {\n        return this._updateProperty('hidden', hidden, true);\n    }\n\n    setFavorite(favorite) {\n        return this._updateProperty('favorite', favorite, true);\n    }\n\n    setCreationDate(jsDate) {\n        return this._updateProperty('creationDate', jsDate, false);\n    }\n\n    setLocation(latLngObj) {\n        return this._updateProperty('location', latLngObj, false);\n    }\n\n    //name and extension are optional\n    saveAssetToDisk(options, onProgress, generateFileName) {\n        return NativeApi.saveAssetsToDisk([{\n            asset: this,\n            options: options\n        }], {\n                onProgress: onProgress\n            }, generateFileName).then((results) => {\n                return results[0];\n            });\n    }\n\n    _updateProperty(property, value, precheckValue) {\n        return new Promise((resolve, reject) => {\n            if (precheckValue && this[property] === value) {\n                return resolve({\n                    success: true,\n                    error: ''\n                });\n            }\n            return NativeApi.updateAssets({\n                [this.localIdentifier]: {\n                    [property]: value\n                }\n            }).then(resolve, reject);\n        });\n    }\n}\n"
  },
  {
    "path": "src/change-observer-handler.js",
    "content": "function updateHandler(arr, cb) {\n    if (arr) {\n        for (let i = 0; i < arr.length; i++) {\n            const updatedObj = arr[i];\n            cb(updatedObj);\n        }\n    }\n}\n\nfunction enumerateMoves(arr, changeDetails, indexTranslater, cb) {\n    if (changeDetails.moves && changeDetails.moves.length) {\n        for (let i = 0; i < changeDetails.moves.length; i = (i + 2)) {\n            let fromIndex = changeDetails.moves[i];\n            let toIndex = changeDetails.moves[i + 1];\n\n            let fromIndexMod = indexTranslater !== undefined ? indexTranslater(\n                fromIndex, arr, 'move') : fromIndex;\n            let toIndexMod = indexTranslater !== undefined ? indexTranslater(toIndex, arr, 'move') :\n                toIndex;\n            cb(fromIndexMod, toIndexMod, fromIndex, toIndex);\n        }\n    }\n}\n\nexport function indeciesIsReversedNormalOrScrambled(arr, changeDetails, preferedOrder) {\n    if (!arr || arr.length <= 1) {\n        return preferedOrder || 'normal';\n    }\n    const indecies = arr.map(x => x.collectionIndex);\n    if (indecies.some(index => index === undefined)) {\n        return 'scrambled';\n    }\n    let order;\n    for (let i = 0; i < arr.length; i++) {\n        let thisOrder = 'scrambled';\n        let previousIndex;\n        let currentIndex = arr[i].collectionIndex;\n        if (i !== 0 && arr[i - 1]) {\n            previousIndex = arr[i - 1].collectionIndex;\n        }\n        if (previousIndex !== undefined) {\n            if (currentIndex === previousIndex + 1) {\n                thisOrder = 'normal';\n            }\n            if (currentIndex === previousIndex - 1) {\n                thisOrder = 'reversed';\n            }\n            if (order && order !== thisOrder) {\n                order = 'scrambled';\n                break;\n            } else {\n                order = thisOrder;\n            }\n        }\n    }\n    return order;\n}\n\nfunction getObjectIndex(updatedObj, indexTranslater, arr, operation) {\n    const objectIndex = updatedObj.obj !== undefined && (updatedObj.obj.collectionIndex !==\n        undefined) ? updatedObj.obj.collectionIndex : updatedObj.index;\n    return indexTranslater !== undefined ? indexTranslater(\n        objectIndex, arr, operation) : objectIndex;\n}\n\nfunction getMissingIndecies(changeDetails, arr, indexTranslater) {\n    const missingIndecies = [];\n    enumerateMoves(arr, changeDetails,\n        indexTranslater, (fromIndex, toIndex, originalFromIndex, originalToIndex) => {\n            const fromIndexIsOutsideOfRange = (fromIndex > (arr.length - 1) || fromIndex < 0);\n            const toIndexIsWithinRange = (toIndex <= (arr.length - 1) && toIndex >= 0);\n            if ((fromIndexIsOutsideOfRange && toIndexIsWithinRange) &&\n                missingIndecies.indexOf(originalFromIndex) === -1) {\n                //This might seem wrong (to push toIndex and not fromIndex), \n                //but we need to ask for the item we don't have in it's new position.\n                //In native the collection is already up to date:\n                missingIndecies.push(originalToIndex);\n            }\n        });\n    return missingIndecies;\n}\n\nexport function assetArrayObserverHandler(changeDetails, arr, createNewObjFunc, requestNewItemsCb, preferedOrder, stepCompletedCb) {\n    const arrayOrder = indeciesIsReversedNormalOrScrambled(arr, changeDetails, preferedOrder);\n    if (arrayOrder === 'scrambled') {\n        throw new Error(\n            '[RNPhotosFramework] You can not use the automatic update function for change observing with scrambled or undefined indecies (property collectionIndex). Please submit the assets in their original order or do the update manully'\n        );\n        return;\n    }\n\n    return collectionArrayObserverHandler(changeDetails, arr, createNewObjFunc, requestNewItemsCb,\n        (index, arr, operation) => {\n            let startIndex = 0;\n            const arrWithoutUndefined = arr.filter(x => !!x);\n            if (arrWithoutUndefined.length > 0) {\n                startIndex = arrayOrder === 'normal' ? arrWithoutUndefined[0].collectionIndex : arrWithoutUndefined[\n                    arrWithoutUndefined.length - 1].collectionIndex;\n            }\n            let indexAffected = index - startIndex;\n            if (arrayOrder === 'reversed') {\n                indexAffected = ((arr.length - (operation === 'insert' ? 0 : 1)) -\n                    indexAffected);\n            }\n            return indexAffected;\n        }, (arr, index, operation, newObj) => {\n            if (arrayOrder === 'normal') {\n                for (let i = index + 1; i < arr.length; i++) {\n                    modifyIndex(arr, i, operation);\n                }\n            } else if (arrayOrder === 'reversed') {\n                for (let i = index - 1; i >= 0; i--) {\n                    modifyIndex(arr, i, operation);\n                }\n            }\n        }, stepCompletedCb);\n}\n\nfunction modifyIndex(arr, index, operation) {\n    const affectedObj = arr[index];\n    if (affectedObj) {\n        if (operation === 'insert') {\n            affectedObj.collectionIndex++;\n        } else if (operation === 'remove') {\n            affectedObj.collectionIndex--;\n        }\n    }\n}\n\n\nexport function collectionArrayObserverHandler(changeDetails, arr,\n    createNewObjFunc, requestNewItemsCb, indexTranslater, afterModCb, stepCompletedCb) {\n    //This function is constructed from Apple's documentation on how to apply\n    //incremental changes.\n    return new Promise((resolve, reject) => {\n        if (changeDetails.hasIncrementalChanges !== undefined &&\n            !changeDetails.hasIncrementalChanges) {\n            return resolve(arr);\n        }\n        performInsertAndDelete();\n\n        function performInsertAndDelete() {\n            let lastIndex = (arr.length - 1);\n            updateHandler(changeDetails.removedObjects, (updatedObj) => {\n                const index = getObjectIndex(updatedObj, indexTranslater, arr, 'remove');\n                if (index <= lastIndex && index >= 0) {\n                    arr[index] = undefined;\n                    afterModCb && afterModCb(arr, index, 'remove');\n                } else {\n                    //insertion is before our indecies, we need to increment\n                    afterModCb && afterModCb(arr, index, 'remove');\n                }\n            });\n            arr = arr.filter(obj => (obj !== undefined));\n            stepCompletedCb && stepCompletedCb('remove', arr);\n\n            lastIndex = (arr.length - 1);\n            updateHandler(changeDetails.insertedObjects, (updatedObj) => {\n                const index = getObjectIndex(updatedObj, indexTranslater, arr, 'insert');\n                if (index <= (lastIndex + 1) && index >=\n                    0) {\n                    const newObj = createNewObjFunc(updatedObj\n                        .obj);\n                    arr.splice(index, 0, newObj);\n                    afterModCb && afterModCb(arr, index, 'insert', newObj);\n                } else {\n                    //insertion is before our indecies, we need to increment\n                    afterModCb && afterModCb(arr, index, 'insert');\n                }\n                lastIndex = (arr.length - 1);\n            });\n            stepCompletedCb && stepCompletedCb('insert', arr);\n\n\n            if (requestNewItemsCb) {\n                const missingIndecies = getMissingIndecies(changeDetails, arr, indexTranslater);\n                stepCompletedCb && stepCompletedCb('fetch', missingIndecies);\n                if (missingIndecies && missingIndecies.length) {\n                    requestNewItemsCb(missingIndecies, (missingItems) => {\n                        return performMoveAndChange(missingItems);\n                    });\n                } else {\n                    return performMoveAndChange();\n                }\n            } else {\n                return performMoveAndChange();\n            }\n        }\n\n        function performMoveAndChange(missingItems) {\n            //Moves will only happen if you update a property that affects the original sort order.\n            if (changeDetails.moves) {\n                let tempObj = {};\n                let asyncMoves = [];\n                enumerateMoves(arr, changeDetails,\n                    indexTranslater, (fromIndex, toIndex, orginalFromIndex, originalToIndex) => {\n                        const fromIndexIsOutsideOfRange = (fromIndex > (arr.length - 1) || fromIndex < 0);\n                        const toIndexIsWithinRange = (toIndex <= (arr.length - 1) && toIndex >= 0);\n                        if (fromIndexIsOutsideOfRange && !toIndexIsWithinRange) {\n                            return;\n                        }\n                        let reInsertedCollectionIndex;\n                        if (!tempObj[fromIndex] && arr[fromIndex] && arr[fromIndex] && arr[fromIndex].collectionIndex !== undefined) {\n                            reInsertedCollectionIndex = arr[fromIndex].collectionIndex;\n                        }\n\n                        let fromObj = tempObj[fromIndex] || arr[fromIndex];\n                        if (!fromObj && missingItems) {\n                            fromObj = missingItems.find(item => item.collectionIndex === originalToIndex);\n                        }\n                        if (!fromObj) {\n                            console.warn('Could not find aset with collectionIndex', orginalFromIndex);\n                            afterModCb(arr, toIndex, 'remove');\n                        }\n                        tempObj[toIndex] = arr[toIndex];\n\n                        if ((arr[toIndex] && arr[toIndex].collectionIndex !== undefined) &&\n                            (fromObj && fromObj.collectionIndex !== undefined)) {\n                            fromObj.collectionIndex = arr[toIndex].collectionIndex;\n                        }\n\n                        if (toIndex <= arr.length - 1 && toIndex >= 0) {\n                            arr[toIndex] = fromObj;\n                        }\n\n                        if (reInsertedCollectionIndex !== undefined) {\n                            arr[fromIndex] = {\n                                collectionIndex: reInsertedCollectionIndex\n                            }\n                        }\n                        arr = arr.filter(item => item !== undefined);\n                    });\n            }\n            stepCompletedCb && stepCompletedCb('move', arr);\n\n            let lastIndex = (arr.length - 1);\n            updateHandler(changeDetails.changedObjects, (updatedObj) => {\n                const index = getObjectIndex(updatedObj, indexTranslater, arr, 'change');\n                if (index <= lastIndex && index >= 0) {\n                    arr[index] = createNewObjFunc(updatedObj.obj);\n                } \n            });\n            stepCompletedCb && stepCompletedCb('change', arr);\n            return resolve(arr);\n        }\n    });\n} "
  },
  {
    "path": "src/image-asset.js",
    "content": "import Asset from './asset';\n\nexport default class ImageAsset extends Asset {\n    constructor(assetObj, options) {\n        super(assetObj, options);\n    }\n\n    getImageMetadata() {\n        return this._fetchExtraData('getImageAssetsMetadata', 'imageMetadata');\n    }\n} "
  },
  {
    "path": "src/index.js",
    "content": "import ReactPropTypes from \"prop-types\";\nimport { NativeEventEmitter, NativeModules, Platform } from \"react-native\";\nimport Asset from \"./asset\";\nimport Album from \"./album\";\nimport AlbumQueryResult from \"./album-query-result\";\nimport AlbumQueryResultCollection from \"./album-query-result-collection\";\nimport EventEmitter from \"../event-emitter\";\nimport ImageAsset from \"./image-asset\";\nimport VideoAsset from \"./video-asset\";\nimport videoPropsResolver from \"./video-props-resolver\";\nimport uuidGenerator from \"./uuid-generator\";\n\nconst RNPFManager = NativeModules.RNPFManager;\nif (!RNPFManager && Platform.OS === \"ios\") {\n    throw new Error(\n        \"Could not find react-native-photos-framework's native module. It seems it's not linked correctly in your xcode-project.\"\n    );\n}\nexport const eventEmitter = new EventEmitter();\n\n// Main JS-implementation Most methods are written to handle array of input\n// operations.\nclass RNPhotosFramework {\n    constructor() {\n        this.nativeEventEmitter = new NativeEventEmitter(\n            NativeModules.RNPFManager\n        );\n        this.nativeEventEmitter.addListener(\"onObjectChange\", changeDetails => {\n            eventEmitter.emit(\"onObjectChange\", changeDetails);\n        });\n        this.nativeEventEmitter.addListener(\n            \"onLibraryChange\",\n            changeDetails => {\n                eventEmitter.emit(\"onLibraryChange\", changeDetails);\n            }\n        );\n\n        //We need to make sure we clean cache in native before any calls\n        //go into RNPF. This is important when running in DEV because we reastart\n        //often in RN. (Live reload).\n        const methodsWithoutCacheCleanBlock = [\n            \"constructor\",\n            \"libraryStartup\",\n            \"authorizationStatus\",\n            \"requestAuthorization\",\n            \"createJsAsset\",\n            \"withUniqueEventListener\",\n        ];\n        const methodNames = Object.getOwnPropertyNames(\n            RNPhotosFramework.prototype\n        ).filter(\n            method => methodsWithoutCacheCleanBlock.indexOf(method) === -1\n        );\n        methodNames.forEach(methodName => {\n            const originalMethod = this[methodName];\n            this[methodName] = function(...args) {\n                if (!this.libraryStartupPromise) {\n                    this.libraryStartupPromise = this.libraryStartup();\n                }\n                return this.libraryStartupPromise.then(() =>\n                    originalMethod.apply(this, args)\n                );\n            }.bind(this);\n        });\n    }\n\n    onLibraryChange(cb) {\n        return eventEmitter.addListener(\"onLibraryChange\", cb);\n    }\n\n    libraryStartup() {\n        return RNPFManager.libraryStartup(true);\n    }\n\n    authorizationStatus() {\n        return RNPFManager.authorizationStatus();\n    }\n\n    requestAuthorization() {\n        return RNPFManager.requestAuthorization();\n    }\n\n    setAllowsCachingHighQualityImages(allowed) {\n        return RNPFManager.setAllowsCachingHighQualityImages(allowed);\n    }\n\n    addAssetsToAlbum(params) {\n        return RNPFManager.addAssetsToAlbum(params);\n    }\n\n    removeAssetsFromAlbum(params) {\n        return RNPFManager.removeAssetsFromAlbum(params);\n    }\n\n    getAssets(params) {\n        //This might look hacky, but it is!\n        //We default to assetDisplayStartToEnd == false because photos framework will by default\n        //give us the results in the same order as the photos-app displays them. The most recent image last that is.\n        //BUT in this library we have decided to reverse that default, because most third-party apps wants (our guesses)\n        //the most recent photo first. So by default we load the results in reverse by saying assetDisplayStartToEnd = false.\n        //However. If this option is not expicitly set and you provide a saortDescriptor, we no longer want to reverse the ordser\n        //of the photos. Then we want to display them as is. So here we check for that scenario. If the key assetDisplayStartToEnd is\n        //not explicitly set and there is a sortDescriptor, do not reverse the order of the photos by assetDisplayStartToEnd = true.\n        if (\n            params &&\n            params.fetchOptions &&\n            params.assetDisplayStartToEnd === undefined &&\n            params.fetchOptions.sortDescriptors &&\n            params.fetchOptions.sortDescriptors.length\n        ) {\n            params.assetDisplayStartToEnd = true;\n        }\n        return RNPFManager.getAssets(params).then(assetsResponse => {\n            return {\n                assets: assetsResponse.assets.map(this.createJsAsset),\n                includesLastAsset: assetsResponse.includesLastAsset,\n            };\n        });\n    }\n\n    getAssetsWithIndecies(params) {\n        return RNPFManager.getAssetsWithIndecies(\n            params\n        ).then(assetsResponse => {\n            return assetsResponse.assets.map(this.createJsAsset);\n        });\n    }\n\n    getAlbumsCommon(params, asSingleQueryResult) {\n        return this.getAlbumsMany(\n            [\n                Object.assign(\n                    {\n                        type: \"smartAlbum\",\n                        subType: \"any\",\n                    },\n                    params\n                ),\n                Object.assign(\n                    {\n                        type: \"album\",\n                        subType: \"any\",\n                    },\n                    params\n                ),\n            ],\n            asSingleQueryResult\n        ).then(albumQueryResult => {\n            return albumQueryResult;\n        });\n    }\n\n    getAlbums(params) {\n        return this.getAlbumsMany([params]).then(queryResults => {\n            return queryResults[0];\n        });\n    }\n\n    getAlbumsMany(params, asSingleQueryResult) {\n        return this._getAlbumsManyRaw(params).then(albumQueryResultList => {\n            const albumQueryResults = albumQueryResultList.map(\n                (collection, index) =>\n                    new AlbumQueryResult(\n                        collection,\n                        params[index],\n                        eventEmitter\n                    )\n            );\n            if (asSingleQueryResult) {\n                return new AlbumQueryResultCollection(\n                    albumQueryResults,\n                    params,\n                    eventEmitter\n                );\n            }\n            return albumQueryResults;\n        });\n    }\n\n    _getAlbumsManyRaw(params) {\n        return RNPFManager.getAlbumsMany(params);\n    }\n\n    getAlbumsByTitle(title) {\n        return this.getAlbumsWithParams({\n            albumTitles: [title],\n        });\n    }\n\n    getAlbumsByTitles(titles) {\n        return this.getAlbumsWithParams({\n            albumTitles: titles,\n        });\n    }\n\n    // param should include property called albumTitles : array<string> But can also\n    // include things like fetchOptions and type/subtype.\n    getAlbumsWithParams(params) {\n        return RNPFManager.getAlbumsByTitles(params).then(albumQueryResult => {\n            return new AlbumQueryResult(albumQueryResult, params, eventEmitter);\n        });\n    }\n\n    createAlbum(albumTitle) {\n        return this.createAlbums([albumTitle]).then(albums => {\n            return albums[0];\n        });\n    }\n\n    createAlbums(albumTitles) {\n        return RNPFManager.createAlbums(albumTitles).then(albums => {\n            return albums.map(\n                album => new Album(album, undefined, eventEmitter)\n            );\n        });\n    }\n\n    updateAlbumTitle(params) {\n        //minimum params: {newTitle : 'x', albumLocalIdentifier : 'guid'}\n        return RNPFManager.updateAlbumTitle(params);\n    }\n\n    updateAssets(assetUpdateObjs) {\n        /* assetUpdateObj : {localIdentifier : {creationDate, location, favorite, hidden}} */\n        const arrayWithLocalIdentifiers = Object.keys(assetUpdateObjs);\n        return RNPFManager.updateAssets(\n            arrayWithLocalIdentifiers,\n            assetUpdateObjs\n        ).then(result => {\n            return result;\n        });\n    }\n\n    getAssetsMetadata(assetsLocalIdentifiers) {\n        return RNPFManager.getAssetsMetadata(assetsLocalIdentifiers);\n    }\n\n    getAssetsResourcesMetadata(assetsLocalIdentifiers) {\n        return RNPFManager.getAssetsResourcesMetadata(assetsLocalIdentifiers);\n    }\n\n    updateAssetsWithResoucesMetadata(assets) {\n        return new Promise((resolve, reject) => {\n            const assetsWithoutRoesourceMetaData = assets.filter(\n                asset => asset.resourcesMetadata === undefined\n            );\n            if (assetsWithoutRoesourceMetaData.length) {\n                RNPFManager.getAssetsResourcesMetadata(\n                    assetsWithoutRoesourceMetaData.map(\n                        asset => asset.localIdentifier\n                    )\n                ).then(result => {\n                    assetsWithoutRoesourceMetaData.forEach(asset => {\n                        Object.assign(asset, result[asset.localIdentifier]);\n                    });\n                    resolve(assets);\n                });\n            } else {\n                resolve(assets);\n            }\n        });\n    }\n\n    getImageAssetsMetadata(assetsLocalIdentifiers) {\n        return RNPFManager.getImageAssetsMetadata(assetsLocalIdentifiers);\n    }\n\n    deleteAssets(assets) {\n        return RNPFManager.deleteAssets(\n            assets.map(asset => asset.localIdentifier)\n        );\n    }\n\n    deleteAlbums(albums) {\n        return RNPFManager.deleteAlbums(\n            albums.map(album => album.localIdentifier)\n        );\n    }\n\n    createImageAsset(image) {\n        return this.createAssets({\n            images: [image],\n        }).then(result => result[0]);\n    }\n\n    createVideoAsset(video) {\n        return this.createAssets({\n            videos: [video],\n        }).then(result => result[1]);\n    }\n\n    getPostableAssets(localIdentifiers) {\n        return RNPFManager.getPostableAssets(localIdentifiers);\n    }\n\n    createAssets(params, onProgress) {\n        const images = params.images;\n        const videos =\n            params.videos !== undefined\n                ? params.videos.map(videoPropsResolver)\n                : params.videos;\n        let media = [];\n        if (images && images.length) {\n            media = media.concat(\n                images.map(image => ({\n                    type: \"image\",\n                    source: image,\n                }))\n            );\n        }\n        if (videos && videos.length) {\n            media = media.concat(\n                videos.map(video => ({\n                    type: \"video\",\n                    source: video,\n                }))\n            );\n        }\n\n        const { args, unsubscribe } = this.withUniqueEventListener(\n            \"onCreateAssetsProgress\",\n            {\n                media: media,\n                albumLocalIdentifier: params.album\n                    ? params.album.localIdentifier\n                    : undefined,\n                includeMetadata: params.includeMetadata,\n            },\n            onProgress\n        );\n        return RNPFManager.createAssets(args).then(result => {\n            unsubscribe && this.nativeEventEmitter.removeListener(unsubscribe);\n            return result.assets.map(this.createJsAsset);\n        });\n    }\n\n    withUniqueEventListener(eventName, params, cb) {\n        let subscription;\n        if (cb) {\n            params[eventName] = uuidGenerator();\n            subscription = this.nativeEventEmitter.addListener(\n                eventName,\n                data => {\n                    if (cb && data.id && data.id === params[eventName]) {\n                        cb(data);\n                    }\n                }\n            );\n        }\n        return {\n            args: params,\n            unsubscribe: subscription,\n        };\n    }\n\n    stopTracking(cacheKey) {\n        return new Promise((resolve, reject) => {\n            if (cacheKey) {\n                return resolve(RNPFManager.stopTracking(cacheKey));\n            } else {\n                resolve({\n                    success: true,\n                    status: \"was-not-tracked\",\n                });\n            }\n        });\n    }\n\n    asSingleQueryResult(albumQueryResultList, params, eventEmitter) {\n        return new AlbumQueryResultCollection(\n            albumQueryResultList,\n            params,\n            eventEmitter\n        );\n    }\n\n    createJsAsset(nativeObj, options) {\n        switch (nativeObj.mediaType) {\n            case \"image\":\n                return new ImageAsset(nativeObj, options);\n            case \"video\":\n                return new VideoAsset(nativeObj, options);\n        }\n    }\n\n    /*\n      assets,\n      options : {\n        dir : '/path', //optional\n      },\n      generateFileName : (asset, resourceMetadata) => {\n        return 'newFileName';\n      }\n  */\n\n    saveAssetsToDisk(assetsWithOptions, options, generateFileName) {\n        const { args, unsubscribe } = this.withUniqueEventListener(\n            \"onSaveAssetsToFileProgress\",\n            {},\n            options.onProgress\n        );\n\n        return this.updateAssetsWithResoucesMetadata(\n            assetsWithOptions.map(assetWithOption => assetWithOption.asset)\n        ).then(() => {\n            return RNPFManager.saveAssetsToDisk({\n                media: assetsWithOptions.map(assetWithOption => {\n                    const { asset } = assetWithOption;\n                    const resourceMetadata =\n                        assetWithOption.asset.resourcesMetadata[0];\n                    const fileName =\n                        generateFileName !== undefined\n                            ? generateFileName(\n                                  assetWithOption.asset,\n                                  resourceMetadata\n                              )\n                            : resourceMetadata.originalFilename;\n                    return {\n                        fileName,\n                        ...resourceMetadata,\n                        uri: asset.uri,\n                        localIdentifier: asset.localIdentifier,\n                        mediaType: asset.mediaType,\n                        ...assetWithOption.options,\n                    };\n                }),\n                events: {\n                    onSaveAssetsToFileProgress: args.onSaveAssetsToFileProgress,\n                },\n            });\n        });\n    }\n}\n\nexport default new RNPhotosFramework();\n"
  },
  {
    "path": "src/instagram-app-sort.js",
    "content": "export default [{\n        type: 'smartAlbum',\n        subType: 'smartAlbumUserLibrary'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumSelfPortraits'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumFavorites'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumSlomoVideos'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumPanoramas'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumRecentlyAdded'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumScreenshots'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumDepthEffect'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumTimelapses'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumVideos'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumBursts'\n    }\n    //Recently delted\n];\n"
  },
  {
    "path": "src/photo-app-sort.js",
    "content": "export default [{\n        type: 'smartAlbum',\n        subType: 'smartAlbumUserLibrary'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumFavorites'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumVideos'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumSelfPortraits'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumPanoramas'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumTimelapses'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumSlomoVideos'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumBursts'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumScreenshots'\n    }, {\n        type: 'smartAlbum',\n        subType: 'smartAlbumDepthEffect'\n    },\n    //Recently delted\n    {\n        type: 'smartAlbum',\n        subType: 'smartAlbumScreenshots'\n    }\n];"
  },
  {
    "path": "src/uuid-generator.js",
    "content": "export default function() {\n  function s4() {\n    return Math.floor((1 + Math.random()) * 0x10000)\n      .toString(16)\n      .substring(1);\n  }\n  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +\n    s4() + '-' + s4() + s4() + s4();\n}"
  },
  {
    "path": "src/video-asset.js",
    "content": "import Asset from './asset';\nimport NativeApi from './index';\n\nexport default class VideoAsset extends Asset {\n    constructor(assetObj, options) {\n        super(assetObj, options);\n    }\n\n    get video() {\n        if (this._videoRef) {\n            return this._videoRef;\n        }\n        this._videoRef = {\n            uri : this.uri,\n            type : ''\n        };\n        return this._videoRef;\n    }\n}"
  },
  {
    "path": "src/video-props-resolver.js",
    "content": "import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';\n\nexport default function videoPropsResolver(props) {\n    const source = resolveAssetSource(props) || {};\n    let {uri, type} = source;\n    if (uri && uri.match(/^\\//)) {\n        uri = `file://${uri}`;\n    }\n\n    const isNetwork = !!(uri && uri.match(/^https?:/));\n    const isAsset = !!(uri && uri.match(/^(assets-library|file):/));\n    return {\n        isAsset,\n        isNetwork,\n        uri,\n        type\n    };\n}"
  }
]