expo-harmony-toolkit 1.7.2 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.en.md +20 -9
  2. package/README.md +22 -11
  3. package/build/core/autolinking.d.ts +10 -0
  4. package/build/core/autolinking.js +421 -0
  5. package/build/core/build/commands.d.ts +19 -0
  6. package/build/core/build/commands.js +61 -0
  7. package/build/core/build/compatibilityShims.d.ts +1 -0
  8. package/build/core/build/compatibilityShims.js +272 -0
  9. package/build/core/build/localHar.d.ts +13 -0
  10. package/build/core/build/localHar.js +337 -0
  11. package/build/core/build/reporting.d.ts +19 -0
  12. package/build/core/build/reporting.js +67 -0
  13. package/build/core/build/rnohCompatibility.d.ts +1 -0
  14. package/build/core/build/rnohCompatibility.js +38 -0
  15. package/build/core/build.d.ts +4 -12
  16. package/build/core/build.js +70 -762
  17. package/build/core/constants.d.ts +2 -1
  18. package/build/core/constants.js +3 -2
  19. package/build/core/dependencyInspection.d.ts +2 -0
  20. package/build/core/dependencyInspection.js +112 -0
  21. package/build/core/env.js +1 -1
  22. package/build/core/report.js +33 -10
  23. package/build/core/signing.d.ts +2 -0
  24. package/build/core/signing.js +30 -0
  25. package/build/core/template/capabilityRegistry.d.ts +9 -0
  26. package/build/core/template/capabilityRegistry.js +84 -0
  27. package/build/core/template/expoModulesCoreShim.d.ts +2 -0
  28. package/build/core/template/expoModulesCoreShim.js +279 -0
  29. package/build/core/template/metro.d.ts +2 -0
  30. package/build/core/template/metro.js +213 -0
  31. package/build/core/template/nativeFiles.d.ts +8 -0
  32. package/build/core/template/nativeFiles.js +333 -0
  33. package/build/core/template/renderers/camera.d.ts +4 -0
  34. package/build/core/template/renderers/camera.js +612 -0
  35. package/build/core/template/renderers/fileSystem.d.ts +4 -0
  36. package/build/core/template/renderers/fileSystem.js +814 -0
  37. package/build/core/template/renderers/imagePicker.d.ts +4 -0
  38. package/build/core/template/renderers/imagePicker.js +753 -0
  39. package/build/core/template/renderers/location.d.ts +4 -0
  40. package/build/core/template/renderers/location.js +836 -0
  41. package/build/core/template/runtimeShims.d.ts +2 -0
  42. package/build/core/template/runtimeShims.js +192 -0
  43. package/build/core/template/support.d.ts +11 -0
  44. package/build/core/template/support.js +108 -0
  45. package/build/core/template.d.ts +2 -6
  46. package/build/core/template.js +40 -4453
  47. package/build/data/capabilities.js +21 -4
  48. package/build/data/dependencyCatalog.js +10 -0
  49. package/build/data/publicDocs.d.ts +11 -0
  50. package/build/data/publicDocs.js +28 -0
  51. package/build/data/validatedMatrices.js +9 -1
  52. package/build/docs/render.d.ts +9 -0
  53. package/build/docs/render.js +248 -0
  54. package/build/types.d.ts +12 -0
  55. package/docs/cli-build.md +1 -1
  56. package/docs/npm-release.md +1 -0
  57. package/docs/official-app-shell-sample.md +2 -1
  58. package/docs/official-minimal-sample.md +2 -1
  59. package/docs/official-native-capabilities-sample.md +3 -2
  60. package/docs/official-ui-stack-sample.md +2 -1
  61. package/docs/signing-and-release.md +3 -0
  62. package/docs/support-matrix.md +34 -9
  63. package/package.json +13 -5
  64. package/docs/v1.5.1-acceptance.md +0 -385
  65. package/docs/v1.6.0-acceptance.md +0 -193
  66. package/docs/v1.7.0-acceptance.md +0 -111
  67. package/docs/v1.7.1-acceptance.md +0 -111
  68. package/docs/v1.7.2-acceptance.md +0 -37
