From 75b42084749b87686f6880b6a6f956b89896cd34 Mon Sep 17 00:00:00 2001 From: Tuan Luong Date: Wed, 5 Feb 2020 16:20:54 +0700 Subject: [PATCH] feat: Support filter media items between dates (#140) * Update RNCCameraRollManager.m * Update CameraRollModule.java * Update README.md * Update RNCCameraRollManager.m * Update CameraRoll.d.ts * Update RNCCameraRollManager.h * Update CameraRollModule.java * Update RNCCameraRollManager.m * update code --- README.md | 2 + .../cameraroll/CameraRollModule.java | 19 +++++++++ ios/RNCCameraRollManager.h | 4 +- ios/RNCCameraRollManager.m | 39 ++++++++++++++----- typings/CameraRoll.d.ts | 2 + 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b4eb74d94..3a3705336 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,8 @@ Returns a Promise with photo identifier objects from the local camera roll of th * `Videos` * `Photos` // default * `mimeTypes` : {Array} : Filter by mimetype (e.g. image/jpeg). +* `fromTime` : {timestamp} : Filter from date added. +* `toTime` : {timestamp} : Filter to date added. Returns a Promise which when resolved will be of the following shape: diff --git a/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java b/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java index 532513300..e320ba4d5 100644 --- a/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java +++ b/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java @@ -234,6 +234,8 @@ public class CameraRollModule extends ReactContextBaseJavaModule { String after = params.hasKey("after") ? params.getString("after") : null; String groupName = params.hasKey("groupName") ? params.getString("groupName") : null; String assetType = params.hasKey("assetType") ? params.getString("assetType") : ASSET_TYPE_PHOTOS; + long fromTime = params.hasKey("fromTime") ? (long) params.getDouble("fromTime") : 0; + long toTime = params.hasKey("toTime") ? (long) params.getDouble("toTime") : 0; ReadableArray mimeTypes = params.hasKey("mimeTypes") ? params.getArray("mimeTypes") : null; @@ -245,6 +247,8 @@ public class CameraRollModule extends ReactContextBaseJavaModule { groupName, mimeTypes, assetType, + fromTime, + toTime, promise) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -257,6 +261,8 @@ public class CameraRollModule extends ReactContextBaseJavaModule { private final @Nullable ReadableArray mMimeTypes; private final Promise mPromise; private final String mAssetType; + private final long mFromTime; + private final long mToTime; private GetMediaTask( ReactContext context, @@ -265,6 +271,8 @@ public class CameraRollModule extends ReactContextBaseJavaModule { @Nullable String groupName, @Nullable ReadableArray mimeTypes, String assetType, + long fromTime, + long toTime, Promise promise) { super(context); mContext = context; @@ -274,6 +282,8 @@ public class CameraRollModule extends ReactContextBaseJavaModule { mMimeTypes = mimeTypes; mPromise = promise; mAssetType = assetType; + mFromTime = fromTime; + mToTime = toTime; } @Override @@ -314,6 +324,15 @@ public class CameraRollModule extends ReactContextBaseJavaModule { selection.replace(selection.length() - 1, selection.length(), ")"); } + if (mFromTime > 0) { + selection.append(" AND " + Images.Media.DATE_TAKEN + " > ?"); + selectionArgs.add(mFromTime + ""); + } + if (mToTime > 0) { + selection.append(" AND " + Images.Media.DATE_TAKEN + " <= ?"); + selectionArgs.add(mToTime + ""); + } + WritableMap response = new WritableNativeMap(); ContentResolver resolver = mContext.getContentResolver(); diff --git a/ios/RNCCameraRollManager.h b/ios/RNCCameraRollManager.h index a011b5589..8b3b4c566 100644 --- a/ios/RNCCameraRollManager.h +++ b/ios/RNCCameraRollManager.h @@ -12,7 +12,9 @@ @interface RCTConvert (PHFetchOptions) -+ (PHFetchOptions *)PHFetchOptionsFromMediaType:(NSString *)mediaType; ++ (PHFetchOptions *)PHFetchOptionsFromMediaType:(NSString *)mediaType + fromTime:(NSUInteger)fromTime + toTime:(NSUInteger)toTime; @end diff --git a/ios/RNCCameraRollManager.m b/ios/RNCCameraRollManager.m index 022568049..7a879cdb5 100644 --- a/ios/RNCCameraRollManager.m +++ b/ios/RNCCameraRollManager.m @@ -43,27 +43,44 @@ RCT_ENUM_CONVERTER(PHAssetCollectionSubtype, (@{ @implementation RCTConvert (PHFetchOptions) + (PHFetchOptions *)PHFetchOptionsFromMediaType:(NSString *)mediaType + fromTime:(NSUInteger)fromTime + toTime:(NSUInteger)toTime { // This is not exhaustive in terms of supported media type predicates; more can be added in the future NSString *const lowercase = [mediaType lowercaseString]; + NSMutableArray *format = [NSMutableArray new]; + NSMutableArray *arguments = [NSMutableArray new]; if ([lowercase isEqualToString:@"photos"]) { - PHFetchOptions *const options = [PHFetchOptions new]; - options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d", PHAssetMediaTypeImage]; - return options; + [format addObject:@"mediaType = %d"]; + [arguments addObject:@(PHAssetMediaTypeImage)]; } else if ([lowercase isEqualToString:@"videos"]) { - PHFetchOptions *const options = [PHFetchOptions new]; - options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d", PHAssetMediaTypeVideo]; - return options; + [format addObject:@"mediaType = %d"]; + [arguments addObject:@(PHAssetMediaTypeVideo)]; } else { if (![lowercase isEqualToString:@"all"]) { RCTLogError(@"Invalid filter option: '%@'. Expected one of 'photos'," "'videos' or 'all'.", mediaType); } - // This case includes the "all" mediatype - PHFetchOptions *const options = [PHFetchOptions new]; - return options; } + + if (fromTime > 0) { + NSDate* fromDate = [NSDate dateWithTimeIntervalSince1970:fromTime/1000]; + [format addObject:@"creationDate > %@"]; + [arguments addObject:fromDate]; + } + if (toTime > 0) { + NSDate* toDate = [NSDate dateWithTimeIntervalSince1970:toTime/1000]; + [format addObject:@"creationDate < %@"]; + [arguments addObject:toDate]; + } + + // This case includes the "all" mediatype + PHFetchOptions *const options = [PHFetchOptions new]; + if ([format count] > 0) { + options.predicate = [NSPredicate predicateWithFormat:[format componentsJoinedByString:@" AND "] argumentArray:arguments]; + } + return options; } @end @@ -225,6 +242,8 @@ RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params NSString *const groupName = [RCTConvert NSString:params[@"groupName"]]; NSString *const groupTypes = [[RCTConvert NSString:params[@"groupTypes"]] lowercaseString]; NSString *const mediaType = [RCTConvert NSString:params[@"assetType"]]; + NSUInteger const fromTime = [RCTConvert NSInteger:params[@"fromTime"]]; + NSUInteger const toTime = [RCTConvert NSInteger:params[@"toTime"]]; NSArray *const mimeTypes = [RCTConvert NSStringArray:params[@"mimeTypes"]]; // If groupTypes is "all", we want to fetch the SmartAlbum "all photos". Otherwise, all @@ -235,7 +254,7 @@ RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params PHAssetCollectionSubtype const collectionSubtype = [RCTConvert PHAssetCollectionSubtype:groupTypes]; // Predicate for fetching assets within a collection - PHFetchOptions *const assetFetchOptions = [RCTConvert PHFetchOptionsFromMediaType:mediaType]; + PHFetchOptions *const assetFetchOptions = [RCTConvert PHFetchOptionsFromMediaType:mediaType fromTime:fromTime toTime:toTime]; assetFetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; BOOL __block foundAfter = NO; diff --git a/typings/CameraRoll.d.ts b/typings/CameraRoll.d.ts index d3247a71a..576ce196d 100644 --- a/typings/CameraRoll.d.ts +++ b/typings/CameraRoll.d.ts @@ -26,6 +26,8 @@ declare namespace CameraRoll { groupName?: string; assetType?: AssetType; mimeTypes?: Array; + fromTime?: number; + toTime?: number; } interface PhotoIdentifier {