From 94b204f6709997bc877d2fc92903fcb6162ba629 Mon Sep 17 00:00:00 2001 From: Ibrahem Khalil Date: Sat, 14 Oct 2023 17:59:36 +0300 Subject: [PATCH] Add ability to count iOS images and return favorites and their count (#2) --- .../project.pbxproj | 8 +- example/ios/CameraRollExample/Info.plist | 30 ++--- example/ios/Podfile | 5 +- example/ios/Podfile.lock | 104 +----------------- ios/RNCCameraRollManager.m | 51 +++++++++ js/CameraRoll.js | 13 +++ typings/CameraRoll.d.ts | 10 ++ 7 files changed, 99 insertions(+), 122 deletions(-) diff --git a/example/ios/CameraRollExample.xcodeproj/project.pbxproj b/example/ios/CameraRollExample.xcodeproj/project.pbxproj index 14cba092f..1bef2a65c 100644 --- a/example/ios/CameraRollExample.xcodeproj/project.pbxproj +++ b/example/ios/CameraRollExample.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ 3E13565B03093F5D0EB6851C /* libPods-CameraRollExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F622B858D0D02D717DDBD411 /* libPods-CameraRollExample.a */; }; 4B9B1123FD6E06421E758980 /* libPods-CameraRollExample-tvOSTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA04DD513A5CDFB75CCAD314 /* libPods-CameraRollExample-tvOSTests.a */; }; 8B24C8D225785460007DD804 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B24C8D125785460007DD804 /* LaunchScreen.storyboard */; }; + 90939D1C2AD15DFF00CBDA92 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8B24C8D125785460007DD804 /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -49,7 +50,6 @@ 13B07F961A680F5B00A75B9A /* CameraRollExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CameraRollExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = CameraRollExample/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = CameraRollExample/AppDelegate.m; sourceTree = ""; }; - 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = CameraRollExample/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = CameraRollExample/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = CameraRollExample/main.m; sourceTree = ""; }; @@ -350,7 +350,7 @@ buildActionMask = 2147483647; files = ( 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */, - 8B24C8D225785460007DD804 /* LaunchScreen.storyboard in Resources */, + 90939D1C2AD15DFF00CBDA92 /* LaunchScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -665,7 +665,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.2sa; PRODUCT_NAME = CameraRollExample; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -687,7 +687,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.2sa; PRODUCT_NAME = CameraRollExample; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; diff --git a/example/ios/CameraRollExample/Info.plist b/example/ios/CameraRollExample/Info.plist index a8259655f..e3e992350 100644 --- a/example/ios/CameraRollExample/Info.plist +++ b/example/ios/CameraRollExample/Info.plist @@ -2,8 +2,6 @@ - NSPhotoLibraryUsageDescription - This app wants to see your photos to test the CameraRollManager CFBundleDevelopmentRegion en CFBundleDisplayName @@ -26,8 +24,23 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + NSLocationWhenInUseUsageDescription + NSPhotoLibraryUsageDescription + This app wants to see your photos to test the CameraRollManager UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -42,18 +55,5 @@ UIViewControllerBasedStatusBarAppearance - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSExceptionDomains - - localhost - - NSExceptionAllowsInsecureHTTPLoads - - - - diff --git a/example/ios/Podfile b/example/ios/Podfile index 14deb1b1d..f226671ce 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -21,10 +21,7 @@ target 'CameraRollExample' do # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable these next few lines. - use_flipper! - post_install do |installer| - flipper_post_install(installer) - end + # use_flipper!({ 'Flipper' => '0.74.0' }) end target 'CameraRollExample-tvOS' do diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 26968ad10..02e01bff8 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,7 +1,5 @@ PODS: - boost-for-react-native (1.63.0) - - CocoaAsyncSocket (7.6.4) - - CocoaLibEvent (1.0.0) - DoubleConversion (1.1.6) - FBLazyVector (0.63.4) - FBReactNativeSpec (0.63.4): @@ -11,52 +9,6 @@ PODS: - React-Core (= 0.63.4) - React-jsi (= 0.63.4) - ReactCommon/turbomodule/core (= 0.63.4) - - Flipper (0.54.0): - - Flipper-Folly (~> 2.2) - - Flipper-RSocket (~> 1.1) - - Flipper-DoubleConversion (1.1.7) - - Flipper-Folly (2.3.0): - - boost-for-react-native - - CocoaLibEvent (~> 1.0) - - Flipper-DoubleConversion - - Flipper-Glog - - OpenSSL-Universal (= 1.0.2.20) - - Flipper-Glog (0.3.6) - - Flipper-PeerTalk (0.0.4) - - Flipper-RSocket (1.1.0): - - Flipper-Folly (~> 2.2) - - FlipperKit (0.54.0): - - FlipperKit/Core (= 0.54.0) - - FlipperKit/Core (0.54.0): - - Flipper (~> 0.54.0) - - FlipperKit/CppBridge - - FlipperKit/FBCxxFollyDynamicConvert - - FlipperKit/FBDefines - - FlipperKit/FKPortForwarding - - FlipperKit/CppBridge (0.54.0): - - Flipper (~> 0.54.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.54.0): - - Flipper-Folly (~> 2.2) - - FlipperKit/FBDefines (0.54.0) - - FlipperKit/FKPortForwarding (0.54.0): - - CocoaAsyncSocket (~> 7.6) - - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.54.0) - - FlipperKit/FlipperKitLayoutPlugin (0.54.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutTextSearchable - - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutTextSearchable (0.54.0) - - FlipperKit/FlipperKitNetworkPlugin (0.54.0): - - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.54.0): - - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.54.0): - - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.54.0): - - FlipperKit/Core - - FlipperKit/FlipperKitNetworkPlugin - Folly (2020.01.13.00): - boost-for-react-native - DoubleConversion @@ -67,9 +19,6 @@ PODS: - DoubleConversion - glog - glog (0.3.5) - - OpenSSL-Universal (1.0.2.20): - - OpenSSL-Universal/Static (= 1.0.2.20) - - OpenSSL-Universal/Static (1.0.2.20) - RCTRequired (0.63.4) - RCTTypeSafety (0.63.4): - FBLazyVector (= 0.63.4) @@ -236,8 +185,8 @@ PODS: - React-cxxreact (= 0.63.4) - React-jsi (= 0.63.4) - React-jsinspector (0.63.4) - - react-native-cameraroll (4.0.1): - - React + - react-native-cameraroll (4.0.4): + - React-Core - React-RCTActionSheet (0.63.4): - React-Core/RCTActionSheetHeaders (= 0.63.4) - React-RCTAnimation (0.63.4): @@ -299,32 +248,11 @@ PODS: - React-cxxreact (= 0.63.4) - React-jsi (= 0.63.4) - Yoga (1.14.0) - - YogaKit (1.18.1): - - Yoga (~> 1.14) DEPENDENCIES: - DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../../node_modules/react-native/Libraries/FBReactNativeSpec`) - - Flipper (~> 0.54.0) - - Flipper-DoubleConversion (= 1.1.7) - - Flipper-Folly (~> 2.2) - - Flipper-Glog (= 0.3.6) - - Flipper-PeerTalk (~> 0.0.4) - - Flipper-RSocket (~> 1.1) - - FlipperKit (~> 0.54.0) - - FlipperKit/Core (~> 0.54.0) - - FlipperKit/CppBridge (~> 0.54.0) - - FlipperKit/FBCxxFollyDynamicConvert (~> 0.54.0) - - FlipperKit/FBDefines (~> 0.54.0) - - FlipperKit/FKPortForwarding (~> 0.54.0) - - FlipperKit/FlipperKitHighlightOverlay (~> 0.54.0) - - FlipperKit/FlipperKitLayoutPlugin (~> 0.54.0) - - FlipperKit/FlipperKitLayoutTextSearchable (~> 0.54.0) - - FlipperKit/FlipperKitNetworkPlugin (~> 0.54.0) - - FlipperKit/FlipperKitReactPlugin (~> 0.54.0) - - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.54.0) - - FlipperKit/SKIOSNetworkPlugin (~> 0.54.0) - Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`) - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`) - RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`) @@ -355,17 +283,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - boost-for-react-native - - CocoaAsyncSocket - - CocoaLibEvent - - Flipper - - Flipper-DoubleConversion - - Flipper-Folly - - Flipper-Glog - - Flipper-PeerTalk - - Flipper-RSocket - - FlipperKit - - OpenSSL-Universal - - YogaKit EXTERNAL SOURCES: DoubleConversion: @@ -425,21 +342,11 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c - CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845 - CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f DoubleConversion: cde416483dac037923206447da6e1454df403714 FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e - Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365 - Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 - Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a - Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6 - Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7 - FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d Folly: b73c3869541e86821df3c387eb0af5f65addfab4 glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 - OpenSSL-Universal: ff34003318d5e1163e9529b08470708e389ffcdd RCTRequired: 082f10cd3f905d6c124597fd1c14f6f2655ff65e RCTTypeSafety: 8c9c544ecbf20337d069e4ae7fd9a377aadf504b React: b0a957a2c44da4113b0c4c9853d8387f8e64e615 @@ -450,7 +357,7 @@ SPEC CHECKSUMS: React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31 React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949 React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a - react-native-cameraroll: 60ba0068826eab1c8d43146191bafd4363ea58a7 + react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336 React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0 @@ -462,8 +369,7 @@ SPEC CHECKSUMS: React-RCTVibration: ae4f914cfe8de7d4de95ae1ea6cc8f6315d73d9d ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6 - YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 8f0b12b9b79eee9204592ba3c1e51e4c49c611c3 +PODFILE CHECKSUM: 3ed8f501833322ce1df0c39b8d144dbe3ac60211 -COCOAPODS: 1.9.3 +COCOAPODS: 1.13.0 diff --git a/ios/RNCCameraRollManager.m b/ios/RNCCameraRollManager.m index 06f6fa367..f1134d07d 100644 --- a/ios/RNCCameraRollManager.m +++ b/ios/RNCCameraRollManager.m @@ -443,6 +443,57 @@ RCT_EXPORT_METHOD(deletePhotos:(NSArray*)assets } ]; } +RCT_EXPORT_METHOD(getPhotosCountiOS:(NSString *)blank + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) +{ + __block NSInteger intTotalCount=0; + PHFetchOptions *allPhotosOptions = [PHFetchOptions new]; + allPhotosOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d ",PHAssetMediaTypeImage]; + PHFetchResult *allPhotosResult = [PHAsset fetchAssetsWithOptions:allPhotosOptions]; + intTotalCount+=allPhotosResult.count; + + resolve(@(intTotalCount)); +} + +RCT_EXPORT_METHOD(getFavoritesiOS:(NSString *)blank + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) +{ + __block NSInteger intTotalCount=0; + PHFetchOptions *fetchOptions = [PHFetchOptions new]; + NSString *format = @"(favorite == true)"; + fetchOptions.predicate = [NSPredicate predicateWithFormat:format]; + PHFetchResult *const assetsFetchResult = [PHAsset fetchAssetsWithOptions:fetchOptions]; + PHAsset *imageAsset = [assetsFetchResult firstObject]; + NSMutableArray * result = [NSMutableArray new]; + + + for (PHAsset* asset in assetsFetchResult) { + NSArray *resources = [PHAssetResource assetResourcesForAsset:asset ]; + if ([resources count] < 1) continue; + NSString *orgFilename = ((PHAssetResource*)resources[0]).originalFilename; + NSString *uit = ((PHAssetResource*)resources[0]).uniformTypeIdentifier; + NSString *mimeType = (NSString *)CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(uit), kUTTagClassMIMEType)); + CFStringRef extension = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(uit), kUTTagClassFilenameExtension); + [result addObject:@{ + @"width": @([asset pixelWidth]), + @"height": @([asset pixelHeight]), + @"filename": orgFilename ?: @"", + @"mimeType": mimeType ?: @"", + @"id": [asset localIdentifier], + @"creationDate": [asset creationDate], + @"uri": [NSString stringWithFormat:@"ph://%@", [asset localIdentifier]], + @"duration": @([asset duration]) + }]; + } + + + [result addObject:@{ + @"count": @(assetsFetchResult.count) + }]; + resolve(result); +} static void checkPhotoLibraryConfig() { diff --git a/js/CameraRoll.js b/js/CameraRoll.js index a7a0f12f9..aa09c209b 100644 --- a/js/CameraRoll.js +++ b/js/CameraRoll.js @@ -242,6 +242,19 @@ class CameraRoll { return promise; } + /** + Returns total iOS image count + */ + static getPhotosCountiOS(): Promise { + return RNCCameraRoll.getPhotosCountiOS(''); + } + + /** + Returns favorites and their count iOS + */ + static getFavoritesiOS(): Promise { + return RNCCameraRoll.getFavoritesiOS(''); + } } module.exports = CameraRoll; diff --git a/typings/CameraRoll.d.ts b/typings/CameraRoll.d.ts index 7e254e89e..66e2f450f 100644 --- a/typings/CameraRoll.d.ts +++ b/typings/CameraRoll.d.ts @@ -154,6 +154,16 @@ declare namespace CameraRoll { */ function deletePhotos(photoUris: Array): Promise; + /** + * Returns the Camera Roll images count on iOS. + */ + function getPhotosCountiOS(): Promise; + + /** + * Returns the Camera Roll favorite images count on iOS. + */ + function getFavoritesiOS(): Promise; + /** * Saves the photo or video to the camera roll or photo library. */