c40b5565d3
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.
62 lines
2.7 KiB
TypeScript
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;
|