UNPKG

12.1 kBPlain TextView Raw
1#import <EXCamera/EXCamera.h>
2#import <EXCamera/EXCameraManager.h>
3#import <EXCamera/EXCameraUtils.h>
4#import <EXCamera/EXCameraPermissionRequester.h>
5
6#import <UMCore/UMUIManager.h>
7#import <UMFileSystemInterface/UMFileSystemInterface.h>
8#import <UMPermissionsInterface/UMPermissionsInterface.h>
9#import <UMPermissionsInterface/UMPermissionsMethodsDelegate.h>
10
11@interface EXCameraManager ()
12
13@property (nonatomic, weak) id<UMFileSystemInterface> fileSystem;
14@property (nonatomic, weak) id<UMUIManager> uiManager;
15@property (nonatomic, weak) UMModuleRegistry *moduleRegistry;
16@property (nonatomic, weak) id<UMPermissionsInterface> permissionsManager;
17@end
18
19@implementation EXCameraManager
20
21UM_EXPORT_MODULE(ExponentCameraManager);
22
23- (NSString *)viewName
24{
25 return @"ExponentCamera";
26}
27
28- (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry
29{
30 _moduleRegistry = moduleRegistry;
31 _fileSystem = [moduleRegistry getModuleImplementingProtocol:@protocol(UMFileSystemInterface)];
32 _uiManager = [moduleRegistry getModuleImplementingProtocol:@protocol(UMUIManager)];
33 _permissionsManager = [moduleRegistry getModuleImplementingProtocol:@protocol(UMPermissionsInterface)];
34 [UMPermissionsMethodsDelegate registerRequesters:@[[EXCameraPermissionRequester new]] withPermissionsManager:_permissionsManager];
35}
36
37- (UIView *)view
38{
39 return [[EXCamera alloc] initWithModuleRegistry:_moduleRegistry];
40}
41
42- (NSDictionary *)constantsToExport
43{
44 return @{
45 @"Type" :
46 @{@"front" : @(EXCameraTypeFront), @"back" : @(EXCameraTypeBack)},
47 @"FlashMode" : @{
48 @"off" : @(EXCameraFlashModeOff),
49 @"on" : @(EXCameraFlashModeOn),
50 @"auto" : @(EXCameraFlashModeAuto),
51 @"torch" : @(EXCameraFlashModeTorch)
52 },
53 @"AutoFocus" :
54 @{@"on" : @(EXCameraAutoFocusOn), @"off" : @(EXCameraAutoFocusOff)},
55 @"WhiteBalance" : @{
56 @"auto" : @(EXCameraWhiteBalanceAuto),
57 @"sunny" : @(EXCameraWhiteBalanceSunny),
58 @"cloudy" : @(EXCameraWhiteBalanceCloudy),
59 @"shadow" : @(EXCameraWhiteBalanceShadow),
60 @"incandescent" : @(EXCameraWhiteBalanceIncandescent),
61 @"fluorescent" : @(EXCameraWhiteBalanceFluorescent)
62 },
63 @"VideoQuality": @{
64 @"2160p": @(EXCameraVideo2160p),
65 @"1080p": @(EXCameraVideo1080p),
66 @"720p": @(EXCameraVideo720p),
67 @"480p": @(EXCameraVideo4x3),
68 @"4:3": @(EXCameraVideo4x3),
69 },
70 @"VideoStabilization": @{
71 @"off": @(EXCameraVideoStabilizationModeOff),
72 @"standard": @(EXCameraVideoStabilizationModeStandard),
73 @"cinematic": @(EXCameraVideoStabilizationModeCinematic),
74 @"auto": @(EXCameraAVCaptureVideoStabilizationModeAuto)
75 },
76 };
77}
78
79- (NSArray<NSString *> *)supportedEvents
80{
81 return @[
82 @"onCameraReady",
83 @"onMountError",
84 @"onPictureSaved",
85 @"onBarCodeScanned",
86 @"onFacesDetected",
87 ];
88}
89
90+ (NSDictionary *)pictureSizes
91{
92 return @{
93 @"3840x2160" : AVCaptureSessionPreset3840x2160,
94 @"1920x1080" : AVCaptureSessionPreset1920x1080,
95 @"1280x720" : AVCaptureSessionPreset1280x720,
96 @"640x480" : AVCaptureSessionPreset640x480,
97 @"352x288" : AVCaptureSessionPreset352x288,
98 @"Photo" : AVCaptureSessionPresetPhoto,
99 @"High" : AVCaptureSessionPresetHigh,
100 @"Medium" : AVCaptureSessionPresetMedium,
101 @"Low" : AVCaptureSessionPresetLow
102 };
103}
104
105UM_VIEW_PROPERTY(type, NSNumber *, EXCamera)
106{
107 long longValue = [value longValue];
108 if (view.presetCamera != longValue) {
109 [view setPresetCamera:longValue];
110 [view updateType];
111 }
112}
113
114UM_VIEW_PROPERTY(flashMode, NSNumber *, EXCamera)
115{
116 long longValue = [value longValue];
117 if (longValue != view.flashMode) {
118 [view setFlashMode:longValue];
119 [view updateFlashMode];
120 }
121}
122
123UM_VIEW_PROPERTY(faceDetectorSettings, NSDictionary *, EXCamera)
124{
125 [view updateFaceDetectorSettings:value];
126}
127
128UM_VIEW_PROPERTY(barCodeScannerSettings, NSDictionary *, EXCamera)
129{
130 [view setBarCodeScannerSettings:value];
131}
132
133UM_VIEW_PROPERTY(autoFocus, NSNumber *, EXCamera)
134{
135 long longValue = [value longValue];
136 if (longValue != view.autoFocus) {
137 [view setAutoFocus:longValue];
138 [view updateFocusMode];
139 }
140}
141
142UM_VIEW_PROPERTY(focusDepth, NSNumber *, EXCamera)
143{
144 float floatValue = [value floatValue];
145 if (fabsf(view.focusDepth - floatValue) > FLT_EPSILON) {
146 [view setFocusDepth:floatValue];
147 [view updateFocusDepth];
148 }
149}
150
151UM_VIEW_PROPERTY(zoom, NSNumber *, EXCamera)
152{
153 double doubleValue = [value doubleValue];
154 if (fabs(view.zoom - doubleValue) > DBL_EPSILON) {
155 [view setZoom:doubleValue];
156 [view updateZoom];
157 }
158}
159
160UM_VIEW_PROPERTY(whiteBalance, NSNumber *, EXCamera)
161{
162 long longValue = [value longValue];
163 if (longValue != view.whiteBalance) {
164 [view setWhiteBalance:longValue];
165 [view updateWhiteBalance];
166 }
167}
168
169UM_VIEW_PROPERTY(pictureSize, NSString *, EXCamera) {
170 [view setPictureSize:[[self class] pictureSizes][value]];
171 [view updatePictureSize];
172}
173
174UM_VIEW_PROPERTY(faceDetectorEnabled, NSNumber *, EXCamera)
175{
176 bool boolValue = [value boolValue];
177 if ([view isDetectingFaces] != boolValue) {
178 [view setIsDetectingFaces:boolValue];
179 }
180}
181
182UM_VIEW_PROPERTY(barCodeScannerEnabled, NSNumber *, EXCamera)
183{
184 bool boolValue = [value boolValue];
185 if ([view isScanningBarCodes] != boolValue) {
186 [view setIsScanningBarCodes:boolValue];
187 }
188}
189
190UM_EXPORT_METHOD_AS(takePicture,
191 takePictureWithOptions:(NSDictionary *)options
192 reactTag:(nonnull NSNumber *)reactTag
193 resolver:(UMPromiseResolveBlock)resolve
194 rejecter:(UMPromiseRejectBlock)reject)
195{
196#if TARGET_IPHONE_SIMULATOR
197 __weak EXCameraManager *weakSelf = self;
198#endif
199 [_uiManager executeUIBlock:^(id view) {
200 if (view != nil) {
201#if TARGET_IPHONE_SIMULATOR
202 __strong EXCameraManager *strongSelf = weakSelf;
203 if (!strongSelf.fileSystem) {
204 reject(@"E_IMAGE_SAVE_FAILED", @"No filesystem module", nil);
205 return;
206 }
207
208 NSString *path = [strongSelf.fileSystem generatePathInDirectory:[strongSelf.fileSystem.cachesDirectory stringByAppendingPathComponent:@"Camera"] withExtension:@".jpg"];
209
210 UIImage *generatedPhoto = [EXCameraUtils generatePhotoOfSize:CGSizeMake(200, 200)];
211 BOOL useFastMode = options[@"fastMode"] && [options[@"fastMode"] boolValue];
212 if (useFastMode) {
213 resolve(nil);
214 }
215
216 float quality = [options[@"quality"] floatValue];
217 NSData *photoData = UIImageJPEGRepresentation(generatedPhoto, quality);
218
219 NSMutableDictionary *response = [[NSMutableDictionary alloc] init];
220 response[@"uri"] = [EXCameraUtils writeImage:photoData toPath:path];
221 response[@"width"] = @(generatedPhoto.size.width);
222 response[@"height"] = @(generatedPhoto.size.height);
223 if ([options[@"base64"] boolValue]) {
224 response[@"base64"] = [photoData base64EncodedStringWithOptions:0];
225 }
226 if (useFastMode) {
227 [view onPictureSaved:@{@"data": response, @"id": options[@"id"]}];
228 } else {
229 resolve(response);
230 }
231#else
232 [view takePicture:options resolve:resolve reject:reject];
233#endif
234 } else {
235 NSString *reason = [NSString stringWithFormat:@"Invalid view returned from registry, expected EXCamera, got: %@", view];
236 reject(@"E_INVALID_VIEW", reason, nil);
237 }
238 } forView:reactTag ofClass:[EXCamera class]];
239
240}
241
242UM_EXPORT_METHOD_AS(record,
243 recordWithOptions:(NSDictionary *)options
244 reactTag:(nonnull NSNumber *)reactTag
245 resolver:(UMPromiseResolveBlock)resolve
246 rejecter:(UMPromiseRejectBlock)reject)
247{
248#pragma clang diagnostic push
249#pragma clang diagnostic ignored "-Wunreachable-code"
250#if TARGET_IPHONE_SIMULATOR
251 reject(@"E_RECORDING_FAILED", @"Video recording is not supported on a simulator.", nil);
252 return;
253#endif
254 [_uiManager executeUIBlock:^(id view) {
255 if (view != nil) {
256 [view record:options resolve:resolve reject:reject];
257 } else {
258 NSString *reason = [NSString stringWithFormat:@"Invalid view returned from registry, expected EXCamera, got: %@", view];
259 reject(@"E_INVALID_VIEW", reason, nil);
260 }
261 } forView:reactTag ofClass:[EXCamera class]];
262#pragma clang diagnostic pop
263}
264
265UM_EXPORT_METHOD_AS(stopRecording,
266 stopRecordingOfReactTag:(nonnull NSNumber *)reactTag
267 resolver:(UMPromiseResolveBlock)resolve
268 rejecter:(UMPromiseRejectBlock)reject)
269{
270 [_uiManager executeUIBlock:^(id view) {
271 if (view != nil) {
272 [view stopRecording];
273 resolve(nil);
274 } else {
275 UMLogError(@"Invalid view returned from registry, expected EXCamera, got: %@", view);
276 }
277 } forView:reactTag ofClass:[EXCamera class]];
278}
279
280UM_EXPORT_METHOD_AS(resumePreview,
281 resumePreview:(nonnull NSNumber *)tag
282 resolver:(UMPromiseResolveBlock)resolve
283 rejecter:(UMPromiseRejectBlock)reject)
284{
285#pragma clang diagnostic push
286#pragma clang diagnostic ignored "-Wunreachable-code"
287#if TARGET_IPHONE_SIMULATOR
288 reject(@"E_SIM_PREVIEW", @"Resuming preview is not supported on simulator.", nil);
289 return;
290#endif
291 [_uiManager executeUIBlock:^(id view) {
292 if (view != nil) {
293 [view resumePreview];
294 resolve(nil);
295 } else {
296 UMLogError(@"Invalid view returned from registry, expected EXCamera, got: %@", view);
297 }
298 } forView:tag ofClass:[EXCamera class]];
299#pragma clang diagnostic pop
300}
301
302UM_EXPORT_METHOD_AS(pausePreview,
303 pausePreview:(nonnull NSNumber *)tag
304 resolver:(UMPromiseResolveBlock)resolve
305 rejecter:(UMPromiseRejectBlock)reject)
306{
307#pragma clang diagnostic push
308#pragma clang diagnostic ignored "-Wunreachable-code"
309#if TARGET_IPHONE_SIMULATOR
310 reject(@"E_SIM_PREVIEW", @"Pausing preview is not supported on simulator.", nil);
311 return;
312#endif
313 [_uiManager executeUIBlock:^(id view) {
314 if (view != nil) {
315 [view pausePreview];
316 resolve(nil);
317 } else {
318 UMLogError(@"Invalid view returned from registry, expected EXCamera, got: %@", view);
319 }
320 } forView:tag ofClass:[EXCamera class]];
321#pragma clang diagnostic pop
322}
323
324UM_EXPORT_METHOD_AS(getAvailablePictureSizes,
325 getAvailablePictureSizesWithRatio:(NSString *)ratio
326 tag:(nonnull NSNumber *)tag
327 resolver:(UMPromiseResolveBlock)resolve
328 rejecter:(UMPromiseRejectBlock)reject)
329{
330 resolve([[[self class] pictureSizes] allKeys]);
331}
332
333UM_EXPORT_METHOD_AS(getPermissionsAsync,
334 getPermissionsAsync:(UMPromiseResolveBlock)resolve
335 rejecter:(UMPromiseRejectBlock)reject)
336{
337 [UMPermissionsMethodsDelegate getPermissionWithPermissionsManager:_permissionsManager
338 withRequester:[EXCameraPermissionRequester class]
339 resolve:resolve
340 reject:reject];
341}
342
343UM_EXPORT_METHOD_AS(requestPermissionsAsync,
344 requestPermissionsAsync:(UMPromiseResolveBlock)resolve
345 rejecter:(UMPromiseRejectBlock)reject)
346{
347 [UMPermissionsMethodsDelegate askForPermissionWithPermissionsManager:_permissionsManager
348 withRequester:[EXCameraPermissionRequester class]
349 resolve:resolve
350 reject:reject];
351}
352
353@end