mirror of
https://github.com/status-im/react-native-cameraroll.git
synced 2025-01-27 01:52:11 +00:00
feat: get album list (#139)
This commit is contained in:
parent
f3fc48d150
commit
fc1855e001
22
README.md
22
README.md
@ -75,6 +75,7 @@ On Android permission is required to read the external storage. Add below line t
|
|||||||
|
|
||||||
* [`saveToCameraRoll`](#savetocameraroll)
|
* [`saveToCameraRoll`](#savetocameraroll)
|
||||||
* [`save`](#save)
|
* [`save`](#save)
|
||||||
|
* [`getAlbums`](#getalbums)
|
||||||
* [`getPhotos`](#getphotos)
|
* [`getPhotos`](#getphotos)
|
||||||
* [`deletePhotos`](#deletephotos)
|
* [`deletePhotos`](#deletephotos)
|
||||||
|
|
||||||
@ -115,6 +116,27 @@ Returns a Promise which will resolve with the new URI.
|
|||||||
| tag | string | Yes | See above. |
|
| tag | string | Yes | See above. |
|
||||||
| type | enum('photo', 'video') | No | Overrides automatic detection based on the file extension. |
|
| 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()`
|
### `getPhotos()`
|
||||||
|
@ -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) {
|
private static void putPageInfo(Cursor media, WritableMap response, int limit, int offset) {
|
||||||
WritableMap pageInfo = new WritableNativeMap();
|
WritableMap pageInfo = new WritableNativeMap();
|
||||||
pageInfo.putBoolean("has_next_page", limit < media.getCount());
|
pageInfo.putBoolean("has_next_page", limit < media.getCount());
|
||||||
|
@ -196,6 +196,28 @@ RCT_EXPORT_METHOD(saveToCameraRoll:(NSURLRequest *)request
|
|||||||
requestPhotoLibraryAccess(reject, loadBlock);
|
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,
|
static void RCTResolvePromise(RCTPromiseResolveBlock resolve,
|
||||||
NSArray<NSDictionary<NSString *, id> *> *assets,
|
NSArray<NSDictionary<NSString *, id> *> *assets,
|
||||||
BOOL hasNextPage)
|
BOOL hasNextPage)
|
||||||
|
@ -104,6 +104,15 @@ export type SaveToCameraRollOptions = {
|
|||||||
type?: 'photo' | 'video' | 'auto',
|
type?: 'photo' | 'video' | 'auto',
|
||||||
album?: string,
|
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.
|
* `CameraRoll` provides access to the local camera roll or photo library.
|
||||||
*
|
*
|
||||||
@ -168,6 +177,9 @@ class CameraRoll {
|
|||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return CameraRoll.save(tag, {type});
|
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
|
* Returns a Promise with photo identifier objects from the local camera
|
||||||
* roll of the device matching shape defined by `getPhotosReturnChecker`.
|
* roll of the device matching shape defined by `getPhotosReturnChecker`.
|
||||||
|
11
typings/CameraRoll.d.ts
vendored
11
typings/CameraRoll.d.ts
vendored
@ -62,6 +62,15 @@ declare namespace CameraRoll {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GetAlbumsParams {
|
||||||
|
assetType?: AssetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Album {
|
||||||
|
title: string;
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
type SaveToCameraRollOptions = {
|
type SaveToCameraRollOptions = {
|
||||||
type?: 'photo' | 'video' | 'auto',
|
type?: 'photo' | 'video' | 'auto',
|
||||||
album?: string,
|
album?: string,
|
||||||
@ -92,6 +101,8 @@ declare namespace CameraRoll {
|
|||||||
* roll of the device matching shape defined by `getPhotosReturnChecker`.
|
* roll of the device matching shape defined by `getPhotosReturnChecker`.
|
||||||
*/
|
*/
|
||||||
function getPhotos(params: GetPhotosParams): Promise<PhotoIdentifiersPage>;
|
function getPhotos(params: GetPhotosParams): Promise<PhotoIdentifiersPage>;
|
||||||
|
|
||||||
|
function getAlbums(params: GetAlbumsParams): Promise<Album[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export = CameraRoll;
|
export = CameraRoll;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user