Move iOS CameraRoll files into FB internal

Summary:
This moves ios CameraRoll files from React Native open source into FB internal as part of the Lean Core effort.

Changelog: [Breaking][ios] Remove CameraRoll from React Native

Reviewed By: cpojer

Differential Revision: D22208352

fbshipit-source-id: 894d6aff34ece94648dad68060c13b44974c93bb
This commit is contained in:
Sean Wang
2020-07-06 20:22:25 -07:00
committed by Facebook GitHub Bot
parent ac0f4b42c5
commit 824d3a9770
15 changed files with 0 additions and 1557 deletions
@@ -1,73 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
'use strict';
import type {TurboModule} from '../TurboModule/RCTExport';
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
export type PhotoIdentifier = {|
node: {|
image: PhotoIdentifierImage,
type: string,
group_name: string,
timestamp: number,
location: {|
longitude: number,
latitude: number,
// iOS Only
altitude: ?number,
heading: ?number,
speed: ?number,
|},
|},
|};
export type PhotoIdentifierImage = {|
uri: string,
playableDuration: number,
width: number,
height: number,
isStored: ?boolean,
filename: ?string,
|};
export type PhotoIdentifiersPage = {|
edges: Array<PhotoIdentifier>,
page_info: {|
has_next_page: boolean,
start_cursor?: ?string,
end_cursor?: ?string,
|},
|};
export type GetPhotosParams = {|
first: number,
after?: ?string,
groupName?: ?string,
groupTypes?: ?string,
assetType?: ?string,
maxSize?: ?number,
mimeTypes?: ?Array<string>,
|};
export interface Spec extends TurboModule {
+getConstants: () => {||};
+getPhotos: (params: GetPhotosParams) => Promise<PhotoIdentifiersPage>;
+saveToCameraRoll: (uri: string, type: string) => Promise<string>;
// iOS Only
+deletePhotos: (assets: Array<string>) => Promise<boolean>;
}
export default (TurboModuleRegistry.getEnforcing<Spec>(
'CameraRollManager',
): Spec);
@@ -1,15 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTBridge.h>
#import <React/RCTURLRequestHandler.h>
@class PHPhotoLibrary;
@interface RCTAssetsLibraryRequestHandler : NSObject <RCTURLRequestHandler>
@end
@@ -1,172 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTAssetsLibraryRequestHandler.h"
#import <atomic>
#import <dlfcn.h>
#import <memory>
#import <objc/runtime.h>
#import <Photos/Photos.h>
#import <MobileCoreServices/MobileCoreServices.h>
#import <React/RCTBridge.h>
#import <React/RCTNetworking.h>
#import <React/RCTUtils.h>
#import <ReactCommon/RCTTurboModule.h>
#import "RCTCameraRollPlugins.h"
@interface RCTAssetsLibraryRequestHandler() <RCTTurboModule>
@end
@implementation RCTAssetsLibraryRequestHandler
RCT_EXPORT_MODULE()
#pragma mark - RCTURLRequestHandler
- (BOOL)canHandleRequest:(NSURLRequest *)request
{
if (![PHAsset class]) {
return NO;
}
return [request.URL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame
|| [request.URL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame
|| [request.URL.scheme caseInsensitiveCompare:RCTNetworkingPHUploadHackScheme] == NSOrderedSame;
}
- (id)sendRequest:(NSURLRequest *)request
withDelegate:(id<RCTURLRequestDelegate>)delegate
{
auto cancelled = std::make_shared<std::atomic<bool>>(false);
void (^cancellationBlock)(void) = ^{
cancelled->store(true);
};
NSURL *requestURL = request.URL;
BOOL isPHUpload = [requestURL.scheme caseInsensitiveCompare:RCTNetworkingPHUploadHackScheme] == NSOrderedSame;
if (isPHUpload) {
requestURL = [NSURL URLWithString:[@"ph" stringByAppendingString:[requestURL.absoluteString substringFromIndex:RCTNetworkingPHUploadHackScheme.length]]];
}
if (!requestURL) {
NSString *const msg = [NSString stringWithFormat:@"Cannot send request without URL"];
[delegate URLRequest:cancellationBlock didCompleteWithError:RCTErrorWithMessage(msg)];
return cancellationBlock;
}
PHFetchResult<PHAsset *> *fetchResult;
if ([requestURL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame) {
// Fetch assets using PHAsset localIdentifier (recommended)
NSString *const localIdentifier = [requestURL.absoluteString substringFromIndex:@"ph://".length];
fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil];
} else if ([requestURL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
// This is the older, deprecated way of fetching assets from assets-library
// using the "assets-library://" protocol
fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[requestURL] options:nil];
} else {
NSString *const msg = [NSString stringWithFormat:@"Cannot send request with unknown protocol: %@", requestURL];
[delegate URLRequest:cancellationBlock didCompleteWithError:RCTErrorWithMessage(msg)];
return cancellationBlock;
}
if (![fetchResult firstObject]) {
NSString *errorMessage = [NSString stringWithFormat:@"Failed to load asset"
" at URL %@ with no error message.", requestURL];
NSError *error = RCTErrorWithMessage(errorMessage);
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return cancellationBlock;
}
if (cancelled->load()) {
return cancellationBlock;
}
PHAsset *const _Nonnull asset = [fetchResult firstObject];
// When we're uploading a video, provide the full data but in any other case,
// provide only the thumbnail of the video.
if (asset.mediaType == PHAssetMediaTypeVideo && isPHUpload) {
PHVideoRequestOptions *const requestOptions = [PHVideoRequestOptions new];
requestOptions.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestAVAssetForVideo:asset options:requestOptions resultHandler:^(AVAsset * _Nullable avAsset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
NSError *error = [info objectForKey:PHImageErrorKey];
if (error) {
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return;
}
if (![avAsset isKindOfClass:[AVURLAsset class]]) {
error = [NSError errorWithDomain:RCTErrorDomain code:0 userInfo:
@{
NSLocalizedDescriptionKey: @"Unable to load AVURLAsset",
}];
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return;
}
NSData *data = [NSData dataWithContentsOfURL:((AVURLAsset *)avAsset).URL
options:(NSDataReadingOptions)0
error:&error];
if (data) {
NSURLResponse *const response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:nil expectedContentLength:data.length textEncodingName:nil];
[delegate URLRequest:cancellationBlock didReceiveResponse:response];
[delegate URLRequest:cancellationBlock didReceiveData:data];
}
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
}];
} else {
// By default, allow downloading images from iCloud
PHImageRequestOptions *const requestOptions = [PHImageRequestOptions new];
requestOptions.networkAccessAllowed = YES;
[[PHImageManager defaultManager] requestImageDataForAsset:asset
options:requestOptions
resultHandler:^(NSData * _Nullable imageData,
NSString * _Nullable dataUTI,
UIImageOrientation orientation,
NSDictionary * _Nullable info) {
NSError *const error = [info objectForKey:PHImageErrorKey];
if (error) {
[delegate URLRequest:cancellationBlock didCompleteWithError:error];
return;
}
NSInteger const length = [imageData length];
CFStringRef const dataUTIStringRef = (__bridge CFStringRef _Nonnull)(dataUTI);
CFStringRef const mimeType = UTTypeCopyPreferredTagWithClass(dataUTIStringRef, kUTTagClassMIMEType);
NSURLResponse *const response = [[NSURLResponse alloc] initWithURL:request.URL
MIMEType:(__bridge NSString *)(mimeType)
expectedContentLength:length
textEncodingName:nil];
CFRelease(mimeType);
[delegate URLRequest:cancellationBlock didReceiveResponse:response];
[delegate URLRequest:cancellationBlock didReceiveData:imageData];
[delegate URLRequest:cancellationBlock didCompleteWithError:nil];
}];
}
return cancellationBlock;
}
- (void)cancelRequest:(id)requestToken
{
((void (^)(void))requestToken)();
}
@end
Class RCTAssetsLibraryRequestHandlerCls(void) {
return RCTAssetsLibraryRequestHandler.class;
}
@@ -1,22 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Photos/Photos.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTConvert.h>
@interface RCTConvert (PHFetchOptions)
+ (PHFetchOptions *)PHFetchOptionsFromMediaType:(NSString *)mediaType;
@end
@interface RCTCameraRollManager : NSObject <RCTBridgeModule>
@end
@@ -1,360 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTCameraRollManager.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <Photos/Photos.h>
#import <dlfcn.h>
#import <objc/runtime.h>
#import <MobileCoreServices/UTType.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTImageLoader.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
#import "RCTCameraRollPlugins.h"
#import "RCTAssetsLibraryRequestHandler.h"
@implementation RCTConvert (PHAssetCollectionSubtype)
RCT_ENUM_CONVERTER(PHAssetCollectionSubtype, (@{
@"album": @(PHAssetCollectionSubtypeAny),
@"all": @(PHAssetCollectionSubtypeSmartAlbumUserLibrary),
@"event": @(PHAssetCollectionSubtypeAlbumSyncedEvent),
@"faces": @(PHAssetCollectionSubtypeAlbumSyncedFaces),
@"library": @(PHAssetCollectionSubtypeSmartAlbumUserLibrary),
@"photo-stream": @(PHAssetCollectionSubtypeAlbumMyPhotoStream), // incorrect, but legacy
@"photostream": @(PHAssetCollectionSubtypeAlbumMyPhotoStream),
@"saved-photos": @(PHAssetCollectionSubtypeAny), // incorrect, but legacy
@"savedphotos": @(PHAssetCollectionSubtypeAny), // This was ALAssetsGroupSavedPhotos, seems to have no direct correspondence in PHAssetCollectionSubtype
}), PHAssetCollectionSubtypeAny, integerValue)
@end
@implementation RCTConvert (PHFetchOptions)
+ (PHFetchOptions *)PHFetchOptionsFromMediaType:(NSString *)mediaType
{
// This is not exhaustive in terms of supported media type predicates; more can be added in the future
NSString *const lowercase = [mediaType lowercaseString];
if ([lowercase isEqualToString:@"photos"]) {
PHFetchOptions *const options = [PHFetchOptions new];
options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d", PHAssetMediaTypeImage];
return options;
} else if ([lowercase isEqualToString:@"videos"]) {
PHFetchOptions *const options = [PHFetchOptions new];
options.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d", PHAssetMediaTypeVideo];
return options;
} else {
if (![lowercase isEqualToString:@"all"]) {
RCTLogError(@"Invalid filter option: '%@'. Expected one of 'photos',"
"'videos' or 'all'.", mediaType);
}
// This case includes the "all" mediatype
return nil;
}
}
@end
@interface RCTCameraRollManager() <NativeCameraRollManagerSpec>
@end
@implementation RCTCameraRollManager
RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
static NSString *const kErrorUnableToSave = @"E_UNABLE_TO_SAVE";
static NSString *const kErrorUnableToLoad = @"E_UNABLE_TO_LOAD";
static NSString *const kErrorAuthRestricted = @"E_PHOTO_LIBRARY_AUTH_RESTRICTED";
static NSString *const kErrorAuthDenied = @"E_PHOTO_LIBRARY_AUTH_DENIED";
typedef void (^PhotosAuthorizedBlock)(void);
static void requestPhotoLibraryAccess(RCTPromiseRejectBlock reject, PhotosAuthorizedBlock authorizedBlock) {
PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
if (authStatus == PHAuthorizationStatusRestricted) {
reject(kErrorAuthRestricted, @"Access to photo library is restricted", nil);
} else if (authStatus == PHAuthorizationStatusAuthorized) {
authorizedBlock();
} else if (authStatus == PHAuthorizationStatusNotDetermined) {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
requestPhotoLibraryAccess(reject, authorizedBlock);
}];
} else {
reject(kErrorAuthDenied, @"Access to photo library was denied", nil);
}
}
RCT_EXPORT_METHOD(saveToCameraRoll:(NSURLRequest *)request
type:(NSString *)type
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
__block PHObjectPlaceholder *placeholder;
// We load images and videos differently.
// Images have many custom loaders which can load images from ALAssetsLibrary URLs, PHPhotoLibrary
// URLs, `data:` URIs, etc. Video URLs are passed directly through for now; it may be nice to support
// more ways of loading videos in the future.
__block NSURL *inputURI = nil;
__block UIImage *inputImage = nil;
void (^saveBlock)(void) = ^void() {
// performChanges and the completionHandler are called on
// arbitrary threads, not the main thread - this is safe
// for now since all JS is queued and executed on a single thread.
// We should reevaluate this if that assumption changes.
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest;
// Defaults to "photo". `type` is an optional param.
if ([type isEqualToString:@"video"]) {
changeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:inputURI];
} else {
changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:inputImage];
}
placeholder = [changeRequest placeholderForCreatedAsset];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSString *uri = [NSString stringWithFormat:@"ph://%@", [placeholder localIdentifier]];
resolve(uri);
} else {
reject(kErrorUnableToSave, nil, error);
}
}];
};
void (^loadBlock)(void) = ^void() {
if ([type isEqualToString:@"video"]) {
inputURI = request.URL;
saveBlock();
} else {
[[self.bridge moduleForClass:[RCTImageLoader class]] loadImageWithURLRequest:request callback:^(NSError *error, UIImage *image) {
if (error) {
reject(kErrorUnableToLoad, nil, error);
return;
}
inputImage = image;
saveBlock();
}];
}
};
requestPhotoLibraryAccess(reject, loadBlock);
}
static void RCTResolvePromise(RCTPromiseResolveBlock resolve,
NSArray<NSDictionary<NSString *, id> *> *assets,
BOOL hasNextPage)
{
if (!assets.count) {
resolve(@{
@"edges": assets,
@"page_info": @{
@"has_next_page": @NO,
}
});
return;
}
resolve(@{
@"edges": assets,
@"page_info": @{
@"start_cursor": assets[0][@"node"][@"image"][@"uri"],
@"end_cursor": assets[assets.count - 1][@"node"][@"image"][@"uri"],
@"has_next_page": @(hasNextPage),
}
});
}
RCT_EXPORT_METHOD(getPhotos:(JS::NativeCameraRollManager::GetPhotosParams &)params
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
checkPhotoLibraryConfig();
NSUInteger const first = [RCTConvert NSInteger:[NSNumber numberWithDouble:params.first()]];
NSString *const afterCursor = [RCTConvert NSString:params.after()];
NSString *const groupName = [RCTConvert NSString:params.groupName()];
NSString *const groupTypes = [[RCTConvert NSString:params.groupTypes()] lowercaseString];
NSString *const mediaType = [RCTConvert NSString:params.assetType()];
NSArray<NSString *> *const mimeTypes = [RCTConvert NSStringArray:RCTConvertOptionalVecToArray(params.mimeTypes())];
// If groupTypes is "all", we want to fetch the SmartAlbum "all photos". Otherwise, all
// other groupTypes values require the "album" collection type.
PHAssetCollectionType const collectionType = ([groupTypes isEqualToString:@"all"]
? PHAssetCollectionTypeSmartAlbum
: PHAssetCollectionTypeAlbum);
PHAssetCollectionSubtype const collectionSubtype = [RCTConvert PHAssetCollectionSubtype:groupTypes];
// Predicate for fetching assets within a collection
PHFetchOptions *const assetFetchOptions = [RCTConvert PHFetchOptionsFromMediaType:mediaType];
assetFetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
BOOL __block foundAfter = NO;
BOOL __block hasNextPage = NO;
BOOL __block resolvedPromise = NO;
NSMutableArray<NSDictionary<NSString *, id> *> *assets = [NSMutableArray new];
// Filter collection name ("group")
PHFetchOptions *const collectionFetchOptions = [PHFetchOptions new];
collectionFetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"endDate" ascending:NO]];
if (groupName != nil) {
collectionFetchOptions.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"localizedTitle == '%@'", groupName]];
}
requestPhotoLibraryAccess(reject, ^{
PHFetchResult<PHAssetCollection *> *const assetCollectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:collectionType subtype:collectionSubtype options:collectionFetchOptions];
[assetCollectionFetchResult enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull assetCollection, NSUInteger collectionIdx, BOOL * _Nonnull stopCollections) {
// Enumerate assets within the collection
PHFetchResult<PHAsset *> *const assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:assetFetchOptions];
[assetsFetchResult enumerateObjectsUsingBlock:^(PHAsset * _Nonnull asset, NSUInteger assetIdx, BOOL * _Nonnull stopAssets) {
NSString *const uri = [NSString stringWithFormat:@"ph://%@", [asset localIdentifier]];
if (afterCursor && !foundAfter) {
if ([afterCursor isEqualToString:uri]) {
foundAfter = YES;
}
return; // skip until we get to the first one
}
// Get underlying resources of an asset - this includes files as well as details about edited PHAssets
if ([mimeTypes count] > 0) {
NSArray<PHAssetResource *> *const assetResources = [PHAssetResource assetResourcesForAsset:asset];
if (![assetResources firstObject]) {
return;
}
PHAssetResource *const _Nonnull resource = [assetResources firstObject];
CFStringRef const uti = (__bridge CFStringRef _Nonnull)(resource.uniformTypeIdentifier);
NSString *const mimeType = (NSString *)CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
BOOL __block mimeTypeFound = NO;
[mimeTypes enumerateObjectsUsingBlock:^(NSString * _Nonnull mimeTypeFilter, NSUInteger idx, BOOL * _Nonnull stop) {
if ([mimeType isEqualToString:mimeTypeFilter]) {
mimeTypeFound = YES;
*stop = YES;
}
}];
if (!mimeTypeFound) {
return;
}
}
// If we've accumulated enough results to resolve a single promise
if (first == assets.count) {
*stopAssets = YES;
*stopCollections = YES;
hasNextPage = YES;
RCTAssert(resolvedPromise == NO, @"Resolved the promise before we finished processing the results.");
RCTResolvePromise(resolve, assets, hasNextPage);
resolvedPromise = YES;
return;
}
NSString *const assetMediaTypeLabel = (asset.mediaType == PHAssetMediaTypeVideo
? @"video"
: (asset.mediaType == PHAssetMediaTypeImage
? @"image"
: (asset.mediaType == PHAssetMediaTypeAudio
? @"audio"
: @"unknown")));
CLLocation *const loc = asset.location;
// A note on isStored: in the previous code that used ALAssets, isStored
// was always set to YES, probably because iCloud-synced images were never returned (?).
// To get the "isStored" information and filename, we would need to actually request the
// image data from the image manager. Those operations could get really expensive and
// would definitely utilize the disk too much.
// Thus, this field is actually not reliable.
// Note that Android also does not return the `isStored` field at all.
[assets addObject:@{
@"node": @{
@"type": assetMediaTypeLabel, // TODO: switch to mimeType?
@"group_name": [assetCollection localizedTitle],
@"image": @{
@"uri": uri,
@"height": @([asset pixelHeight]),
@"width": @([asset pixelWidth]),
@"isStored": @YES, // this field doesn't seem to exist on android
@"playableDuration": @([asset duration]) // fractional seconds
},
@"timestamp": @(asset.creationDate.timeIntervalSince1970),
@"location": (loc ? @{
@"latitude": @(loc.coordinate.latitude),
@"longitude": @(loc.coordinate.longitude),
@"altitude": @(loc.altitude),
@"heading": @(loc.course),
@"speed": @(loc.speed), // speed in m/s
} : @{})
}
}];
}];
}];
// If we get this far and haven't resolved the promise yet, we reached the end of the list of photos
if (!resolvedPromise) {
hasNextPage = NO;
RCTResolvePromise(resolve, assets, hasNextPage);
resolvedPromise = YES;
}
});
}
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);
}
}
];
}
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
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeCameraRollManagerSpecJSI>(params);
}
@end
Class RCTCameraRollManagerCls(void) {
return RCTCameraRollManager.class;
}
@@ -1,43 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated by an internal plugin build system
*/
#ifdef RN_DISABLE_OSS_PLUGIN_HEADER
// FB Internal: FBRCTCameraRollPlugins.h is autogenerated by the build system.
#import <RCTCameraRollApple/FBRCTCameraRollPlugins.h>
#else
// OSS-compatibility layer
#import <Foundation/Foundation.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
#ifdef __cplusplus
extern "C" {
#endif
// RCTTurboModuleManagerDelegate should call this to resolve module classes.
Class RCTCameraRollClassProvider(const char *name);
// Lookup functions
Class RCTAssetsLibraryRequestHandlerCls(void) __attribute__((used));
Class RCTCameraRollManagerCls(void) __attribute__((used));
Class RCTImagePickerManagerCls(void) __attribute__((used));
Class RCTPhotoLibraryImageLoaderCls(void) __attribute__((used));
#ifdef __cplusplus
}
#endif
#pragma GCC diagnostic pop
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
@@ -1,35 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated by an internal plugin build system
*/
#ifndef RN_DISABLE_OSS_PLUGIN_HEADER
// OSS-compatibility layer
#import "RCTCameraRollPlugins.h"
#import <string>
#import <unordered_map>
Class RCTCameraRollClassProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sCoreModuleClassMap = {
{"AssetsLibraryRequestHandler", RCTAssetsLibraryRequestHandlerCls},
{"CameraRollManager", RCTCameraRollManagerCls},
{"ImagePickerIOS", RCTImagePickerManagerCls},
{"PhotoLibraryImageLoader", RCTPhotoLibraryImageLoaderCls},
};
auto p = sCoreModuleClassMap.find(name);
if (p != sCoreModuleClassMap.end()) {
auto classFunc = p->second;
return classFunc();
}
return nil;
}
#endif // RN_DISABLE_OSS_PLUGIN_HEADER
@@ -1,12 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTBridgeModule.h>
@interface RCTImagePickerManager : NSObject <RCTBridgeModule>
@end
@@ -1,261 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTImagePickerManager.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <MobileCoreServices/UTCoreTypes.h>
#import <UIKit/UIKit.h>
#import <React/RCTConvert.h>
#import <React/RCTImageStoreManager.h>
#import <React/RCTRootView.h>
#import <React/RCTUtils.h>
#import "RCTCameraRollPlugins.h"
@interface RCTImagePickerController : UIImagePickerController
@property (nonatomic, assign) BOOL unmirrorFrontFacingCamera;
@end
@implementation RCTImagePickerController
@end
@interface RCTImagePickerManager () <UIImagePickerControllerDelegate, UINavigationControllerDelegate, NativeImagePickerIOSSpec>
@end
@implementation RCTImagePickerManager
{
NSMutableArray<UIImagePickerController *> *_pickers;
NSMutableArray<RCTResponseSenderBlock> *_pickerCallbacks;
NSMutableArray<RCTResponseSenderBlock> *_pickerCancelCallbacks;
NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *_pendingVideoInfo;
}
RCT_EXPORT_MODULE(ImagePickerIOS);
@synthesize bridge = _bridge;
- (id)init
{
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(cameraChanged:)
name:@"AVCaptureDeviceDidStartRunningNotification"
object:nil];
}
return self;
}
+ (BOOL)requiresMainQueueSetup
{
return NO;
}
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_METHOD(canRecordVideos:(RCTResponseSenderBlock)callback)
{
NSArray<NSString *> *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
callback(@[@([availableMediaTypes containsObject:(NSString *)kUTTypeMovie])]);
}
RCT_EXPORT_METHOD(canUseCamera:(RCTResponseSenderBlock)callback)
{
callback(@[@([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])]);
}
RCT_EXPORT_METHOD(openCameraDialog:(JS::NativeImagePickerIOS::SpecOpenCameraDialogConfig &)config
successCallback:(RCTResponseSenderBlock)callback
cancelCallback:(RCTResponseSenderBlock)cancelCallback)
{
if (RCTRunningInAppExtension()) {
cancelCallback(@[@"Camera access is unavailable in an app extension"]);
return;
}
RCTImagePickerController *imagePicker = [RCTImagePickerController new];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
NSArray<NSString *> *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
imagePicker.mediaTypes = availableMediaTypes;
imagePicker.unmirrorFrontFacingCamera = config.unmirrorFrontFacingCamera() ? YES : NO;
if (config.videoMode()) {
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
}
[self _presentPicker:imagePicker
successCallback:callback
cancelCallback:cancelCallback];
}
RCT_EXPORT_METHOD(openSelectDialog:(JS::NativeImagePickerIOS::SpecOpenSelectDialogConfig &)config
successCallback:(RCTResponseSenderBlock)callback
cancelCallback:(RCTResponseSenderBlock)cancelCallback)
{
if (RCTRunningInAppExtension()) {
cancelCallback(@[@"Image picker is currently unavailable in an app extension"]);
return;
}
UIImagePickerController *imagePicker = [UIImagePickerController new];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
NSMutableArray<NSString *> *allowedTypes = [NSMutableArray new];
if (config.showImages()) {
[allowedTypes addObject:(NSString *)kUTTypeImage];
}
if (config.showVideos()) {
[allowedTypes addObject:(NSString *)kUTTypeMovie];
}
imagePicker.mediaTypes = allowedTypes;
[self _presentPicker:imagePicker
successCallback:callback
cancelCallback:cancelCallback];
}
// In iOS 13, the URLs provided when selecting videos from the library are only valid while the
// info object provided by the delegate is retained.
// This method provides a way to clear out all retained pending info objects.
RCT_EXPORT_METHOD(clearAllPendingVideos)
{
[_pendingVideoInfo removeAllObjects];
_pendingVideoInfo = [NSMutableDictionary new];
}
// In iOS 13, the URLs provided when selecting videos from the library are only valid while the
// info object provided by the delegate is retained.
// This method provides a way to release the info object for a particular file url when the application
// is done with it, for example after the video has been uploaded or copied locally.
RCT_EXPORT_METHOD(removePendingVideo:(NSString *)url)
{
[_pendingVideoInfo removeObjectForKey:url];
}
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info
{
NSString *mediaType = info[UIImagePickerControllerMediaType];
BOOL isMovie = [mediaType isEqualToString:(NSString *)kUTTypeMovie];
NSString *key = isMovie ? UIImagePickerControllerMediaURL : UIImagePickerControllerReferenceURL;
NSURL *imageURL = info[key];
UIImage *image = info[UIImagePickerControllerOriginalImage];
NSNumber *width = 0;
NSNumber *height = 0;
if (image) {
height = @(image.size.height);
width = @(image.size.width);
}
if (imageURL) {
NSString *imageURLString = imageURL.absoluteString;
// In iOS 13, video URLs are only valid while info dictionary is retained
if (@available(iOS 13.0, *)) {
if (isMovie) {
_pendingVideoInfo[imageURLString] = info;
}
}
[self _dismissPicker:picker args:@[imageURLString, RCTNullIfNil(height), RCTNullIfNil(width)]];
return;
}
// This is a newly taken image, and doesn't have a URL yet.
// We need to save it to the image store first.
UIImage *originalImage = info[UIImagePickerControllerOriginalImage];
// WARNING: Using ImageStoreManager may cause a memory leak because the
// image isn't automatically removed from store once we're done using it.
[_bridge.imageStoreManager storeImage:originalImage withBlock:^(NSString *tempImageTag) {
[self _dismissPicker:picker args:tempImageTag ? @[tempImageTag, RCTNullIfNil(height), RCTNullIfNil(width)] : nil];
}];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self _dismissPicker:picker args:nil];
}
- (void)_presentPicker:(UIImagePickerController *)imagePicker
successCallback:(RCTResponseSenderBlock)callback
cancelCallback:(RCTResponseSenderBlock)cancelCallback
{
if (!_pickers) {
_pickers = [NSMutableArray new];
_pickerCallbacks = [NSMutableArray new];
_pickerCancelCallbacks = [NSMutableArray new];
_pendingVideoInfo = [NSMutableDictionary new];
}
[_pickers addObject:imagePicker];
[_pickerCallbacks addObject:callback];
[_pickerCancelCallbacks addObject:cancelCallback];
UIViewController *rootViewController = RCTPresentedViewController();
[rootViewController presentViewController:imagePicker animated:YES completion:nil];
}
- (void)_dismissPicker:(UIImagePickerController *)picker args:(NSArray *)args
{
NSUInteger index = [_pickers indexOfObject:picker];
if (index == NSNotFound) {
// This happens if the user selects multiple items in succession.
return;
}
RCTResponseSenderBlock successCallback = _pickerCallbacks[index];
RCTResponseSenderBlock cancelCallback = _pickerCancelCallbacks[index];
[_pickers removeObjectAtIndex:index];
[_pickerCallbacks removeObjectAtIndex:index];
[_pickerCancelCallbacks removeObjectAtIndex:index];
UIViewController *rootViewController = RCTPresentedViewController();
[rootViewController dismissViewControllerAnimated:YES completion:nil];
if (args) {
successCallback(args);
} else {
cancelCallback(@[]);
}
}
- (void)cameraChanged:(NSNotification *)notification
{
for (UIImagePickerController *picker in _pickers) {
if (picker.sourceType != UIImagePickerControllerSourceTypeCamera) {
continue;
}
if ([picker isKindOfClass:[RCTImagePickerController class]]
&& ((RCTImagePickerController *)picker).unmirrorFrontFacingCamera
&& picker.cameraDevice == UIImagePickerControllerCameraDeviceFront) {
picker.cameraViewTransform = CGAffineTransformScale(CGAffineTransformIdentity, -1, 1);
} else {
picker.cameraViewTransform = CGAffineTransformIdentity;
}
}
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeImagePickerIOSSpecJSI>(params);
}
@end
Class RCTImagePickerManagerCls(void) {
return RCTImagePickerManager.class;
}
@@ -1,12 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTImageLoader.h>
@interface RCTPhotoLibraryImageLoader : NSObject <RCTImageURLLoader>
@end
@@ -1,121 +0,0 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTPhotoLibraryImageLoader.h"
#import <Photos/Photos.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
#import <ReactCommon/RCTTurboModule.h>
#import "RCTCameraRollPlugins.h"
@interface RCTPhotoLibraryImageLoader () <RCTTurboModule>
@end
@implementation RCTPhotoLibraryImageLoader
RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
#pragma mark - RCTImageLoader
- (BOOL)canLoadImageURL:(NSURL *)requestURL
{
if (![PHAsset class]) {
return NO;
}
return [requestURL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame ||
[requestURL.scheme caseInsensitiveCompare:@"ph"] == NSOrderedSame;
}
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
{
// Using PhotoKit for iOS 8+
// The 'ph://' prefix is used by FBMediaKit to differentiate between
// assets-library. It is prepended to the local ID so that it is in the
// form of an NSURL which is what assets-library uses.
NSString *assetID = @"";
PHFetchResult *results;
if (!imageURL) {
completionHandler(RCTErrorWithMessage(@"Cannot load a photo library asset with no URL"), nil);
return ^{};
} else if ([imageURL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
assetID = [imageURL absoluteString];
results = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil];
} else {
assetID = [imageURL.absoluteString substringFromIndex:@"ph://".length];
results = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil];
}
if (results.count == 0) {
NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", assetID];
completionHandler(RCTErrorWithMessage(errorText), nil);
return ^{};
}
PHAsset *asset = [results firstObject];
PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];
// Allow PhotoKit to fetch images from iCloud
imageOptions.networkAccessAllowed = YES;
if (progressHandler) {
imageOptions.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary<NSString *, id> *info) {
static const double multiplier = 1e6;
progressHandler(progress * multiplier, multiplier);
};
}
// Note: PhotoKit defaults to a deliveryMode of PHImageRequestOptionsDeliveryModeOpportunistic
// which means it may call back multiple times - we probably don't want that
imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);
CGSize targetSize;
if (useMaximumSize) {
targetSize = PHImageManagerMaximumSize;
imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
} else {
targetSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
}
PHImageContentMode contentMode = PHImageContentModeAspectFill;
if (resizeMode == RCTResizeModeContain) {
contentMode = PHImageContentModeAspectFit;
}
PHImageRequestID requestID =
[[PHImageManager defaultManager] requestImageForAsset:asset
targetSize:targetSize
contentMode:contentMode
options:imageOptions
resultHandler:^(UIImage *result, NSDictionary<NSString *, id> *info) {
if (result) {
completionHandler(nil, result);
} else {
completionHandler(info[PHImageErrorKey], nil);
}
}];
return ^{
[[PHImageManager defaultManager] cancelImageRequest:requestID];
};
}
@end
Class RCTPhotoLibraryImageLoaderCls(void) {
return RCTPhotoLibraryImageLoader.class;
}
@@ -703,83 +703,6 @@ namespace facebook {
} // namespace react
} // namespace facebook
@implementation RCTCxxConvert (NativeCameraRollManager_GetPhotosParams)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::GetPhotosParams>(json);
}
@end
namespace facebook {
namespace react {
static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "getPhotos", @selector(getPhotos:resolve:reject:), args, count);
}
static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "saveToCameraRoll", @selector(saveToCameraRoll:type:resolve:reject:), args, count);
}
static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "deletePhotos", @selector(deletePhotos:resolve:reject:), args, count);
}
NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams &params)
: ObjCTurboModule(params) {
methodMap_["getPhotos"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos};
setMethodArgConversionSelector(@"getPhotos", 0, @"JS_NativeCameraRollManager_GetPhotosParams:");
methodMap_["saveToCameraRoll"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll};
methodMap_["deletePhotos"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos};
}
} // namespace react
} // namespace facebook
@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierImage)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierImage:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::PhotoIdentifierImage>(json);
}
@end
@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNodeLocation)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNodeLocation:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::PhotoIdentifierNodeLocation>(json);
}
@end
@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNode)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNode:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::PhotoIdentifierNode>(json);
}
@end
@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifier)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifier:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::PhotoIdentifier>(json);
}
@end
@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPagePage_info)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPagePage_info:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info>(json);
}
@end
@implementation RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPage)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPage:(id)json
{
return facebook::react::managedPointer<JS::NativeCameraRollManager::PhotoIdentifiersPage>(json);
}
@end
namespace facebook {
namespace react {
@@ -648,167 +648,6 @@ namespace facebook {
};
} // namespace react
} // namespace facebook
namespace JS {
namespace NativeCameraRollManager {
struct GetPhotosParams {
double first() const;
NSString *after() const;
NSString *groupName() const;
NSString *groupTypes() const;
NSString *assetType() const;
folly::Optional<double> maxSize() const;
folly::Optional<facebook::react::LazyVector<NSString *>> mimeTypes() const;
GetPhotosParams(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_GetPhotosParams)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_GetPhotosParams:(id)json;
@end
@protocol NativeCameraRollManagerSpec <RCTBridgeModule, RCTTurboModule>
- (void)getPhotos:(JS::NativeCameraRollManager::GetPhotosParams &)params
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject;
- (void)saveToCameraRoll:(NSString *)uri
type:(NSString *)type
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject;
- (void)deletePhotos:(NSArray *)assets
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject;
@end
namespace facebook {
namespace react {
/**
* ObjC++ class for module 'CameraRollManager'
*/
class JSI_EXPORT NativeCameraRollManagerSpecJSI : public ObjCTurboModule {
public:
NativeCameraRollManagerSpecJSI(const ObjCTurboModule::InitParams &params);
};
} // namespace react
} // namespace facebook
namespace JS {
namespace NativeCameraRollManager {
struct PhotoIdentifierImage {
NSString *uri() const;
double playableDuration() const;
double width() const;
double height() const;
folly::Optional<bool> isStored() const;
NSString *filename() const;
PhotoIdentifierImage(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierImage)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierImage:(id)json;
@end
namespace JS {
namespace NativeCameraRollManager {
struct PhotoIdentifierNodeLocation {
double longitude() const;
double latitude() const;
folly::Optional<double> altitude() const;
folly::Optional<double> heading() const;
folly::Optional<double> speed() const;
PhotoIdentifierNodeLocation(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNodeLocation)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNodeLocation:(id)json;
@end
namespace JS {
namespace NativeCameraRollManager {
struct PhotoIdentifierNode {
JS::NativeCameraRollManager::PhotoIdentifierImage image() const;
NSString *type() const;
NSString *group_name() const;
double timestamp() const;
JS::NativeCameraRollManager::PhotoIdentifierNodeLocation location() const;
PhotoIdentifierNode(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifierNode)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifierNode:(id)json;
@end
namespace JS {
namespace NativeCameraRollManager {
struct PhotoIdentifier {
JS::NativeCameraRollManager::PhotoIdentifierNode node() const;
PhotoIdentifier(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifier)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifier:(id)json;
@end
namespace JS {
namespace NativeCameraRollManager {
struct PhotoIdentifiersPagePage_info {
bool has_next_page() const;
NSString *start_cursor() const;
NSString *end_cursor() const;
PhotoIdentifiersPagePage_info(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPagePage_info)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPagePage_info:(id)json;
@end
namespace JS {
namespace NativeCameraRollManager {
struct PhotoIdentifiersPage {
facebook::react::LazyVector<JS::NativeCameraRollManager::PhotoIdentifier> edges() const;
JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info page_info() const;
PhotoIdentifiersPage(NSDictionary *const v) : _v(v) {}
private:
NSDictionary *_v;
};
}
}
@interface RCTCxxConvert (NativeCameraRollManager_PhotoIdentifiersPage)
+ (RCTManagedPointer *)JS_NativeCameraRollManager_PhotoIdentifiersPage:(id)json;
@end
@protocol NativeClipboardSpec <RCTBridgeModule, RCTTurboModule>
- (void)getString:(RCTPromiseResolveBlock)resolve
@@ -3076,151 +2915,6 @@ inline JS::NativeBlobModule::Constants::Builder::Builder(const Input i) : _facto
inline JS::NativeBlobModule::Constants::Builder::Builder(Constants i) : _factory(^{
return i.unsafeRawValue();
}) {}
inline double JS::NativeCameraRollManager::GetPhotosParams::first() const
{
id const p = _v[@"first"];
return RCTBridgingToDouble(p);
}
inline NSString *JS::NativeCameraRollManager::GetPhotosParams::after() const
{
id const p = _v[@"after"];
return RCTBridgingToString(p);
}
inline NSString *JS::NativeCameraRollManager::GetPhotosParams::groupName() const
{
id const p = _v[@"groupName"];
return RCTBridgingToString(p);
}
inline NSString *JS::NativeCameraRollManager::GetPhotosParams::groupTypes() const
{
id const p = _v[@"groupTypes"];
return RCTBridgingToString(p);
}
inline NSString *JS::NativeCameraRollManager::GetPhotosParams::assetType() const
{
id const p = _v[@"assetType"];
return RCTBridgingToString(p);
}
inline folly::Optional<double> JS::NativeCameraRollManager::GetPhotosParams::maxSize() const
{
id const p = _v[@"maxSize"];
return RCTBridgingToOptionalDouble(p);
}
inline folly::Optional<facebook::react::LazyVector<NSString *>> JS::NativeCameraRollManager::GetPhotosParams::mimeTypes() const
{
id const p = _v[@"mimeTypes"];
return RCTBridgingToOptionalVec(p, ^NSString *(id itemValue_0) { return RCTBridgingToString(itemValue_0); });
}
inline NSString *JS::NativeCameraRollManager::PhotoIdentifierImage::uri() const
{
id const p = _v[@"uri"];
return RCTBridgingToString(p);
}
inline double JS::NativeCameraRollManager::PhotoIdentifierImage::playableDuration() const
{
id const p = _v[@"playableDuration"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeCameraRollManager::PhotoIdentifierImage::width() const
{
id const p = _v[@"width"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeCameraRollManager::PhotoIdentifierImage::height() const
{
id const p = _v[@"height"];
return RCTBridgingToDouble(p);
}
inline folly::Optional<bool> JS::NativeCameraRollManager::PhotoIdentifierImage::isStored() const
{
id const p = _v[@"isStored"];
return RCTBridgingToOptionalBool(p);
}
inline NSString *JS::NativeCameraRollManager::PhotoIdentifierImage::filename() const
{
id const p = _v[@"filename"];
return RCTBridgingToString(p);
}
inline double JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::longitude() const
{
id const p = _v[@"longitude"];
return RCTBridgingToDouble(p);
}
inline double JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::latitude() const
{
id const p = _v[@"latitude"];
return RCTBridgingToDouble(p);
}
inline folly::Optional<double> JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::altitude() const
{
id const p = _v[@"altitude"];
return RCTBridgingToOptionalDouble(p);
}
inline folly::Optional<double> JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::heading() const
{
id const p = _v[@"heading"];
return RCTBridgingToOptionalDouble(p);
}
inline folly::Optional<double> JS::NativeCameraRollManager::PhotoIdentifierNodeLocation::speed() const
{
id const p = _v[@"speed"];
return RCTBridgingToOptionalDouble(p);
}
inline JS::NativeCameraRollManager::PhotoIdentifierImage JS::NativeCameraRollManager::PhotoIdentifierNode::image() const
{
id const p = _v[@"image"];
return JS::NativeCameraRollManager::PhotoIdentifierImage(p);
}
inline NSString *JS::NativeCameraRollManager::PhotoIdentifierNode::type() const
{
id const p = _v[@"type"];
return RCTBridgingToString(p);
}
inline NSString *JS::NativeCameraRollManager::PhotoIdentifierNode::group_name() const
{
id const p = _v[@"group_name"];
return RCTBridgingToString(p);
}
inline double JS::NativeCameraRollManager::PhotoIdentifierNode::timestamp() const
{
id const p = _v[@"timestamp"];
return RCTBridgingToDouble(p);
}
inline JS::NativeCameraRollManager::PhotoIdentifierNodeLocation JS::NativeCameraRollManager::PhotoIdentifierNode::location() const
{
id const p = _v[@"location"];
return JS::NativeCameraRollManager::PhotoIdentifierNodeLocation(p);
}
inline JS::NativeCameraRollManager::PhotoIdentifierNode JS::NativeCameraRollManager::PhotoIdentifier::node() const
{
id const p = _v[@"node"];
return JS::NativeCameraRollManager::PhotoIdentifierNode(p);
}
inline bool JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::has_next_page() const
{
id const p = _v[@"has_next_page"];
return RCTBridgingToBool(p);
}
inline NSString *JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::start_cursor() const
{
id const p = _v[@"start_cursor"];
return RCTBridgingToString(p);
}
inline NSString *JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info::end_cursor() const
{
id const p = _v[@"end_cursor"];
return RCTBridgingToString(p);
}
inline facebook::react::LazyVector<JS::NativeCameraRollManager::PhotoIdentifier> JS::NativeCameraRollManager::PhotoIdentifiersPage::edges() const
{
id const p = _v[@"edges"];
return RCTBridgingToVec(p, ^JS::NativeCameraRollManager::PhotoIdentifier(id itemValue_0) { return JS::NativeCameraRollManager::PhotoIdentifier(itemValue_0); });
}
inline JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info JS::NativeCameraRollManager::PhotoIdentifiersPage::page_info() const
{
id const p = _v[@"page_info"];
return JS::NativeCameraRollManager::PhotoIdentifiersPagePage_info(p);
}
inline JS::NativeDeviceInfo::DisplayMetrics::Builder::Builder(const Input i) : _factory(^{
NSMutableDictionary *d = [NSMutableDictionary new];
auto width = i.width.get();
@@ -580,40 +580,6 @@ namespace facebook {
}
} // namespace react
} // namespace facebook
namespace facebook {
namespace react {
static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule&>(turboModule).invokeJavaMethod(rt, PromiseKind, "getPhotos", "(Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V", args, count);
}
static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule&>(turboModule).invokeJavaMethod(rt, PromiseKind, "saveToCameraRoll", "(Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count);
}
static facebook::jsi::Value __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule&>(turboModule).invokeJavaMethod(rt, PromiseKind, "deletePhotos", "(Lcom/facebook/react/bridge/ReadableArray;Lcom/facebook/react/bridge/Promise;)V", args, count);
}
NativeCameraRollManagerSpecJSI::NativeCameraRollManagerSpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) {
methodMap_["getPhotos"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_getPhotos};
methodMap_["saveToCameraRoll"] = MethodMetadata {2, __hostFunction_NativeCameraRollManagerSpecJSI_saveToCameraRoll};
methodMap_["deletePhotos"] = MethodMetadata {1, __hostFunction_NativeCameraRollManagerSpecJSI_deletePhotos};
}
} // namespace react
@@ -171,20 +171,6 @@ namespace facebook {
} // namespace react
} // namespace facebook
namespace facebook {
namespace react {
/**
* C++ class for module 'CameraRollManager'
*/
class JSI_EXPORT NativeCameraRollManagerSpecJSI : public JavaTurboModule {
public:
NativeCameraRollManagerSpecJSI(const JavaTurboModule::InitParams &params);
};
} // namespace react
} // namespace facebook
namespace facebook {
namespace react {
/**