UNPKG

theta-client-react-native

Version:

This library provides a way to control RICOH THETA using.

248 lines (216 loc) 8.37 kB
import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; import { normalizeNativeError } from './theta-repository/theta-web-api-error'; import { isPromiseLike } from './theta-repository/libs'; export interface Spec extends TurboModule { // Event listeners for Android old architecture only addListener(eventName: string): void; removeListeners(count: number): void; // API Log setApiLogListener(enabled: boolean): Promise<void>; // Initialize initialize( endPoint: string, config: Object | null, timeout: Object | null ): Promise<boolean>; isInitialized(): Promise<boolean>; // Get theta info getThetaModel(): Promise<string | undefined>; getThetaInfo(): Promise<Object>; getThetaLicense(): Promise<string>; getThetaState(): Promise<Object>; // File operations listFiles( fileType: string, startPosition: number, entryCount: number, storage: string | null ): Promise<Object>; deleteFiles(fileUrls: Array<string>): Promise<boolean>; deleteAllFiles(): Promise<boolean>; deleteAllImageFiles(): Promise<boolean>; deleteAllVideoFiles(): Promise<boolean>; // Options getOptions(optionNames: Array<string>): Promise<Object>; setOptions(options: Object): Promise<boolean>; // Live preview getLivePreview(): Promise<boolean>; stopLivePreview(): Promise<boolean>; // Photo capture getPhotoCaptureBuilder(): Promise<void>; buildPhotoCapture(options: Object): Promise<void>; takePicture(): Promise<string>; // TimeShift capture getTimeShiftCaptureBuilder(): Promise<void>; buildTimeShiftCapture(options: Object): Promise<void>; startTimeShiftCapture(): Promise<string>; cancelTimeShiftCapture(): Promise<void>; // TimeShift manual capture getTimeShiftManualCaptureBuilder(): Promise<void>; buildTimeShiftManualCapture(options: Object): Promise<void>; startTimeShiftManualCapture(): Promise<string>; startTimeShiftManualSecondCapture(): Promise<string>; cancelTimeShiftManualCapture(): Promise<void>; // Video capture getVideoCaptureBuilder(): Promise<void>; buildVideoCapture(options: Object): Promise<void>; startVideoCapture(): Promise<string>; stopVideoCapture(): Promise<string>; // Limitless interval capture getLimitlessIntervalCaptureBuilder(): Promise<void>; buildLimitlessIntervalCapture(options: Object): Promise<void>; startLimitlessIntervalCapture(): Promise<Array<string>>; stopLimitlessIntervalCapture(): Promise<Array<string>>; // Shot count specified interval capture getShotCountSpecifiedIntervalCaptureBuilder(shotCount: number): Promise<void>; buildShotCountSpecifiedIntervalCapture(options: Object): Promise<void>; startShotCountSpecifiedIntervalCapture(): Promise<Array<string>>; cancelShotCountSpecifiedIntervalCapture(): Promise<void>; // Composite interval capture getCompositeIntervalCaptureBuilder(shootingTimeSec: number): Promise<void>; buildCompositeIntervalCapture(options: Object): Promise<void>; startCompositeIntervalCapture(): Promise<Array<string>>; cancelCompositeIntervalCapture(): Promise<void>; // Burst capture getBurstCaptureBuilder( burstCaptureNum: string, burstBracketStep: string, burstCompensation: string, burstMaxExposureTime: string, burstEnableIsoControl: string, burstOrder: string ): Promise<void>; buildBurstCapture(options: Object): Promise<void>; startBurstCapture(): Promise<Array<string>>; cancelBurstCapture(): Promise<void>; // Multi bracket capture getMultiBracketCaptureBuilder(): Promise<void>; buildMultiBracketCapture(options: Object): Promise<void>; startMultiBracketCapture(): Promise<Array<string>>; cancelMultiBracketCapture(): Promise<void>; // Continuous capture getContinuousCaptureBuilder(): Promise<void>; buildContinuousCapture(options: Object): Promise<void>; startContinuousCapture(): Promise<Array<string>>; // Metadata getMetadata(fileUrl: string): Promise<Object>; // Commands reboot(): Promise<void>; reset(): Promise<boolean>; restoreSettings(): Promise<boolean>; stopSelfTimer(): Promise<boolean>; // Video convert convertVideoFormats( fileUrl: string, toLowResolution: boolean, applyTopBottomCorrection: boolean ): Promise<string>; cancelVideoConvert(): Promise<boolean>; // WLAN finishWlan(): Promise<boolean>; listAccessPoints(): Promise<Array<Object>>; setAccessPointDynamically(params: Object): Promise<boolean>; setAccessPointStatically(params: Object): Promise<boolean>; setAccessPointConnectionPriority( ssid: string, connectionPriority: number, ssidStealth: boolean ): Promise<boolean>; deleteAccessPoint(ssid: string): Promise<boolean>; // My setting getMySetting(captureMode: string): Promise<Object>; getMySettingFromOldModel(optionNames: Array<string>): Promise<Object>; setMySetting(captureMode: string, options: Object): Promise<boolean>; deleteMySetting(captureMode: string): Promise<boolean>; // Plugin listPlugins(): Promise<Array<Object>>; setPlugin(packageName: string): Promise<boolean>; startPlugin(packageName: string): Promise<boolean>; stopPlugin(): Promise<boolean>; getPluginLicense(packageName: string): Promise<string>; getPluginOrders(): Promise<Array<string>>; setPluginOrders(plugins: Array<string>): Promise<boolean>; // Bluetooth setBluetoothDevice(uuid: string): Promise<string>; // Event WebSocket getEventWebSocket(): Promise<void>; eventWebSocketStart(): Promise<void>; eventWebSocketStop(): Promise<void>; } // New Architecture only: resolve TurboModule on first access let cachedModule: Spec | null = null; function getModule(): Spec { if (cachedModule != null) { return cachedModule; } const turbo = TurboModuleRegistry.get<Spec>('ThetaClientReactNative'); if (turbo == null) { // In test environment, return a mock object instead of throwing if ( process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined ) { cachedModule = {} as Spec; return cachedModule; } throw new Error( 'ThetaClientReactNative TurboModule could not be found. Ensure New Architecture is enabled and the module is registered in the native binary.' ); } cachedModule = turbo; return cachedModule; } export default new Proxy({} as Spec, { get(_, prop: string | symbol) { const module = getModule(); const value = module[prop as keyof Spec]; if (typeof value !== 'function') { return value; } // Wrap native async methods so rejected promises carry parsed THETA Web API details, // without adding extra microtask ticks on the success path. return (...args: unknown[]) => { const result = (value as (...innerArgs: unknown[]) => unknown).apply( module, args ); if (!isPromiseLike(result)) { return result; } // Wrap the original promise in a Proxy that intercepts .then()/.catch() to // normalize errors, while preserving the microtask timing of the original // promise on the success path (no extra .then() hops added). return new Proxy(result, { get(target, p) { if (p === 'then') { return ( onFulfilled: ((value: unknown) => unknown) | null | undefined, onRejected: ((reason: unknown) => unknown) | null | undefined ) => { const normalizedRejected = (err: unknown): unknown => onRejected != null ? onRejected(normalizeNativeError(err)) : Promise.reject(normalizeNativeError(err)); return (target as PromiseLike<unknown>).then( onFulfilled ?? undefined, normalizedRejected ); }; } if (p === 'catch') { return ( onRejected: ((reason: unknown) => unknown) | null | undefined ) => (target as Promise<unknown>).catch((err: unknown) => onRejected != null ? onRejected(normalizeNativeError(err)) : Promise.reject(normalizeNativeError(err)) ); } return (target as unknown as Record<string | symbol, unknown>)[p]; }, }); }; }, });