diff --git a/example/ios/Example.xcodeproj/project.pbxproj b/example/ios/Example.xcodeproj/project.pbxproj index 00ee509..75468fd 100644 --- a/example/ios/Example.xcodeproj/project.pbxproj +++ b/example/ios/Example.xcodeproj/project.pbxproj @@ -209,6 +209,41 @@ remoteGlobalIDString = A15C300E1CD25C330074CB35; remoteInfo = RNFetchBlob; }; + 63D83B701F653C63009EF4A6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7; + remoteInfo = "third-party"; + }; + 63D83B721F653C63009EF4A6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D383D3C1EBD27B6005632C8; + remoteInfo = "third-party-tvOS"; + }; + 63D83B741F653C63009EF4A6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 139D7E881E25C6D100323FB7; + remoteInfo = "double-conversion"; + }; + 63D83B761F653C63009EF4A6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3D383D621EBD27B9005632C8; + remoteInfo = "double-conversion-tvOS"; + }; + 63D83B7F1F655B0A009EF4A6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5115D1A9E6B3D00147676; + remoteInfo = RCTCameraRoll; + }; 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; @@ -267,6 +302,7 @@ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; + 63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTCameraRoll.xcodeproj; path = "../node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; 8C2A0F3E1E22AF1F00E31596 /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVideo.xcodeproj; path = "../node_modules/react-native-video/ios/RCTVideo.xcodeproj"; sourceTree = ""; }; @@ -414,6 +450,10 @@ 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */, 3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */, 3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */, + 63D83B711F653C63009EF4A6 /* libthird-party.a */, + 63D83B731F653C63009EF4A6 /* libthird-party.a */, + 63D83B751F653C63009EF4A6 /* libdouble-conversion.a */, + 63D83B771F653C63009EF4A6 /* libdouble-conversion.a */, ); name = Products; sourceTree = ""; @@ -422,7 +462,7 @@ isa = PBXGroup; children = ( 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */, + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */, ); name = Products; sourceTree = ""; @@ -435,6 +475,14 @@ name = Products; sourceTree = ""; }; + 63D83B7C1F655B0A009EF4A6 /* Products */ = { + isa = PBXGroup; + children = ( + 63D83B801F655B0A009EF4A6 /* libRCTCameraRoll.a */, + ); + name = Products; + sourceTree = ""; + }; 78C398B11ACF4ADC00677621 /* Products */ = { isa = PBXGroup; children = ( @@ -447,6 +495,7 @@ 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( + 63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */, 8C2A0F3E1E22AF1F00E31596 /* RCTVideo.xcodeproj */, 8CEAA5641E1D7D4700AD097D /* RNPhotosFramework.xcodeproj */, 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */, @@ -594,6 +643,10 @@ ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */; ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; }, + { + ProductGroup = 63D83B7C1F655B0A009EF4A6 /* Products */; + ProjectRef = 63D83B7B1F655B0A009EF4A6 /* RCTCameraRoll.xcodeproj */; + }, { ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; @@ -806,10 +859,10 @@ remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = { + 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = "libRCTAnimation-tvOS.a"; + path = libRCTAnimation.a; remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -820,6 +873,41 @@ remoteRef = 63369B731E959CBA002B65F8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 63D83B711F653C63009EF4A6 /* libthird-party.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libthird-party.a"; + remoteRef = 63D83B701F653C63009EF4A6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 63D83B731F653C63009EF4A6 /* libthird-party.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libthird-party.a"; + remoteRef = 63D83B721F653C63009EF4A6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 63D83B751F653C63009EF4A6 /* libdouble-conversion.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libdouble-conversion.a"; + remoteRef = 63D83B741F653C63009EF4A6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 63D83B771F653C63009EF4A6 /* libdouble-conversion.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libdouble-conversion.a"; + remoteRef = 63D83B761F653C63009EF4A6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 63D83B801F655B0A009EF4A6 /* libRCTCameraRoll.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTCameraRoll.a; + remoteRef = 63D83B7F1F655B0A009EF4A6 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -893,7 +981,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh"; + shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/example/package.json b/example/package.json index 13c6617..e69251a 100644 --- a/example/package.json +++ b/example/package.json @@ -10,8 +10,8 @@ "dependencies": { "babel": "^6.23.0", "babel-plugin-module-alias": "^1.6.0", - "react": "16.0.0-alpha.6", - "react-native": "^0.48.2", + "react": "16.0.0-alpha.12", + "react-native": "0.48.2", "react-native-fetch-blob": "^0.10.8", "react-native-photos-framework": "latest", "react-native-router-flux": "^4.0.0-beta.21", diff --git a/example/react-native-photos-framework/event-emitter.js b/example/react-native-photos-framework/event-emitter.js index 4089104..f80ed3e 100644 --- a/example/react-native-photos-framework/event-emitter.js +++ b/example/react-native-photos-framework/event-emitter.js @@ -1,2 +1,2 @@ -import EventEmitter from 'react-native/Libraries/EventEmitter/EventEmitter'; -export default EventEmitter; \ No newline at end of file +import EventEmitter from "EventEmitter"; +export default EventEmitter; diff --git a/example/yarn.lock b/example/yarn.lock index 625d838..928fcd6 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -61,10 +61,6 @@ ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" -ansi-escapes@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" - ansi-escapes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" @@ -640,7 +636,7 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-polyfill@6.23.0: +babel-polyfill@6.23.0, babel-polyfill@^6.20.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" dependencies: @@ -648,14 +644,6 @@ babel-polyfill@6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-polyfill@^6.20.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" - dependencies: - babel-runtime "^6.26.0" - core-js "^2.5.0" - regenerator-runtime "^0.10.5" - babel-preset-es2015-node@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-preset-es2015-node/-/babel-preset-es2015-node-6.1.1.tgz#60b23157024b0cfebf3a63554cb05ee035b4e55f" @@ -1045,7 +1033,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1: +chalk@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" dependencies: @@ -1566,7 +1554,7 @@ extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.0.1, external-editor@^2.0.4: +external-editor@^2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" dependencies: @@ -1705,15 +1693,7 @@ forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" -form-data@^2.1.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.1.1: +form-data@^2.1.1, form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" dependencies: @@ -2030,7 +2010,7 @@ ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inquirer@3.0.6: +inquirer@3.0.6, inquirer@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" dependencies: @@ -2048,25 +2028,6 @@ inquirer@3.0.6: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^3.0.6: - version "3.2.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.3.tgz#1c7b1731cf77b934ec47d22c9ac5aa8fe7fbe095" - dependencies: - ansi-escapes "^2.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -3063,20 +3024,13 @@ negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -node-fetch@1.6.3: +node-fetch@1.6.3, node-fetch@^1.0.1, node-fetch@^1.3.3: version "1.6.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" dependencies: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^1.0.1, node-fetch@^1.3.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -3456,7 +3410,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.10, prop-types@^15.5.8: +prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.5.8: version "15.5.10" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154" dependencies: @@ -3587,7 +3541,7 @@ react-native-tab-view@^0.0.67: dependencies: keymirror "0.1.1" -react-native@^0.48.2: +react-native@0.48.2: version "0.48.2" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.2.tgz#9907d5a73640ade3920701e7096fc109ba9cc6e4" dependencies: @@ -3711,13 +3665,15 @@ react-transform-hmr@^1.0.4: global "^4.3.0" react-proxy "^1.1.7" -react@16.0.0-alpha.6: - version "16.0.0-alpha.6" - resolved "https://registry.yarnpkg.com/react/-/react-16.0.0-alpha.6.tgz#2ccb1afb4425ccc12f78a123a666f2e4c141adb9" +react@16.0.0-alpha.12: + version "16.0.0-alpha.12" + resolved "https://registry.yarnpkg.com/react/-/react-16.0.0-alpha.12.tgz#8c59485281485df319b6f77682d8dd0621c08194" dependencies: + create-react-class "^15.5.2" fbjs "^0.8.9" loose-envify "^1.1.0" object-assign "^4.1.0" + prop-types "^15.5.6" read-pkg-up@^1.0.1: version "1.0.1" @@ -3778,7 +3734,7 @@ regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" -regenerator-runtime@^0.10.0, regenerator-runtime@^0.10.5: +regenerator-runtime@^0.10.0: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" @@ -3935,16 +3891,6 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" @@ -4192,7 +4138,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0: +string-width@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: diff --git a/ios/RNPhotosFramework/RNPFManager.m b/ios/RNPhotosFramework/RNPFManager.m index 107c4e0..2d35259 100644 --- a/ios/RNPhotosFramework/RNPFManager.m +++ b/ios/RNPhotosFramework/RNPFManager.m @@ -341,7 +341,7 @@ -(void) updateAssets:(NSMutableArray *)assets andUpdateObjs:(NSDictio NSString *progressEventId = [RCTConvert NSString:events[@"onSaveAssetsToFileProgress"]]; NSString *cancellationEventId = [RCTConvert NSString:events[@"onCancellationTokenCreated"]]; - [self sendEventWithName:@"onCancellationTokenCreated" body:@{@"id" : cancellationEventId, @"data" : arrayWithProgress}]; + // [self sendEventWithName:@"onCancellationTokenCreated" body:@{@"id" : cancellationEventId, @"data" : arrayWithProgress}]; if(progressEventId != nil) { arrayWithProgress = [NSMutableArray arrayWithCapacity:media.count]; diff --git a/src/index.js b/src/index.js index 2d94a69..5028000 100644 --- a/src/index.js +++ b/src/index.js @@ -1,345 +1,389 @@ -import ReactPropTypes from 'prop-types'; -import { - NativeEventEmitter, - NativeModules, - Platform -} from 'react-native'; -import Asset from './asset'; -import Album from './album'; -import AlbumQueryResult from './album-query-result'; -import AlbumQueryResultCollection from './album-query-result-collection'; -import EventEmitter from '../event-emitter'; -import ImageAsset from './image-asset'; -import VideoAsset from './video-asset'; -import videoPropsResolver from './video-props-resolver'; -import uuidGenerator from './uuid-generator'; +import ReactPropTypes from "prop-types"; +import { NativeEventEmitter, NativeModules, Platform } from "react-native"; +import Asset from "./asset"; +import Album from "./album"; +import AlbumQueryResult from "./album-query-result"; +import AlbumQueryResultCollection from "./album-query-result-collection"; +import EventEmitter from "../event-emitter"; +import ImageAsset from "./image-asset"; +import VideoAsset from "./video-asset"; +import videoPropsResolver from "./video-props-resolver"; +import uuidGenerator from "./uuid-generator"; const RNPFManager = NativeModules.RNPFManager; if (!RNPFManager && Platform.OS === "ios") { - throw new Error("Could not find react-native-photos-framework's native module. It seems it's not linked correctly in your xcode-project."); + throw new Error( + "Could not find react-native-photos-framework's native module. It seems it's not linked correctly in your xcode-project." + ); } export const eventEmitter = new EventEmitter(); // Main JS-implementation Most methods are written to handle array of input // operations. class RNPhotosFramework { + constructor() { + this.nativeEventEmitter = new NativeEventEmitter( + NativeModules.RNPFManager + ); + this.nativeEventEmitter.addListener("onObjectChange", changeDetails => { + eventEmitter.emit("onObjectChange", changeDetails); + }); + this.nativeEventEmitter.addListener( + "onLibraryChange", + changeDetails => { + eventEmitter.emit("onLibraryChange", changeDetails); + } + ); + + //We need to make sure we clean cache in native before any calls + //go into RNPF. This is important when running in DEV because we reastart + //often in RN. (Live reload). + const methodsWithoutCacheCleanBlock = [ + "constructor", + "libraryStartup", + "authorizationStatus", + "requestAuthorization", + "createJsAsset", + "withUniqueEventListener", + ]; + const methodNames = Object.getOwnPropertyNames( + RNPhotosFramework.prototype + ).filter( + method => methodsWithoutCacheCleanBlock.indexOf(method) === -1 + ); + methodNames.forEach(methodName => { + const originalMethod = this[methodName]; + this[methodName] = function(...args) { + if (!this.libraryStartupPromise) { + this.libraryStartupPromise = this.libraryStartup(); + } + return this.libraryStartupPromise.then(() => + originalMethod.apply(this, args) + ); + }.bind(this); + }); + } - constructor() { - - this.nativeEventEmitter = new NativeEventEmitter(NativeModules.RNPFManager); - this.nativeEventEmitter.addListener('onObjectChange', (changeDetails) => { - eventEmitter.emit('onObjectChange', changeDetails); - }); - this.nativeEventEmitter.addListener('onLibraryChange', (changeDetails) => { - eventEmitter.emit('onLibraryChange', changeDetails); - }); - - //We need to make sure we clean cache in native before any calls - //go into RNPF. This is important when running in DEV because we reastart - //often in RN. (Live reload). - const methodsWithoutCacheCleanBlock = ['constructor', 'libraryStartup', 'authorizationStatus', 'requestAuthorization', 'createJsAsset', 'withUniqueEventListener']; - const methodNames = ( - Object.getOwnPropertyNames(RNPhotosFramework.prototype) - .filter(method => methodsWithoutCacheCleanBlock.indexOf(method) === -1) - ); - methodNames.forEach(methodName => { - const originalMethod = this[methodName]; - this[methodName] = function (...args) { - if (!this.libraryStartupPromise) { - this.libraryStartupPromise = this.libraryStartup(); + onLibraryChange(cb) { + return eventEmitter.addListener("onLibraryChange", cb); + } + + libraryStartup() { + return RNPFManager.libraryStartup(true); + } + + authorizationStatus() { + return RNPFManager.authorizationStatus(); + } + + requestAuthorization() { + return RNPFManager.requestAuthorization(); + } + + setAllowsCachingHighQualityImages(allowed) { + return RNPFManager.setAllowsCachingHighQualityImages(allowed); + } + + addAssetsToAlbum(params) { + return RNPFManager.addAssetsToAlbum(params); + } + + removeAssetsFromAlbum(params) { + return RNPFManager.removeAssetsFromAlbum(params); + } + + getAssets(params) { + //This might look hacky, but it is! + //We default to assetDisplayStartToEnd == false because photos framework will by default + //give us the results in the same order as the photos-app displays them. The most recent image last that is. + //BUT in this library we have decided to reverse that default, because most third-party apps wants (our guesses) + //the most recent photo first. So by default we load the results in reverse by saying assetDisplayStartToEnd = false. + //However. If this option is not expicitly set and you provide a saortDescriptor, we no longer want to reverse the ordser + //of the photos. Then we want to display them as is. So here we check for that scenario. If the key assetDisplayStartToEnd is + //not explicitly set and there is a sortDescriptor, do not reverse the order of the photos by assetDisplayStartToEnd = true. + if ( + params && + params.fetchOptions && + params.assetDisplayStartToEnd === undefined && + params.fetchOptions.sortDescriptors && + params.fetchOptions.sortDescriptors.length + ) { + params.assetDisplayStartToEnd = true; } - return this.libraryStartupPromise.then(() => originalMethod.apply(this, args)); - }.bind(this); - }); - } - - onLibraryChange(cb) { - return eventEmitter.addListener('onLibraryChange', cb); - } - - libraryStartup() { - return RNPFManager.libraryStartup(true); - } - - authorizationStatus() { - return RNPFManager.authorizationStatus(); - } - - requestAuthorization() { - return RNPFManager.requestAuthorization(); - } - - setAllowsCachingHighQualityImages(allowed) { - return RNPFManager.setAllowsCachingHighQualityImages(allowed); - } - - addAssetsToAlbum(params) { - return RNPFManager.addAssetsToAlbum(params); - } - - removeAssetsFromAlbum(params) { - return RNPFManager.removeAssetsFromAlbum(params); - } - - getAssets(params) { - //This might look hacky, but it is! - //We default to assetDisplayStartToEnd == false because photos framework will by default - //give us the results in the same order as the photos-app displays them. The most recent image last that is. - //BUT in this library we have decided to reverse that default, because most third-party apps wants (our guesses) - //the most recent photo first. So by default we load the results in reverse by saying assetDisplayStartToEnd = false. - //However. If this option is not expicitly set and you provide a saortDescriptor, we no longer want to reverse the ordser - //of the photos. Then we want to display them as is. So here we check for that scenario. If the key assetDisplayStartToEnd is - //not explicitly set and there is a sortDescriptor, do not reverse the order of the photos by assetDisplayStartToEnd = true. - if (params && params.fetchOptions && params.assetDisplayStartToEnd === undefined && params.fetchOptions.sortDescriptors && params.fetchOptions.sortDescriptors.length) { - params.assetDisplayStartToEnd = true; - } - return RNPFManager - .getAssets(params) - .then((assetsResponse) => { - return { - assets: assetsResponse - .assets - .map(this.createJsAsset), - includesLastAsset: assetsResponse.includesLastAsset - }; - }); - } - - getAssetsWithIndecies(params) { - return RNPFManager - .getAssetsWithIndecies(params) - .then((assetsResponse) => { - return assetsResponse - .assets - .map(this.createJsAsset); - }); - } - - getAlbumsCommon(params, asSingleQueryResult) { - return this.getAlbumsMany([ - Object.assign({ - type: 'smartAlbum', - subType: 'any' - }, params), - Object.assign({ - type: 'album', - subType: 'any' - }, params) - ], asSingleQueryResult).then((albumQueryResult) => { - return albumQueryResult; - }); - } - - getAlbums(params) { - return this - .getAlbumsMany([params]) - .then((queryResults) => { - return queryResults[0]; - }); - } - - getAlbumsMany(params, asSingleQueryResult) { - return this - ._getAlbumsManyRaw(params) - .then((albumQueryResultList) => { - const albumQueryResults = albumQueryResultList.map((collection, index) => new AlbumQueryResult(collection, params[index], eventEmitter)); - if (asSingleQueryResult) { - return new AlbumQueryResultCollection(albumQueryResults, params, eventEmitter); + return RNPFManager.getAssets(params).then(assetsResponse => { + return { + assets: assetsResponse.assets.map(this.createJsAsset), + includesLastAsset: assetsResponse.includesLastAsset, + }; + }); + } + + getAssetsWithIndecies(params) { + return RNPFManager.getAssetsWithIndecies( + params + ).then(assetsResponse => { + return assetsResponse.assets.map(this.createJsAsset); + }); + } + + getAlbumsCommon(params, asSingleQueryResult) { + return this.getAlbumsMany( + [ + Object.assign( + { + type: "smartAlbum", + subType: "any", + }, + params + ), + Object.assign( + { + type: "album", + subType: "any", + }, + params + ), + ], + asSingleQueryResult + ).then(albumQueryResult => { + return albumQueryResult; + }); + } + + getAlbums(params) { + return this.getAlbumsMany([params]).then(queryResults => { + return queryResults[0]; + }); + } + + getAlbumsMany(params, asSingleQueryResult) { + return this._getAlbumsManyRaw(params).then(albumQueryResultList => { + const albumQueryResults = albumQueryResultList.map( + (collection, index) => + new AlbumQueryResult( + collection, + params[index], + eventEmitter + ) + ); + if (asSingleQueryResult) { + return new AlbumQueryResultCollection( + albumQueryResults, + params, + eventEmitter + ); + } + return albumQueryResults; + }); + } + + _getAlbumsManyRaw(params) { + return RNPFManager.getAlbumsMany(params); + } + + getAlbumsByTitle(title) { + return this.getAlbumsWithParams({ + albumTitles: [title], + }); + } + + getAlbumsByTitles(titles) { + return this.getAlbumsWithParams({ + albumTitles: titles, + }); + } + + // param should include property called albumTitles : array But can also + // include things like fetchOptions and type/subtype. + getAlbumsWithParams(params) { + return RNPFManager.getAlbumsByTitles(params).then(albumQueryResult => { + return new AlbumQueryResult(albumQueryResult, params, eventEmitter); + }); + } + + createAlbum(albumTitle) { + return this.createAlbums([albumTitle]).then(albums => { + return albums[0]; + }); + } + + createAlbums(albumTitles) { + return RNPFManager.createAlbums(albumTitles).then(albums => { + return albums.map( + album => new Album(album, undefined, eventEmitter) + ); + }); + } + + updateAlbumTitle(params) { + //minimum params: {newTitle : 'x', albumLocalIdentifier : 'guid'} + return RNPFManager.updateAlbumTitle(params); + } + + updateAssets(assetUpdateObjs) { + /* assetUpdateObj : {localIdentifier : {creationDate, location, favorite, hidden}} */ + const arrayWithLocalIdentifiers = Object.keys(assetUpdateObjs); + return RNPFManager.updateAssets( + arrayWithLocalIdentifiers, + assetUpdateObjs + ).then(result => { + return result; + }); + } + + getAssetsMetadata(assetsLocalIdentifiers) { + return RNPFManager.getAssetsMetadata(assetsLocalIdentifiers); + } + + getAssetsResourcesMetadata(assetsLocalIdentifiers) { + return RNPFManager.getAssetsResourcesMetadata(assetsLocalIdentifiers); + } + + updateAssetsWithResoucesMetadata(assets) { + return new Promise((resolve, reject) => { + const assetsWithoutRoesourceMetaData = assets.filter( + asset => asset.resourcesMetadata === undefined + ); + if (assetsWithoutRoesourceMetaData.length) { + RNPFManager.getAssetsResourcesMetadata( + assetsWithoutRoesourceMetaData.map( + asset => asset.localIdentifier + ) + ).then(result => { + assetsWithoutRoesourceMetaData.forEach(asset => { + Object.assign(asset, result[asset.localIdentifier]); + }); + resolve(assets); + }); + } else { + resolve(assets); + } + }); + } + + getImageAssetsMetadata(assetsLocalIdentifiers) { + return RNPFManager.getImageAssetsMetadata(assetsLocalIdentifiers); + } + + deleteAssets(assets) { + return RNPFManager.deleteAssets( + assets.map(asset => asset.localIdentifier) + ); + } + + deleteAlbums(albums) { + return RNPFManager.deleteAlbums( + albums.map(album => album.localIdentifier) + ); + } + + createImageAsset(image) { + return this.createAssets({ + images: [image], + }).then(result => result[0]); + } + + createVideoAsset(video) { + return this.createAssets({ + videos: [video], + }).then(result => result[1]); + } + + getPostableAssets(localIdentifiers) { + return RNPFManager.getPostableAssets(localIdentifiers); + } + + createAssets(params, onProgress) { + const images = params.images; + const videos = + params.videos !== undefined + ? params.videos.map(videoPropsResolver) + : params.videos; + let media = []; + if (images && images.length) { + media = media.concat( + images.map(image => ({ + type: "image", + source: image, + })) + ); + } + if (videos && videos.length) { + media = media.concat( + videos.map(video => ({ + type: "video", + source: video, + })) + ); } - return albumQueryResults; - }); - } - - _getAlbumsManyRaw(params) { - return RNPFManager.getAlbumsMany(params); - } - - getAlbumsByTitle(title) { - return this.getAlbumsWithParams({ - albumTitles: [title] - }); - } - - getAlbumsByTitles(titles) { - return this.getAlbumsWithParams({ - albumTitles: titles - }); - } - - // param should include property called albumTitles : array But can also - // include things like fetchOptions and type/subtype. - getAlbumsWithParams(params) { - return RNPFManager - .getAlbumsByTitles(params) - .then((albumQueryResult) => { - return new AlbumQueryResult(albumQueryResult, params, eventEmitter); - }); - } - - createAlbum(albumTitle) { - return this - .createAlbums([albumTitle]) - .then((albums) => { - return albums[0]; - }); - } - - createAlbums(albumTitles) { - return RNPFManager - .createAlbums(albumTitles) - .then((albums) => { - return albums.map(album => new Album(album, undefined, eventEmitter)); - }); - } - - updateAlbumTitle(params) { - //minimum params: {newTitle : 'x', albumLocalIdentifier : 'guid'} - return RNPFManager.updateAlbumTitle(params); - } - - updateAssets(assetUpdateObjs) { - /* assetUpdateObj : {localIdentifier : {creationDate, location, favorite, hidden}} */ - const arrayWithLocalIdentifiers = Object.keys(assetUpdateObjs); - return RNPFManager.updateAssets(arrayWithLocalIdentifiers, assetUpdateObjs).then((result) => { - return result; - }); - } - - getAssetsMetadata(assetsLocalIdentifiers) { - return RNPFManager.getAssetsMetadata(assetsLocalIdentifiers); - } - - getAssetsResourcesMetadata(assetsLocalIdentifiers) { - return RNPFManager.getAssetsResourcesMetadata(assetsLocalIdentifiers); - } - - updateAssetsWithResoucesMetadata(assets) { - return new Promise((resolve, reject) => { - const assetsWithoutRoesourceMetaData = assets.filter(asset => asset.resourcesMetadata === undefined); - if (assetsWithoutRoesourceMetaData.length) { - RNPFManager.getAssetsResourcesMetadata(assetsWithoutRoesourceMetaData.map(asset => asset.localIdentifier)).then((result) => { - assetsWithoutRoesourceMetaData.forEach((asset) => { - Object.assign(asset, result[asset.localIdentifier]); - }); - resolve(assets); + + const { args, unsubscribe } = this.withUniqueEventListener( + "onCreateAssetsProgress", + { + media: media, + albumLocalIdentifier: params.album + ? params.album.localIdentifier + : undefined, + includeMetadata: params.includeMetadata, + }, + onProgress + ); + return RNPFManager.createAssets(args).then(result => { + unsubscribe && this.nativeEventEmitter.removeListener(unsubscribe); + return result.assets.map(this.createJsAsset); }); - } else { - resolve(assets); - } - }); - } - - getImageAssetsMetadata(assetsLocalIdentifiers) { - return RNPFManager.getImageAssetsMetadata(assetsLocalIdentifiers); - } - - deleteAssets(assets) { - return RNPFManager.deleteAssets(assets.map(asset => asset.localIdentifier)); - } - - deleteAlbums(albums) { - return RNPFManager.deleteAlbums(albums.map(album => album.localIdentifier)); - } - - createImageAsset(image) { - return this - .createAssets({ - images: [image] - }) - .then((result) => result[0]); - } - - createVideoAsset(video) { - return this - .createAssets({ - videos: [video] - }) - .then((result) => result[1]); - } - - getPostableAssets(localIdentifiers) { - return RNPFManager.getPostableAssets(localIdentifiers); - } - - createAssets(params, onProgress) { - const images = params.images; - const videos = params.videos !== undefined ? params.videos.map(videoPropsResolver) : params.videos; - let media = []; - if (images && images.length) { - media = media.concat(images.map(image => ({ - type: 'image', - source: image - }))); - } - if (videos && videos.length) { - media = media.concat(videos.map(video => ({ - type: 'video', - source: video - }))); - } - - const { - args, - unsubscribe - } = this.withUniqueEventListener('onCreateAssetsProgress', { - media: media, - albumLocalIdentifier: params.album ? - params.album.localIdentifier : undefined, - includeMetadata: params.includeMetadata - }, onProgress); - return RNPFManager - .createAssets(args) - .then((result) => { - unsubscribe && this.nativeEventEmitter.removeListener(unsubscribe); - return result - .assets - .map(this.createJsAsset); - }); - } - - withUniqueEventListener(eventName, params, cb) { - let subscription; - if (cb) { - params[eventName] = uuidGenerator(); - subscription = this.nativeEventEmitter.addListener(eventName, (data) => { - if (cb && data.id && data.id === params[eventName]) { - cb(data); + } + + withUniqueEventListener(eventName, params, cb) { + let subscription; + if (cb) { + params[eventName] = uuidGenerator(); + subscription = this.nativeEventEmitter.addListener( + eventName, + data => { + if (cb && data.id && data.id === params[eventName]) { + cb(data); + } + } + ); } - }); - } - return { - args: params, - unsubscribe: subscription - }; - } - - stopTracking(cacheKey) { - return new Promise((resolve, reject) => { - if (cacheKey) { - return resolve(RNPFManager.stopTracking(cacheKey)); - } else { - resolve({ - success: true, - status: 'was-not-tracked' + return { + args: params, + unsubscribe: subscription, + }; + } + + stopTracking(cacheKey) { + return new Promise((resolve, reject) => { + if (cacheKey) { + return resolve(RNPFManager.stopTracking(cacheKey)); + } else { + resolve({ + success: true, + status: "was-not-tracked", + }); + } }); - } - }); - } + } - asSingleQueryResult(albumQueryResultList, params, eventEmitter) { - return new AlbumQueryResultCollection(albumQueryResultList, params, eventEmitter); - } + asSingleQueryResult(albumQueryResultList, params, eventEmitter) { + return new AlbumQueryResultCollection( + albumQueryResultList, + params, + eventEmitter + ); + } - createJsAsset(nativeObj, options) { - switch (nativeObj.mediaType) { - case "image": - return new ImageAsset(nativeObj, options); - case "video": - return new VideoAsset(nativeObj, options); + createJsAsset(nativeObj, options) { + switch (nativeObj.mediaType) { + case "image": + return new ImageAsset(nativeObj, options); + case "video": + return new VideoAsset(nativeObj, options); + } } - } - /* + /* assets, options : { dir : '/path', //optional @@ -349,31 +393,43 @@ class RNPhotosFramework { } */ - saveAssetsToDisk(assetsWithOptions, options, generateFileName) { - const { - args, - unsubscribe - } = this.withUniqueEventListener('onSaveAssetsToFileProgress', {}, options.onProgress); - - return this.updateAssetsWithResoucesMetadata(assetsWithOptions.map(assetWithOption => assetWithOption.asset)).then(() => { - return RNPFManager.saveAssetsToDisk({ - media: assetsWithOptions.map(assetWithOption => { - const { asset } = assetWithOption; - const resourceMetadata = assetWithOption.asset.resourcesMetadata[0]; - const fileName = generateFileName !== undefined ? generateFileName(assetWithOption.asset, resourceMetadata) : resourceMetadata.originalFilename; - return { - fileName, - ...resourceMetadata, - uri: asset.uri, - localIdentifier: asset.localIdentifier, - mediaType: asset.mediaType, - ...assetWithOption.options - }; - }), - ...args - }); - }); - } + saveAssetsToDisk(assetsWithOptions, options, generateFileName) { + const { args, unsubscribe } = this.withUniqueEventListener( + "onSaveAssetsToFileProgress", + {}, + options.onProgress + ); + + return this.updateAssetsWithResoucesMetadata( + assetsWithOptions.map(assetWithOption => assetWithOption.asset) + ).then(() => { + return RNPFManager.saveAssetsToDisk({ + media: assetsWithOptions.map(assetWithOption => { + const { asset } = assetWithOption; + const resourceMetadata = + assetWithOption.asset.resourcesMetadata[0]; + const fileName = + generateFileName !== undefined + ? generateFileName( + assetWithOption.asset, + resourceMetadata + ) + : resourceMetadata.originalFilename; + return { + fileName, + ...resourceMetadata, + uri: asset.uri, + localIdentifier: asset.localIdentifier, + mediaType: asset.mediaType, + ...assetWithOption.options, + }; + }), + events: { + onSaveAssetsToFileProgress: args.onSaveAssetsToFileProgress, + }, + }); + }); + } } -export default new RNPhotosFramework(); \ No newline at end of file +export default new RNPhotosFramework();