@@ -0,0 +1,612 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderExpoHarmonyCameraTurboModule = renderExpoHarmonyCameraTurboModule;
4
+ exports.renderExpoCameraHarmonyAdapterShim = renderExpoCameraHarmonyAdapterShim;
5
+ exports.renderExpoCameraPreviewShim = renderExpoCameraPreviewShim;
6
+ function renderExpoHarmonyCameraTurboModule() {
7
+ return `import type { Permissions } from '@ohos.abilityAccessCtrl';
8
+ import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
9
+ import camera from '@ohos.multimedia.camera';
10
+ import cameraPicker from '@ohos.multimedia.cameraPicker';
11
+ import image from '@ohos.multimedia.image';
12
+ import { UITurboModuleContext, UITurboModule } from '@rnoh/react-native-openharmony/ts';
13
+
14
+ type PermissionResponse = {
15
+ status: 'granted' | 'denied' | 'undetermined';
16
+ granted: boolean;
17
+ canAskAgain: boolean;
18
+ expires: 'never';
19
+ };
20
+
21
+ type CameraCaptureResult = {
22
+ uri: string;
23
+ width: number;
24
+ height: number;
25
+ base64?: string;
26
+ exif: null;
27
+ };
28
+
29
+ type CameraRecordingResult = {
30
+ uri: string;
31
+ duration: number;
32
+ fileSize: number | null;
33
+ mimeType: string;
34
+ };
35
+
36
+ export class ExpoHarmonyCameraTurboModule extends UITurboModule {
37
+ public static readonly NAME = 'ExpoHarmonyCamera';
38
+
39
+ private readonly atManager = abilityAccessCtrl.createAtManager();
40
+ private readonly previewStates = new Map<string, 'running' | 'paused'>();
41
+ private readonly activeRecordings = new Map<string, CameraRecordingResult>();
42
+
43
+ getConstants(): Record<string, never> {
44
+ return {};
45
+ }
46
+
47
+ async getCameraPermissionStatus(): Promise<PermissionResponse> {
48
+ return this.getPermissionResponse('ohos.permission.CAMERA');
49
+ }
50
+
51
+ async requestCameraPermission(): Promise<PermissionResponse> {
52
+ return this.requestPermissionResponse('ohos.permission.CAMERA');
53
+ }
54
+
55
+ async getMicrophonePermissionStatus(): Promise<PermissionResponse> {
56
+ return this.getPermissionResponse('ohos.permission.MICROPHONE');
57
+ }
58
+
59
+ async requestMicrophonePermission(): Promise<PermissionResponse> {
60
+ return this.requestPermissionResponse('ohos.permission.MICROPHONE');
61
+ }
62
+
63
+ async createPreview(options?: { viewId?: string }): Promise<{ viewId: string; state: 'running' }> {
64
+ const viewId = typeof options?.viewId === 'string' && options.viewId.length > 0
65
+ ? options.viewId
66
+ : 'expo-harmony-camera-preview';
67
+ this.previewStates.set(viewId, 'running');
68
+ return {
69
+ viewId,
70
+ state: 'running',
71
+ };
72
+ }
73
+
74
+ async disposePreview(options?: { viewId?: string }): Promise<void> {
75
+ if (typeof options?.viewId === 'string') {
76
+ this.previewStates.delete(options.viewId);
77
+ this.activeRecordings.delete(options.viewId);
78
+ }
79
+ }
80
+
81
+ async pausePreview(options?: { viewId?: string }): Promise<{ paused: boolean }> {
82
+ if (typeof options?.viewId === 'string') {
83
+ this.previewStates.set(options.viewId, 'paused');
84
+ }
85
+ return {
86
+ paused: true,
87
+ };
88
+ }
89
+
90
+ async resumePreview(options?: { viewId?: string }): Promise<{ paused: boolean }> {
91
+ if (typeof options?.viewId === 'string') {
92
+ this.previewStates.set(options.viewId, 'running');
93
+ }
94
+ return {
95
+ paused: false,
96
+ };
97
+ }
98
+
99
+ async takePicture(options?: { cameraType?: string; viewId?: string }): Promise<CameraCaptureResult> {
100
+ const profile = new cameraPicker.PickerProfile();
101
+ profile.cameraPosition =
102
+ options?.cameraType === 'front'
103
+ ? camera.CameraPosition.CAMERA_POSITION_FRONT
104
+ : camera.CameraPosition.CAMERA_POSITION_BACK;
105
+
106
+ const result = await cameraPicker.pick(
107
+ this.ctx.uiAbilityContext,
108
+ [cameraPicker.PickerMediaType.PHOTO],
109
+ profile,
110
+ );
111
+
112
+ if (!result || typeof result.resultUri !== 'string' || result.resultUri.length === 0) {
113
+ throw new Error('Camera capture was canceled.');
114
+ }
115
+
116
+ const imageSize = await this.getImageSize(result.resultUri);
117
+
118
+ return {
119
+ uri: result.resultUri,
120
+ width: imageSize.width,
121
+ height: imageSize.height,
122
+ exif: null,
123
+ };
124
+ }
125
+
126
+ async startRecording(options?: { viewId?: string; cameraType?: string }): Promise<CameraRecordingResult> {
127
+ await this.requestPermissionResponse('ohos.permission.MICROPHONE');
128
+ const profile = new cameraPicker.PickerProfile();
129
+ profile.cameraPosition =
130
+ options?.cameraType === 'front'
131
+ ? camera.CameraPosition.CAMERA_POSITION_FRONT
132
+ : camera.CameraPosition.CAMERA_POSITION_BACK;
133
+
134
+ const result = await cameraPicker.pick(
135
+ this.ctx.uiAbilityContext,
136
+ [cameraPicker.PickerMediaType.VIDEO],
137
+ profile,
138
+ );
139
+
140
+ if (!result || typeof result.resultUri !== 'string' || result.resultUri.length === 0) {
141
+ throw new Error('Camera recording was canceled.');
142
+ }
143
+
144
+ const recording = {
145
+ uri: result.resultUri,
146
+ duration: 0,
147
+ fileSize: null,
148
+ mimeType: 'video/mp4',
149
+ };
150
+
151
+ if (typeof options?.viewId === 'string') {
152
+ this.activeRecordings.set(options.viewId, recording);
153
+ }
154
+
155
+ return recording;
156
+ }
157
+
158
+ async stopRecording(options?: { viewId?: string }): Promise<CameraRecordingResult | null> {
159
+ if (typeof options?.viewId === 'string') {
160
+ const recording = this.activeRecordings.get(options.viewId) ?? null;
161
+ this.activeRecordings.delete(options.viewId);
162
+ return recording;
163
+ }
164
+
165
+ return null;
166
+ }
167
+
168
+ async toggleRecording(options?: { viewId?: string; cameraType?: string }): Promise<CameraRecordingResult | null> {
169
+ if (typeof options?.viewId === 'string' && this.activeRecordings.has(options.viewId)) {
170
+ return this.stopRecording(options);
171
+ }
172
+
173
+ return this.startRecording(options);
174
+ }
175
+
176
+ private async getPermissionResponse(permissionName: Permissions): Promise<PermissionResponse> {
177
+ const atManagerWithSelfStatus = this.atManager as abilityAccessCtrl.AtManager & {
178
+ getSelfPermissionStatus?: (permission: Permissions) => abilityAccessCtrl.PermissionStatus;
179
+ };
180
+ const permissionStatus =
181
+ typeof atManagerWithSelfStatus.getSelfPermissionStatus === 'function'
182
+ ? atManagerWithSelfStatus.getSelfPermissionStatus(permissionName)
183
+ : this.atManager.checkAccessTokenSync(
184
+ this.ctx.uiAbilityContext.abilityInfo.applicationInfo.accessTokenId,
185
+ permissionName,
186
+ ) === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED
187
+ ? abilityAccessCtrl.PermissionStatus.GRANTED
188
+ : abilityAccessCtrl.PermissionStatus.NOT_DETERMINED;
189
+
190
+ return this.createPermissionResponse(permissionStatus);
191
+ }
192
+
193
+ private async requestPermissionResponse(permissionName: Permissions): Promise<PermissionResponse> {
194
+ await this.atManager.requestPermissionsFromUser(this.ctx.uiAbilityContext, [permissionName]);
195
+ return this.getPermissionResponse(permissionName);
196
+ }
197
+
198
+ private createPermissionResponse(
199
+ permissionStatus: abilityAccessCtrl.PermissionStatus,
200
+ ): PermissionResponse {
201
+ const granted = permissionStatus === abilityAccessCtrl.PermissionStatus.GRANTED;
202
+ const denied =
203
+ permissionStatus === abilityAccessCtrl.PermissionStatus.DENIED ||
204
+ permissionStatus === abilityAccessCtrl.PermissionStatus.RESTRICTED ||
205
+ permissionStatus === abilityAccessCtrl.PermissionStatus.INVALID;
206
+
207
+ return {
208
+ status: granted ? 'granted' : denied ? 'denied' : 'undetermined',
209
+ granted,
210
+ canAskAgain: !denied,
211
+ expires: 'never',
212
+ };
213
+ }
214
+
215
+ private async getImageSize(assetUri: string): Promise<{ width: number; height: number }> {
216
+ let imageSource: image.ImageSource | null = null;
217
+
218
+ try {
219
+ imageSource = image.createImageSource(assetUri);
220
+ const imageInfo = await imageSource.getImageInfo();
221
+ return {
222
+ width: Number(imageInfo.size?.width ?? 0),
223
+ height: Number(imageInfo.size?.height ?? 0),
224
+ };
225
+ } catch (_error) {
226
+ return {
227
+ width: 0,
228
+ height: 0,
229
+ };
230
+ } finally {
231
+ if (imageSource) {
232
+ try {
233
+ await imageSource.release();
234
+ } catch (_error) {
235
+ // Ignore cleanup errors from ImageSource release.
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ `;
242
+ }
243
+ function renderExpoCameraHarmonyAdapterShim(capability) {
244
+ return `'use strict';
245
+
246
+ const React = require('react');
247
+ const { TurboModuleRegistry, requireNativeComponent } = require('react-native');
248
+ const { CodedError } = require('expo-modules-core');
249
+
250
+ const NATIVE_MODULE_NAME = 'ExpoHarmonyCamera';
251
+ const NATIVE_MODULE = TurboModuleRegistry.get(NATIVE_MODULE_NAME);
252
+ const NativeCameraView = requireNativeComponent('ExpoHarmonyCameraView');
253
+ const DEFAULT_PERMISSION_RESPONSE = {
254
+ status: 'undetermined',
255
+ granted: false,
256
+ canAskAgain: true,
257
+ expires: 'never',
258
+ };
259
+ let nextCameraViewId = 1;
260
+
261
+ function createError(code, message) {
262
+ return new CodedError(code, message);
263
+ }
264
+
265
+ function createUnsupportedError(operationName) {
266
+ return createError(
267
+ 'ERR_EXPO_HARMONY_UNSUPPORTED',
268
+ '${capability.packageName} does not implement ' + operationName + ' on HarmonyOS yet.',
269
+ );
270
+ }
271
+
272
+ function requireNativeModule(operationName) {
273
+ if (NATIVE_MODULE) {
274
+ return NATIVE_MODULE;
275
+ }
276
+
277
+ throw createError(
278
+ 'ERR_EXPO_HARMONY_NATIVE_MODULE_MISSING',
279
+ '${capability.packageName} expected the ' +
280
+ NATIVE_MODULE_NAME +
281
+ ' TurboModule to be registered, but it was missing while running ' +
282
+ operationName +
283
+ '.',
284
+ );
285
+ }
286
+
287
+ function normalizeNativeError(error) {
288
+ if (error instanceof Error) {
289
+ return error;
290
+ }
291
+
292
+ if (error && typeof error === 'object') {
293
+ const code =
294
+ typeof error.code === 'number' || typeof error.code === 'string'
295
+ ? String(error.code)
296
+ : null;
297
+ const message =
298
+ typeof error.message === 'string' && error.message.length > 0
299
+ ? error.message
300
+ : typeof error.name === 'string' && error.name.length > 0
301
+ ? error.name
302
+ : JSON.stringify(error);
303
+
304
+ return new Error(code ? '[native:' + code + '] ' + message : message);
305
+ }
306
+
307
+ return new Error(String(error));
308
+ }
309
+
310
+ async function invokeNative(methodName, operationName, ...args) {
311
+ try {
312
+ return await requireNativeModule(operationName)[methodName](...args);
313
+ } catch (error) {
314
+ throw normalizeNativeError(error);
315
+ }
316
+ }
317
+
318
+ function normalizePermissionResponse(permissionResponse) {
319
+ return {
320
+ status: permissionResponse?.status ?? DEFAULT_PERMISSION_RESPONSE.status,
321
+ granted: permissionResponse?.granted === true,
322
+ canAskAgain: permissionResponse?.canAskAgain !== false,
323
+ expires: permissionResponse?.expires ?? DEFAULT_PERMISSION_RESPONSE.expires,
324
+ };
325
+ }
326
+
327
+ function normalizeCameraFacing(facing) {
328
+ return facing === 'front' ? 'front' : 'back';
329
+ }
330
+
331
+ const CameraView = React.forwardRef(function ExpoHarmonyCameraView(props, ref) {
332
+ const viewIdRef = React.useRef(null);
333
+
334
+ if (!viewIdRef.current) {
335
+ viewIdRef.current = 'expo-harmony-camera-view-' + String(nextCameraViewId++);
336
+ }
337
+
338
+ const viewId = viewIdRef.current;
339
+
340
+ React.useEffect(() => {
341
+ void invokeNative('createPreview', 'CameraView.mount', {
342
+ viewId,
343
+ facing: normalizeCameraFacing(props.facing),
344
+ mode: props.mode ?? 'picture',
345
+ }).catch(() => {});
346
+
347
+ return () => {
348
+ void invokeNative('disposePreview', 'CameraView.unmount', {
349
+ viewId,
350
+ }).catch(() => {});
351
+ };
352
+ }, [props.facing, props.mode, viewId]);
353
+
354
+ React.useImperativeHandle(
355
+ ref,
356
+ () => ({
357
+ async takePictureAsync(options) {
358
+ return invokeNative('takePicture', 'CameraView.takePictureAsync', {
359
+ viewId,
360
+ cameraType: normalizeCameraFacing(props.facing),
361
+ ...options,
362
+ });
363
+ },
364
+ async pausePreview() {
365
+ return invokeNative('pausePreview', 'CameraView.pausePreview', {
366
+ viewId,
367
+ });
368
+ },
369
+ async resumePreview() {
370
+ return invokeNative('resumePreview', 'CameraView.resumePreview', {
371
+ viewId,
372
+ });
373
+ },
374
+ async getAvailablePictureSizesAsync() {
375
+ throw createUnsupportedError('CameraView.getAvailablePictureSizesAsync');
376
+ },
377
+ async getAvailableLensesAsync() {
378
+ throw createUnsupportedError('CameraView.getAvailableLensesAsync');
379
+ },
380
+ async recordAsync(options) {
381
+ return invokeNative('startRecording', 'CameraView.recordAsync', {
382
+ viewId,
383
+ cameraType: normalizeCameraFacing(props.facing),
384
+ ...options,
385
+ });
386
+ },
387
+ async stopRecording() {
388
+ return invokeNative('stopRecording', 'CameraView.stopRecording', {
389
+ viewId,
390
+ });
391
+ },
392
+ async toggleRecordingAsync(options) {
393
+ return invokeNative('toggleRecording', 'CameraView.toggleRecordingAsync', {
394
+ viewId,
395
+ cameraType: normalizeCameraFacing(props.facing),
396
+ ...options,
397
+ });
398
+ },
399
+ }),
400
+ [props.facing, viewId],
401
+ );
402
+
403
+ return React.createElement(NativeCameraView, {
404
+ ...props,
405
+ viewId,
406
+ facing: normalizeCameraFacing(props.facing),
407
+ accessibilityLabel: props.accessibilityLabel ?? 'Expo Harmony embedded camera preview',
408
+ style: [
409
+ {
410
+ minHeight: 220,
411
+ overflow: 'hidden',
412
+ backgroundColor: '#111827',
413
+ },
414
+ props.style,
415
+ ],
416
+ });
417
+ });
418
+
419
+ CameraView.displayName = 'ExpoHarmonyCameraView';
420
+
421
+ async function getCameraPermissionsAsync() {
422
+ return normalizePermissionResponse(
423
+ await invokeNative('getCameraPermissionStatus', 'getCameraPermissionsAsync'),
424
+ );
425
+ }
426
+
427
+ async function requestCameraPermissionsAsync() {
428
+ return normalizePermissionResponse(
429
+ await invokeNative('requestCameraPermission', 'requestCameraPermissionsAsync'),
430
+ );
431
+ }
432
+
433
+ async function getMicrophonePermissionsAsync() {
434
+ return normalizePermissionResponse(
435
+ await invokeNative('getMicrophonePermissionStatus', 'getMicrophonePermissionsAsync'),
436
+ );
437
+ }
438
+
439
+ async function requestMicrophonePermissionsAsync() {
440
+ return normalizePermissionResponse(
441
+ await invokeNative('requestMicrophonePermission', 'requestMicrophonePermissionsAsync'),
442
+ );
443
+ }
444
+
445
+ module.exports = {
446
+ CameraType: {
447
+ front: 'front',
448
+ back: 'back',
449
+ },
450
+ FlashMode: {
451
+ off: 'off',
452
+ on: 'on',
453
+ auto: 'auto',
454
+ torch: 'torch',
455
+ },
456
+ CameraView,
457
+ Camera: {
458
+ CameraType: {
459
+ front: 'front',
460
+ back: 'back',
461
+ },
462
+ Constants: {
463
+ Type: {
464
+ front: 'front',
465
+ back: 'back',
466
+ },
467
+ FlashMode: {
468
+ off: 'off',
469
+ on: 'on',
470
+ auto: 'auto',
471
+ torch: 'torch',
472
+ },
473
+ },
474
+ getCameraPermissionsAsync,
475
+ requestCameraPermissionsAsync,
476
+ getMicrophonePermissionsAsync,
477
+ requestMicrophonePermissionsAsync,
478
+ },
479
+ getCameraPermissionsAsync,
480
+ requestCameraPermissionsAsync,
481
+ getMicrophonePermissionsAsync,
482
+ requestMicrophonePermissionsAsync,
483
+ async scanFromURLAsync() {
484
+ throw createUnsupportedError('scanFromURLAsync');
485
+ },
486
+ };
487
+ `;
488
+ }
489
+ function renderExpoCameraPreviewShim(capability) {
490
+ return `'use strict';
491
+
492
+ const React = require('react');
493
+ const { Text, View } = require('react-native');
494
+ const { CodedError } = require('expo-modules-core');
495
+
496
+ const PREVIEW_MESSAGE =
497
+ '${capability.packageName} is routed through the Expo Harmony ${capability.supportTier} bridge. Bundling is supported, and a managed preview surface can render, but device-side camera permission and capture flows still need validation.';
498
+ const DEFAULT_PERMISSION_RESPONSE = {
499
+ status: 'undetermined',
500
+ granted: false,
501
+ canAskAgain: true,
502
+ expires: 'never',
503
+ };
504
+
505
+ function createPreviewError(operationName) {
506
+ return new CodedError(
507
+ 'ERR_EXPO_HARMONY_PREVIEW',
508
+ PREVIEW_MESSAGE + ' Attempted operation: ' + operationName + '.',
509
+ );
510
+ }
511
+
512
+ async function unavailable(operationName) {
513
+ throw createPreviewError(operationName);
514
+ }
515
+
516
+ function getPermissionResponse() {
517
+ return { ...DEFAULT_PERMISSION_RESPONSE };
518
+ }
519
+
520
+ const CameraView = React.forwardRef(function ExpoHarmonyCameraPreview(props, ref) {
521
+ React.useImperativeHandle(ref, () => ({
522
+ takePictureAsync(options) {
523
+ return unavailable('CameraView.takePictureAsync(' + JSON.stringify(options ?? {}) + ')');
524
+ },
525
+ pausePreview() {
526
+ return unavailable('CameraView.pausePreview()');
527
+ },
528
+ resumePreview() {
529
+ return unavailable('CameraView.resumePreview()');
530
+ },
531
+ }));
532
+
533
+ return React.createElement(
534
+ View,
535
+ {
536
+ style: [
537
+ {
538
+ minHeight: 220,
539
+ alignItems: 'center',
540
+ justifyContent: 'center',
541
+ borderRadius: 20,
542
+ borderWidth: 1,
543
+ borderStyle: 'dashed',
544
+ borderColor: '#14b8a6',
545
+ backgroundColor: '#ccfbf1',
546
+ padding: 20,
547
+ },
548
+ props.style,
549
+ ],
550
+ accessibilityLabel: 'Expo Harmony preview camera surface',
551
+ },
552
+ React.createElement(
553
+ Text,
554
+ {
555
+ style: {
556
+ color: '#0f766e',
557
+ fontSize: 14,
558
+ fontWeight: '600',
559
+ textAlign: 'center',
560
+ },
561
+ },
562
+ 'Expo Harmony preview camera surface',
563
+ ),
564
+ );
565
+ });
566
+
567
+ CameraView.displayName = 'ExpoHarmonyCameraPreview';
568
+
569
+ module.exports = {
570
+ CameraType: {
571
+ front: 'front',
572
+ back: 'back',
573
+ },
574
+ FlashMode: {
575
+ off: 'off',
576
+ on: 'on',
577
+ auto: 'auto',
578
+ torch: 'torch',
579
+ },
580
+ CameraView,
581
+ requestCameraPermissionsAsync() {
582
+ return unavailable('requestCameraPermissionsAsync');
583
+ },
584
+ getCameraPermissionsAsync() {
585
+ return Promise.resolve(getPermissionResponse());
586
+ },
587
+ requestMicrophonePermissionsAsync() {
588
+ return unavailable('requestMicrophonePermissionsAsync');
589
+ },
590
+ getMicrophonePermissionsAsync() {
591
+ return Promise.resolve(getPermissionResponse());
592
+ },
593
+ Camera: {
594
+ getCameraPermissionsAsync() {
595
+ return Promise.resolve(getPermissionResponse());
596
+ },
597
+ requestCameraPermissionsAsync() {
598
+ return unavailable('Camera.requestCameraPermissionsAsync');
599
+ },
600
+ getMicrophonePermissionsAsync() {
601
+ return Promise.resolve(getPermissionResponse());
602
+ },
603
+ requestMicrophonePermissionsAsync() {
604
+ return unavailable('Camera.requestMicrophonePermissionsAsync');
605
+ },
606
+ },
607
+ scanFromURLAsync() {
608
+ return unavailable('scanFromURLAsync');
609
+ },
610
+ };
611
+ `;
612
+ }
@@ -0,0 +1,4 @@
1
+ import { CapabilityDefinition } from '../../../types';
2
+ export declare function renderExpoHarmonyFileSystemTurboModule(): string;
3
+ export declare function renderExpoFileSystemHarmonyAdapterShim(capability: CapabilityDefinition): string;
4
+ export declare function renderExpoFileSystemPreviewShim(capability: CapabilityDefinition): string;