feat: get album list (#139)

This commit is contained in:
Tuan Luong 2020-02-08 10:17:56 +07:00 committed by GitHub
parent f3fc48d150
commit fc1855e001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 0 deletions

View File

@ -75,6 +75,7 @@ On Android permission is required to read the external storage. Add below line t
* [`saveToCameraRoll`](#savetocameraroll)
* [`save`](#save)
* [`getAlbums`](#getalbums)
* [`getPhotos`](#getphotos)
* [`deletePhotos`](#deletephotos)
@ -115,6 +116,27 @@ Returns a Promise which will resolve with the new URI.
| tag | string | Yes | See above. |
| type | enum('photo', 'video') | No | Overrides automatic detection based on the file extension. |
---
### `getAlbums()`
```javascript
CameraRoll.getAlbums(params);
```
Returns a Promise with a list of albums
**Parameters:**
* `assetType` : {string} : Specifies filter on asset type. Valid values are:
* `All` // default
* `Videos`
* `Photos`
**Returns:**
Array of `Album` object
* title: {string}
* count: {number}
---
### `getPhotos()`

View File

@ -370,6 +370,68 @@ public class CameraRollModule extends ReactContextBaseJavaModule {
}
}
@ReactMethod
public void getAlbums(final ReadableMap params, final Promise promise) {
String assetType = params.hasKey("assetType") ? params.getString("assetType") : ASSET_TYPE_ALL;
StringBuilder selection = new StringBuilder("1");
List<String> selectionArgs = new ArrayList<>();
String bucketDisplayName = MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME;
if (assetType.equals(ASSET_TYPE_PHOTOS)) {
selection.append(" AND " + MediaStore.Files.FileColumns.MEDIA_TYPE + " = "
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);
} else if (assetType.equals(ASSET_TYPE_VIDEOS)) {
selection.append(" AND " + MediaStore.Files.FileColumns.MEDIA_TYPE + " = "
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO);
bucketDisplayName = MediaStore.Video.VideoColumns.BUCKET_DISPLAY_NAME;
} else if (assetType.equals(ASSET_TYPE_ALL)) {
selection.append(" AND " + MediaStore.Files.FileColumns.MEDIA_TYPE + " IN ("
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO + ","
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE + ")");
} else {
promise.reject(
ERROR_UNABLE_TO_FILTER,
"Invalid filter option: '" + assetType + "'. Expected one of '"
+ ASSET_TYPE_PHOTOS + "', '" + ASSET_TYPE_VIDEOS + "' or '" + ASSET_TYPE_ALL + "'."
);
return;
}
selection.append(") GROUP BY (").append(bucketDisplayName);
String[] projection = new String[]{
"COUNT(*) as count",
bucketDisplayName,
MediaStore.Images.ImageColumns.DATA
};
try {
Cursor media = getReactApplicationContext().getContentResolver().query(
MediaStore.Files.getContentUri("external").buildUpon().build(),
projection,
selection.toString(),
selectionArgs.toArray(new String[selectionArgs.size()]),
null);
if (media == null) {
promise.reject(ERROR_UNABLE_TO_LOAD, "Could not get media");
} else {
WritableArray response = new WritableNativeArray();
try {
if (media.moveToFirst()) {
do {
String albumName = media.getString(media.getColumnIndex(bucketDisplayName));
int count = media.getInt(media.getColumnIndex("count"));
WritableMap album = new WritableNativeMap();
album.putString("title", albumName);
album.putInt("count", count);
response.pushMap(album);
} while (media.moveToNext());
}
} finally {
media.close();
promise.resolve(response);
}
}
} catch (Exception e) {}
}
private static void putPageInfo(Cursor media, WritableMap response, int limit, int offset) {
WritableMap pageInfo = new WritableNativeMap();
pageInfo.putBoolean("has_next_page", limit < media.getCount());

View File

@ -196,6 +196,28 @@ RCT_EXPORT_METHOD(saveToCameraRoll:(NSURLRequest *)request
requestPhotoLibraryAccess(reject, loadBlock);
}
RCT_EXPORT_METHOD(getAlbums:(NSDictionary *)params
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
NSString *const mediaType = [params objectForKey:@"assetType"] ? [RCTConvert NSString:params[@"assetType"]] : @"All";
PHFetchOptions* options = [[PHFetchOptions alloc] init];
PHFetchResult<PHAssetCollection *> *const assetCollectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:options];
NSMutableArray * result = [NSMutableArray new];
[assetCollectionFetchResult enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PHFetchOptions *const assetFetchOptions = [RCTConvert PHFetchOptionsFromMediaType:mediaType fromTime:0 toTime:0];
// Enumerate assets within the collection
PHFetchResult<PHAsset *> *const assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:obj options:assetFetchOptions];
if (assetsFetchResult.count > 0) {
[result addObject:@{
@"title": [obj localizedTitle],
@"count": @(assetsFetchResult.count)
}];
}
}];
resolve(result);
}
static void RCTResolvePromise(RCTPromiseResolveBlock resolve,
NSArray<NSDictionary<NSString *, id> *> *assets,
BOOL hasNextPage)

View File

@ -104,6 +104,15 @@ export type SaveToCameraRollOptions = {
type?: 'photo' | 'video' | 'auto',
album?: string,
};
export type GetAlbumsParams = {
assetType?: $Keys<typeof ASSET_TYPE_OPTIONS>,
}
export type Album = {
title: string,
count: number,
}
/**
* `CameraRoll` provides access to the local camera roll or photo library.
*
@ -168,6 +177,9 @@ class CameraRoll {
): Promise<string> {
return CameraRoll.save(tag, {type});
}
static getAlbums(params?: GetAlbumsParams = { assetType: ASSET_TYPE_OPTIONS.All }): Promise<Album[]> {
return RNCCameraRoll.getAlbums(params);
}
/**
* Returns a Promise with photo identifier objects from the local camera
* roll of the device matching shape defined by `getPhotosReturnChecker`.

View File

@ -62,6 +62,15 @@ declare namespace CameraRoll {
};
}
interface GetAlbumsParams {
assetType?: AssetType;
}
interface Album {
title: string;
count: number;
}
type SaveToCameraRollOptions = {
type?: 'photo' | 'video' | 'auto',
album?: string,
@ -92,6 +101,8 @@ declare namespace CameraRoll {
* roll of the device matching shape defined by `getPhotosReturnChecker`.
*/
function getPhotos(params: GetPhotosParams): Promise<PhotoIdentifiersPage>;
function getAlbums(params: GetAlbumsParams): Promise<Album[]>;
}
export = CameraRoll;