2015-09-08 15:58:13 +00:00
|
|
|
/**
|
2018-09-11 22:27:47 +00:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2015-09-08 15:58:13 +00:00
|
|
|
*
|
2018-02-17 02:24:55 +00:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2015-09-08 15:58:13 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#import "RCTCameraRollManager.h"
|
|
|
|
|
|
|
|
#import <CoreLocation/CoreLocation.h>
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#import <UIKit/UIKit.h>
|
2017-11-29 20:07:49 +00:00
|
|
|
#import <Photos/Photos.h>
|
2018-06-19 20:18:51 +00:00
|
|
|
#import <dlfcn.h>
|
|
|
|
#import <objc/runtime.h>
|
2015-09-08 15:58:13 +00:00
|
|
|
|
2016-11-23 15:47:52 +00:00
|
|
|
#import <React/RCTBridge.h>
|
|
|
|
#import <React/RCTConvert.h>
|
|
|
|
#import <React/RCTImageLoader.h>
|
|
|
|
#import <React/RCTLog.h>
|
|
|
|
#import <React/RCTUtils.h>
|
|
|
|
|
2016-01-20 19:03:22 +00:00
|
|
|
#import "RCTAssetsLibraryRequestHandler.h"
|
2015-09-08 15:58:13 +00:00
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
@implementation RCTConvert (ALAssetGroup)
|
2015-11-03 22:45:46 +00:00
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
RCT_ENUM_CONVERTER(ALAssetsGroupType, (@{
|
2015-11-03 22:45:46 +00:00
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
// New values
|
|
|
|
@"album": @(ALAssetsGroupAlbum),
|
|
|
|
@"all": @(ALAssetsGroupAll),
|
|
|
|
@"event": @(ALAssetsGroupEvent),
|
|
|
|
@"faces": @(ALAssetsGroupFaces),
|
|
|
|
@"library": @(ALAssetsGroupLibrary),
|
|
|
|
@"photo-stream": @(ALAssetsGroupPhotoStream),
|
|
|
|
@"saved-photos": @(ALAssetsGroupSavedPhotos),
|
2015-11-03 22:45:46 +00:00
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
// Legacy values
|
|
|
|
@"Album": @(ALAssetsGroupAlbum),
|
|
|
|
@"All": @(ALAssetsGroupAll),
|
|
|
|
@"Event": @(ALAssetsGroupEvent),
|
|
|
|
@"Faces": @(ALAssetsGroupFaces),
|
|
|
|
@"Library": @(ALAssetsGroupLibrary),
|
|
|
|
@"PhotoStream": @(ALAssetsGroupPhotoStream),
|
|
|
|
@"SavedPhotos": @(ALAssetsGroupSavedPhotos),
|
2015-11-03 22:45:46 +00:00
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
}), ALAssetsGroupSavedPhotos, integerValue)
|
2018-06-19 20:18:51 +00:00
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
static Class _ALAssetsFilter = nil;
|
|
|
|
static NSString *_ALAssetsGroupPropertyName = nil;
|
|
|
|
static NSString *_ALAssetPropertyAssetURL = nil;
|
|
|
|
static NSString *_ALAssetPropertyLocation = nil;
|
|
|
|
static NSString *_ALAssetPropertyDate = nil;
|
|
|
|
static NSString *_ALAssetPropertyType = nil;
|
|
|
|
static NSString *_ALAssetPropertyDuration = nil;
|
|
|
|
static NSString *_ALAssetTypeVideo = nil;
|
|
|
|
static NSString *lookupNSString(void * handle, const char * name)
|
2015-11-03 22:45:46 +00:00
|
|
|
{
|
2018-12-22 08:16:33 +00:00
|
|
|
void ** sym = dlsym(handle, name);
|
|
|
|
return (__bridge NSString *)(sym ? *sym : nil);
|
|
|
|
}
|
|
|
|
static void ensureAssetsLibLoaded(void)
|
|
|
|
{
|
|
|
|
static dispatch_once_t onceToken;
|
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
|
void * handle = dlopen("/System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary", RTLD_LAZY);
|
|
|
|
RCTAssert(handle != NULL, @"Unable to load AssetsLibrary.framework.");
|
|
|
|
_ALAssetsFilter = objc_getClass("ALAssetsFilter");
|
|
|
|
_ALAssetsGroupPropertyName = lookupNSString(handle, "ALAssetsGroupPropertyName");
|
|
|
|
_ALAssetPropertyAssetURL = lookupNSString(handle, "ALAssetPropertyAssetURL");
|
|
|
|
_ALAssetPropertyLocation = lookupNSString(handle, "ALAssetPropertyLocation");
|
|
|
|
_ALAssetPropertyDate = lookupNSString(handle, "ALAssetPropertyDate");
|
|
|
|
_ALAssetPropertyType = lookupNSString(handle, "ALAssetPropertyType");
|
|
|
|
_ALAssetPropertyDuration = lookupNSString(handle, "ALAssetPropertyDuration");
|
|
|
|
_ALAssetTypeVideo = lookupNSString(handle, "ALAssetTypeVideo");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (ALAssetsFilter *)ALAssetsFilter:(id)json
|
|
|
|
{
|
|
|
|
static NSDictionary<NSString *, ALAssetsFilter *> *options;
|
|
|
|
static dispatch_once_t onceToken;
|
|
|
|
dispatch_once(&onceToken, ^{
|
|
|
|
ensureAssetsLibLoaded();
|
|
|
|
options = @{
|
|
|
|
// New values
|
|
|
|
@"photos": [_ALAssetsFilter allPhotos],
|
|
|
|
@"videos": [_ALAssetsFilter allVideos],
|
|
|
|
@"all": [_ALAssetsFilter allAssets],
|
|
|
|
|
|
|
|
// Legacy values
|
|
|
|
@"Photos": [_ALAssetsFilter allPhotos],
|
|
|
|
@"Videos": [_ALAssetsFilter allVideos],
|
|
|
|
@"All": [_ALAssetsFilter allAssets],
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
ALAssetsFilter *filter = options[json ?: @"photos"];
|
|
|
|
if (!filter) {
|
|
|
|
RCTLogError(@"Invalid filter option: '%@'. Expected one of 'photos',"
|
|
|
|
"'videos' or 'all'.", json);
|
2015-11-03 22:45:46 +00:00
|
|
|
}
|
2018-12-22 08:16:33 +00:00
|
|
|
return filter ?: [_ALAssetsFilter allPhotos];
|
2015-11-03 22:45:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2015-09-08 15:58:13 +00:00
|
|
|
@implementation RCTCameraRollManager
|
|
|
|
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
|
|
|
|
@synthesize bridge = _bridge;
|
|
|
|
|
2018-12-22 07:11:04 +00:00
|
|
|
static NSString *const kErrorUnableToLoad = @"E_UNABLE_TO_LOAD";
|
2018-12-22 08:16:33 +00:00
|
|
|
static NSString *const kErrorUnableToSave = @"E_UNABLE_TO_SAVE";
|
2016-01-21 16:07:01 +00:00
|
|
|
|
Allow CameraRoll to export videos
Summary:
This PR adds the ability to export videos to the CameraRoll on both Android and iOS (previously only photos were possible, at least on iOS). The API has changed as follows:
```
// old
saveImageWithTag(tag: string): Promise<string>
// new
saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<string>
```
if no `type` parameter is passed, `video` is inferred if the tag ends with ".mov" or ".mp4", otherwise `photo` is assumed.
I've left in the `saveImageWithTag` method for now with a deprecation warning.
**Test plan (required)**
I created the following very simple app to test exporting photos and videos to the CameraRoll, and ran it on both iOS and Android. The functionality works as intended on both platforms.
```js
// index.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
CameraRoll,
} from 'react-native';
import FS fro
Closes https://github.com/facebook/react-native/pull/7988
Differential Revision: D3401251
Pulled By: nicklockwood
fbshipit-source-id: af3fc24e6fa5b84ac377e9173f3709c6f9795f20
2016-06-07 23:37:48 +00:00
|
|
|
RCT_EXPORT_METHOD(saveToCameraRoll:(NSURLRequest *)request
|
|
|
|
type:(NSString *)type
|
2016-01-21 16:07:01 +00:00
|
|
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
|
|
reject:(RCTPromiseRejectBlock)reject)
|
2015-09-08 15:58:13 +00:00
|
|
|
{
|
Allow CameraRoll to export videos
Summary:
This PR adds the ability to export videos to the CameraRoll on both Android and iOS (previously only photos were possible, at least on iOS). The API has changed as follows:
```
// old
saveImageWithTag(tag: string): Promise<string>
// new
saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<string>
```
if no `type` parameter is passed, `video` is inferred if the tag ends with ".mov" or ".mp4", otherwise `photo` is assumed.
I've left in the `saveImageWithTag` method for now with a deprecation warning.
**Test plan (required)**
I created the following very simple app to test exporting photos and videos to the CameraRoll, and ran it on both iOS and Android. The functionality works as intended on both platforms.
```js
// index.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
CameraRoll,
} from 'react-native';
import FS fro
Closes https://github.com/facebook/react-native/pull/7988
Differential Revision: D3401251
Pulled By: nicklockwood
fbshipit-source-id: af3fc24e6fa5b84ac377e9173f3709c6f9795f20
2016-06-07 23:37:48 +00:00
|
|
|
if ([type isEqualToString:@"video"]) {
|
2018-12-22 08:16:33 +00:00
|
|
|
// It's unclear if writeVideoAtPathToSavedPhotosAlbum is thread-safe
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self->_bridge.assetsLibrary writeVideoAtPathToSavedPhotosAlbum:request.URL completionBlock:^(NSURL *assetURL, NSError *saveError) {
|
|
|
|
if (saveError) {
|
|
|
|
reject(kErrorUnableToSave, nil, saveError);
|
|
|
|
} else {
|
|
|
|
resolve(assetURL.absoluteString);
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
});
|
Allow CameraRoll to export videos
Summary:
This PR adds the ability to export videos to the CameraRoll on both Android and iOS (previously only photos were possible, at least on iOS). The API has changed as follows:
```
// old
saveImageWithTag(tag: string): Promise<string>
// new
saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<string>
```
if no `type` parameter is passed, `video` is inferred if the tag ends with ".mov" or ".mp4", otherwise `photo` is assumed.
I've left in the `saveImageWithTag` method for now with a deprecation warning.
**Test plan (required)**
I created the following very simple app to test exporting photos and videos to the CameraRoll, and ran it on both iOS and Android. The functionality works as intended on both platforms.
```js
// index.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
CameraRoll,
} from 'react-native';
import FS fro
Closes https://github.com/facebook/react-native/pull/7988
Differential Revision: D3401251
Pulled By: nicklockwood
fbshipit-source-id: af3fc24e6fa5b84ac377e9173f3709c6f9795f20
2016-06-07 23:37:48 +00:00
|
|
|
} else {
|
2018-12-22 08:16:33 +00:00
|
|
|
[_bridge.imageLoader loadImageWithURLRequest:request
|
|
|
|
callback:^(NSError *loadError, UIImage *loadedImage) {
|
|
|
|
if (loadError) {
|
|
|
|
reject(kErrorUnableToLoad, nil, loadError);
|
Allow CameraRoll to export videos
Summary:
This PR adds the ability to export videos to the CameraRoll on both Android and iOS (previously only photos were possible, at least on iOS). The API has changed as follows:
```
// old
saveImageWithTag(tag: string): Promise<string>
// new
saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<string>
```
if no `type` parameter is passed, `video` is inferred if the tag ends with ".mov" or ".mp4", otherwise `photo` is assumed.
I've left in the `saveImageWithTag` method for now with a deprecation warning.
**Test plan (required)**
I created the following very simple app to test exporting photos and videos to the CameraRoll, and ran it on both iOS and Android. The functionality works as intended on both platforms.
```js
// index.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
CameraRoll,
} from 'react-native';
import FS fro
Closes https://github.com/facebook/react-native/pull/7988
Differential Revision: D3401251
Pulled By: nicklockwood
fbshipit-source-id: af3fc24e6fa5b84ac377e9173f3709c6f9795f20
2016-06-07 23:37:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-12-22 08:16:33 +00:00
|
|
|
// It's unclear if writeImageToSavedPhotosAlbum is thread-safe
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
[self->_bridge.assetsLibrary writeImageToSavedPhotosAlbum:loadedImage.CGImage metadata:nil completionBlock:^(NSURL *assetURL, NSError *saveError) {
|
|
|
|
if (saveError) {
|
|
|
|
RCTLogWarn(@"Error saving cropped image: %@", saveError);
|
|
|
|
reject(kErrorUnableToSave, nil, saveError);
|
|
|
|
} else {
|
|
|
|
resolve(assetURL.absoluteString);
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
});
|
Allow CameraRoll to export videos
Summary:
This PR adds the ability to export videos to the CameraRoll on both Android and iOS (previously only photos were possible, at least on iOS). The API has changed as follows:
```
// old
saveImageWithTag(tag: string): Promise<string>
// new
saveToCameraRoll(tag: string, type?: 'photo' | 'video'): Promise<string>
```
if no `type` parameter is passed, `video` is inferred if the tag ends with ".mov" or ".mp4", otherwise `photo` is assumed.
I've left in the `saveImageWithTag` method for now with a deprecation warning.
**Test plan (required)**
I created the following very simple app to test exporting photos and videos to the CameraRoll, and ran it on both iOS and Android. The functionality works as intended on both platforms.
```js
// index.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
CameraRoll,
} from 'react-native';
import FS fro
Closes https://github.com/facebook/react-native/pull/7988
Differential Revision: D3401251
Pulled By: nicklockwood
fbshipit-source-id: af3fc24e6fa5b84ac377e9173f3709c6f9795f20
2016-06-07 23:37:48 +00:00
|
|
|
}];
|
|
|
|
}
|
2015-09-08 15:58:13 +00:00
|
|
|
}
|
|
|
|
|
2016-01-21 16:07:01 +00:00
|
|
|
static void RCTResolvePromise(RCTPromiseResolveBlock resolve,
|
|
|
|
NSArray<NSDictionary<NSString *, id> *> *assets,
|
|
|
|
BOOL hasNextPage)
|
2015-09-08 15:58:13 +00:00
|
|
|
{
|
|
|
|
if (!assets.count) {
|
2016-02-10 15:24:38 +00:00
|
|
|
resolve(@{
|
2015-11-14 18:25:00 +00:00
|
|
|
@"edges": assets,
|
|
|
|
@"page_info": @{
|
|
|
|
@"has_next_page": @NO,
|
|
|
|
}
|
2016-02-10 15:24:38 +00:00
|
|
|
});
|
2015-09-08 15:58:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-02-10 15:24:38 +00:00
|
|
|
resolve(@{
|
2015-11-14 18:25:00 +00:00
|
|
|
@"edges": assets,
|
|
|
|
@"page_info": @{
|
|
|
|
@"start_cursor": assets[0][@"node"][@"image"][@"uri"],
|
|
|
|
@"end_cursor": assets[assets.count - 1][@"node"][@"image"][@"uri"],
|
|
|
|
@"has_next_page": @(hasNextPage),
|
|
|
|
}
|
2016-02-10 15:24:38 +00:00
|
|
|
});
|
2015-09-08 15:58:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params
|
2016-01-21 16:07:01 +00:00
|
|
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
|
|
reject:(RCTPromiseRejectBlock)reject)
|
2015-09-08 15:58:13 +00:00
|
|
|
{
|
2016-08-18 14:16:26 +00:00
|
|
|
checkPhotoLibraryConfig();
|
|
|
|
|
2018-12-22 08:16:33 +00:00
|
|
|
ensureAssetsLibLoaded();
|
|
|
|
NSUInteger first = [RCTConvert NSInteger:params[@"first"]];
|
|
|
|
NSString *afterCursor = [RCTConvert NSString:params[@"after"]];
|
|
|
|
NSString *groupName = [RCTConvert NSString:params[@"groupName"]];
|
|
|
|
ALAssetsFilter *assetType = [RCTConvert ALAssetsFilter:params[@"assetType"]];
|
|
|
|
ALAssetsGroupType groupTypes = [RCTConvert ALAssetsGroupType:params[@"groupTypes"]];
|
2015-09-08 15:58:13 +00:00
|
|
|
|
|
|
|
BOOL __block foundAfter = NO;
|
|
|
|
BOOL __block hasNextPage = NO;
|
2016-01-21 16:07:01 +00:00
|
|
|
BOOL __block resolvedPromise = NO;
|
2015-11-14 18:25:00 +00:00
|
|
|
NSMutableArray<NSDictionary<NSString *, id> *> *assets = [NSMutableArray new];
|
2018-12-22 08:16:33 +00:00
|
|
|
|
|
|
|
[_bridge.assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) {
|
|
|
|
if (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:_ALAssetsGroupPropertyName]])) {
|
|
|
|
|
|
|
|
[group setAssetsFilter:assetType];
|
|
|
|
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopAssets) {
|
|
|
|
if (result) {
|
|
|
|
NSString *uri = ((NSURL *)[result valueForProperty:_ALAssetPropertyAssetURL]).absoluteString;
|
|
|
|
if (afterCursor && !foundAfter) {
|
|
|
|
if ([afterCursor isEqualToString:uri]) {
|
|
|
|
foundAfter = YES;
|
|
|
|
}
|
|
|
|
return; // Skip until we get to the first one
|
2017-07-15 00:33:52 +00:00
|
|
|
}
|
2018-12-22 08:16:33 +00:00
|
|
|
if (first == assets.count) {
|
|
|
|
*stopAssets = YES;
|
|
|
|
*stopGroups = YES;
|
|
|
|
hasNextPage = YES;
|
|
|
|
RCTAssert(resolvedPromise == NO, @"Resolved the promise before we finished processing the results.");
|
|
|
|
RCTResolvePromise(resolve, assets, hasNextPage);
|
|
|
|
resolvedPromise = YES;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CGSize dimensions = [result defaultRepresentation].dimensions;
|
|
|
|
CLLocation *loc = [result valueForProperty:_ALAssetPropertyLocation];
|
|
|
|
NSDate *date = [result valueForProperty:_ALAssetPropertyDate];
|
|
|
|
NSString *filename = [result defaultRepresentation].filename;
|
|
|
|
int64_t duration = 0;
|
|
|
|
if ([[result valueForProperty:_ALAssetPropertyType] isEqualToString:_ALAssetTypeVideo]) {
|
|
|
|
duration = [[result valueForProperty:_ALAssetPropertyDuration] intValue];
|
|
|
|
}
|
|
|
|
|
|
|
|
[assets addObject:@{
|
|
|
|
@"node": @{
|
|
|
|
@"type": [result valueForProperty:_ALAssetPropertyType],
|
|
|
|
@"group_name": [group valueForProperty:_ALAssetsGroupPropertyName],
|
|
|
|
@"image": @{
|
|
|
|
@"uri": uri,
|
|
|
|
@"filename" : filename ?: [NSNull null],
|
|
|
|
@"height": @(dimensions.height),
|
|
|
|
@"width": @(dimensions.width),
|
|
|
|
@"isStored": @YES,
|
|
|
|
@"playableDuration": @(duration),
|
|
|
|
},
|
|
|
|
@"timestamp": @(date.timeIntervalSince1970),
|
|
|
|
@"location": loc ? @{
|
|
|
|
@"latitude": @(loc.coordinate.latitude),
|
|
|
|
@"longitude": @(loc.coordinate.longitude),
|
|
|
|
@"altitude": @(loc.altitude),
|
|
|
|
@"heading": @(loc.course),
|
|
|
|
@"speed": @(loc.speed),
|
|
|
|
} : @{},
|
|
|
|
}
|
|
|
|
}];
|
2015-09-08 15:58:13 +00:00
|
|
|
}
|
2018-12-22 08:16:33 +00:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!group) {
|
|
|
|
// Sometimes the enumeration continues even if we set stop above, so we guard against resolving the promise
|
|
|
|
// multiple times here.
|
|
|
|
if (!resolvedPromise) {
|
2016-01-21 16:07:01 +00:00
|
|
|
RCTResolvePromise(resolve, assets, hasNextPage);
|
|
|
|
resolvedPromise = YES;
|
2015-09-08 15:58:13 +00:00
|
|
|
}
|
2018-12-22 08:16:33 +00:00
|
|
|
}
|
|
|
|
} failureBlock:^(NSError *error) {
|
|
|
|
if (error.code != ALAssetsLibraryAccessUserDeniedError) {
|
|
|
|
RCTLogError(@"Failure while iterating through asset groups %@", error);
|
|
|
|
}
|
|
|
|
reject(kErrorUnableToLoad, nil, error);
|
2015-09-08 15:58:13 +00:00
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
2017-11-29 20:07:49 +00:00
|
|
|
RCT_EXPORT_METHOD(deletePhotos:(NSArray<NSString *>*)assets
|
|
|
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
|
|
reject:(RCTPromiseRejectBlock)reject)
|
|
|
|
{
|
|
|
|
NSArray<NSURL *> *assets_ = [RCTConvert NSURLArray:assets];
|
|
|
|
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
|
|
|
|
PHFetchResult<PHAsset *> *fetched =
|
|
|
|
[PHAsset fetchAssetsWithALAssetURLs:assets_ options:nil];
|
|
|
|
[PHAssetChangeRequest deleteAssets:fetched];
|
|
|
|
}
|
|
|
|
completionHandler:^(BOOL success, NSError *error) {
|
|
|
|
if (success == YES) {
|
|
|
|
resolve(@(success));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
reject(@"Couldn't delete", @"Couldn't delete assets", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2016-08-18 14:16:26 +00:00
|
|
|
static void checkPhotoLibraryConfig()
|
|
|
|
{
|
|
|
|
#if RCT_DEV
|
|
|
|
if (![[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSPhotoLibraryUsageDescription"]) {
|
|
|
|
RCTLogError(@"NSPhotoLibraryUsageDescription key must be present in Info.plist to use camera roll.");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-09-08 15:58:13 +00:00
|
|
|
@end
|