Files
RecipesCam/modules/recipescam-ultrawide/index.ts
T
admin c40b5565d3 Fire the LED on the 0.5x still
0.5x is a bare Camera2 session, so CameraX never saw the flash setting and the ultra-wide still came off unlit. The native module now reads FLASH_INFO_AVAILABLE off the lens, maps off/auto/on to CONTROL_AE_MODE plus FLASH_MODE_SINGLE, and starts an AE precapture so the HAL can meter the flash before the frame. The viewfinder hands its flashMode down beside the shutter, with a Zap control that only appears where a unit exists.
2026-09-16 18:11:17 +07:00

62 lines
2.7 KiB
TypeScript

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<string>;
/**
* 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<string>;
/**
* 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<void>;
/** Back to whole-frame continuous AF/AE. */
resetFocusAsync(): Promise<void>;
/**
* 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<void>;
/**
* 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<void>;
/** Takes the ultra-wide again after a closeAsync whose handoff was cancelled. */
reopenAsync(): Promise<void>;
}
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<UltraWidePreviewProps>(
'RecipesCamUltraWide',
'UltraWidePreviewView'
) as ComponentType<UltraWidePreviewProps>;
export default requireNativeModule('RecipesCamUltraWide') as UltraWideModule;