forked from mgcrea/vision-camera-barcode-scanner
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuseBarcodeScanner.ts
91 lines (80 loc) · 2.58 KB
/
useBarcodeScanner.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { type ViewProps } from "react-native";
import {
runAtTargetFps,
useFrameProcessor,
type CameraProps,
type Frame,
} from "react-native-vision-camera";
import { useSharedValue } from "react-native-worklets-core";
import { ScanBarcodesOptions, scanCodes } from "src/module";
import type { Barcode, BarcodeType, Rect, Size } from "src/types";
import { useLatestSharedValue } from "./useLatestSharedValue";
type ResizeMode = NonNullable<CameraProps["resizeMode"]>;
export type UseBarcodeScannerOptions = {
barcodeTypes?: BarcodeType[];
regionOfInterest?: Rect;
fps?: number;
onBarcodeScanned: (barcodes: Barcode[], frame: Frame) => void;
resizeMode?: ResizeMode;
isMountedRef?: { value: boolean };
disabled?: boolean;
};
export const useBarcodeScanner = ({
barcodeTypes,
regionOfInterest,
onBarcodeScanned,
resizeMode = "cover",
isMountedRef,
fps = 5,
disabled = false,
}: UseBarcodeScannerOptions) => {
// Layout of the <Camera /> component
const layoutRef = useSharedValue<Size>({ width: 0, height: 0 });
const onLayout: ViewProps["onLayout"] = (event) => {
const { width, height } = event.nativeEvent.layout;
layoutRef.value = { width, height };
};
const resizeModeRef = useLatestSharedValue<ResizeMode>(resizeMode);
const disabledRef = useLatestSharedValue(disabled);
const isPristineRef = useSharedValue<boolean>(true);
const frameProcessor = useFrameProcessor(
(frame) => {
"worklet";
if (isMountedRef && isMountedRef.value === false) {
return;
}
runAtTargetFps(fps, () => {
"worklet";
if (disabledRef.value) {
return;
}
// We must ignore the first frame because as it has width/height inverted (maybe the right value though?)
if (isPristineRef.value) {
isPristineRef.value = false;
return;
}
const { value: layout } = layoutRef;
const { value: resizeMode } = resizeModeRef;
// Call the native barcode scanner
const options: ScanBarcodesOptions = {};
if (barcodeTypes !== undefined) {
options.barcodeTypes = barcodeTypes;
}
if (regionOfInterest !== undefined) {
const { x, y, width, height } = regionOfInterest;
options.regionOfInterest = [x, y, width, height];
}
const barcodes = scanCodes(frame, layout, options, resizeMode);
if (barcodes.length === 0) return;
onBarcodeScanned(barcodes, frame);
});
},
[layoutRef, resizeModeRef],
);
return {
props: {
frameProcessor,
onLayout,
},
};
};