import { requireNativeModule, requireNativeViewManager } from 'expo-modules-core'; import type { ComponentType } from 'react'; import type { ViewProps } from 'react-native'; import type { FlashMode } from '../../src/types'; export interface UltraWideModule { /** Hidden back ultra-wide camera id ('' when this device has none). */ availableAsync(): Promise; /** * Still capture from the ultra-wide lens; resolves to an absolute file path. * `flashMode` is the viewfinder's setting, driven straight into the still * request's FLASH_MODE — the lens falls back to 'off' on its own when it has * no flash unit to fire. */ captureAsync(flashMode: FlashMode): Promise; /** * Tap-to-focus + spot metering on the ultra-wide lens, at a point in the * preview view (React Native dp, same space as a touch's locationX/Y). The * main CameraX session is stopped while 0.5x is live, so this is the only * focus path that exists in that mode. */ focusAsync(x: number, y: number): Promise; /** Back to whole-frame continuous AF/AE. */ resetFocusAsync(): Promise; /** * Hardware AE bias, in EV stops, for the live 0.5x preview. The 1x preview * gets its EV from the Skia matrix gain, but this feed is a bare Camera2 * surface with no frame pipeline behind it, so the lens has to be biased. * Preview only: the still is captured without the bias, exactly like the 1x * path, so the export applies the software gain once and the file matches. */ setEvAsync(ev: number): Promise; /** * Closes the native session and resolves once the HAL has really released the * back camera slot. Leaving 0.5x must wait for this before switching the 1x * preview back on: the two back lenses cannot open at once, so an early 1x * open is refused and only retried ~520ms later. */ closeAsync(): Promise; /** Takes the ultra-wide again after a closeAsync whose handoff was cancelled. */ reopenAsync(): Promise; } export interface UltraWidePreviewProps extends ViewProps { /** Opens the camera while true, closes it on false/unmount. */ active: boolean; /** * Draws this view while true, session or not. While the session is open the * first frame gates it (the previous session's last frame must not show), and * after it closes the texture holds its last frame — which is what lets the * caller keep the ultra-wide on screen until the main preview is live again. */ cover: boolean; } export const UltraWidePreview = requireNativeViewManager( 'RecipesCamUltraWide', 'UltraWidePreviewView' ) as ComponentType; export default requireNativeModule('RecipesCamUltraWide') as UltraWideModule;