import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; import { NativeSyntheticEvent, Platform, StyleSheet, View } from 'react-native'; import { BarcodeItem, autorelease, createSBError } from '../../types'; import NativeBarcodeCameraView, { Commands, } from '../spec/ScanbotBarcodeScannerViewNativeComponent'; import { ScanbotBarcodeCameraViewHandle, ScanbotBarcodeCameraViewProperties, } from './ScanbotBarcodeCameraViewProperties'; export const ScanbotBarcodeCameraView = forwardRef< ScanbotBarcodeCameraViewHandle, ScanbotBarcodeCameraViewProperties >(({ onBarcodeScannerResult, onBarcodeTap, onError, ...props }, forwardedRef) => { const viewRef = useRef(null); const boundBarcodeItemOverlayViews = useRef>(new Map()); useImperativeHandle(forwardedRef, () => { return { freezeCamera() { if (viewRef.current) { Commands.freezeCamera(viewRef.current); } }, unfreezeCamera() { if (viewRef.current) { Commands.unfreezeCamera(viewRef.current); } }, }; }, []); const _onBarcodeScannerResult = useCallback( async (event: NativeSyntheticEvent) => { const result = event.nativeEvent.result; if (result) { const barcodeItems = (Platform.OS === 'ios' ? JSON.parse(result) : result) as any[]; autorelease(async () => { await onBarcodeScannerResult(barcodeItems.map((item) => new BarcodeItem(item))); }); if (props.selectionOverlayConfig?.barcodeItemOverlayViewBinder) { for (let barcode of barcodeItems) { const barcodeItemUuid = barcode.text + barcode.upcEanExtension + '_' + barcode.format; const barcodeItemNextBind = boundBarcodeItemOverlayViews.current.get(barcodeItemUuid); if ( barcodeItemNextBind === undefined || (barcodeItemNextBind !== -1 && Date.now() >= barcodeItemNextBind) ) { boundBarcodeItemOverlayViews.current.set(barcodeItemUuid, -1); const bindingConfig = await props.selectionOverlayConfig.barcodeItemOverlayViewBinder(barcode); if (bindingConfig.refreshRate !== undefined && bindingConfig.refreshRate > 0) { boundBarcodeItemOverlayViews.current.set( barcodeItemUuid, Date.now() + bindingConfig.refreshRate ); } if (viewRef.current != null) { Commands.bindBarcodeItemOverlayView( viewRef.current, barcodeItemUuid, JSON.stringify(bindingConfig) ); } } } } else { boundBarcodeItemOverlayViews.current.clear(); } } }, [props.selectionOverlayConfig, boundBarcodeItemOverlayViews, onBarcodeScannerResult] ); const _onBarcodeSelectionResult = useCallback( (event: NativeSyntheticEvent) => { const result = event.nativeEvent.result; if (result && onBarcodeTap) { autorelease(() => { onBarcodeTap( new BarcodeItem((Platform.OS === 'ios' ? JSON.parse(result)[0] : result) as any) ); }); } }, [onBarcodeTap] ); const _onError = useCallback( (event: NativeSyntheticEvent) => { if (onError) { onError(createSBError(event.nativeEvent)); } }, [onError] ); return ( {props.children} ); }); const styles = StyleSheet.create({ container: { flex: 1, }, contentContainerStyle: { position: 'absolute', width: '100%', height: '100%', zIndex: 2, }, });