Skip to content

Commit e56c0f9

Browse files
committed
chore: add advance config and handle media not ready state
1 parent e8d44a8 commit e56c0f9

File tree

8 files changed

+39
-18
lines changed

8 files changed

+39
-18
lines changed

packages/pluggableWidgets/barcode-scanner-web/src/BarcodeScanner.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export const BarcodeScanner: FunctionComponent<BarcodeScannerContainerProps> = p
2828
height={props.height}
2929
widthUnit={props.widthUnit}
3030
width={props.width}
31+
detectionLogic={props.detectionLogic}
3132
/>
3233
);
3334
};

packages/pluggableWidgets/barcode-scanner-web/src/BarcodeScanner.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
<systemProperty key="Visibility" />
6363
</propertyGroup>
6464
</propertyGroup>
65-
6665
<propertyGroup caption="Dimensions">
6766
<propertyGroup caption="Dimensions">
6867
<property key="widthUnit" type="enumeration" defaultValue="percentage">
@@ -92,5 +91,15 @@
9291
</property>
9392
</propertyGroup>
9493
</propertyGroup>
94+
<propertyGroup caption="Advanced">
95+
<property key="detectionLogic" type="enumeration" defaultValue="native">
96+
<caption>Detection logic</caption>
97+
<description>Choose the detection logic to use for barcode scanning.</description>
98+
<enumerationValues>
99+
<enumerationValue key="zxing">Zxing</enumerationValue>
100+
<enumerationValue key="native">BarcodeDetector API (experimental, fallback to Zxing)</enumerationValue>
101+
</enumerationValues>
102+
</property>
103+
</propertyGroup>
95104
</properties>
96105
</widget>

packages/pluggableWidgets/barcode-scanner-web/src/components/BarcodeScanner.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Alert } from "@mendix/widget-plugin-component-kit/Alert";
44
import { Dimensions, getDimensions } from "@mendix/widget-plugin-platform/utils/get-dimensions";
55
import { useCustomErrorMessage } from "../hooks/useCustomErrorMessage";
66
import { useReader } from "../hooks/useReader";
7-
import { BarcodeFormatsType } from "../../typings/BarcodeScannerProps";
7+
import { BarcodeFormatsType, BarcodeScannerContainerProps } from "../../typings/BarcodeScannerProps";
88

99
import "../ui/BarcodeScanner.scss";
1010

@@ -57,6 +57,7 @@ export interface BarcodeScannerProps extends Dimensions {
5757
class: string;
5858
useAllFormats: boolean;
5959
barcodeFormats?: BarcodeFormatsType[];
60+
detectionLogic?: BarcodeScannerContainerProps["detectionLogic"];
6061
}
6162

6263
export function BarcodeScanner({
@@ -65,6 +66,7 @@ export function BarcodeScanner({
6566
class: className,
6667
barcodeFormats,
6768
useAllFormats,
69+
detectionLogic,
6870
...dimensions
6971
}: BarcodeScannerProps): ReactElement | null {
7072
const [errorMessage, setError] = useCustomErrorMessage();
@@ -75,7 +77,8 @@ export function BarcodeScanner({
7577
useCrop: showMask,
7678
barcodeFormats,
7779
useAllFormats,
78-
canvasMiddleRef
80+
canvasMiddleRef,
81+
detectionLogic
7982
});
8083

8184
const { ref: videoRef, useBrowserAPI } = reader ?? {};

packages/pluggableWidgets/barcode-scanner-web/src/helpers/barcode-detector-utils.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@ const mapToNativeFormat = (format: string): string => {
2121

2222
// Check if BarcodeDetector API is available
2323
export const isBarcodeDetectorSupported = (): boolean => {
24-
return (
25-
typeof globalThis !== "undefined" &&
26-
"BarcodeDetector" in globalThis &&
27-
"detect" in (globalThis as any).BarcodeDetector &&
28-
typeof (globalThis as any).BarcodeDetector.detect === "function"
29-
);
24+
return typeof globalThis !== "undefined" && "BarcodeDetector" in globalThis;
3025
};
3126

3227
// Get supported formats for BarcodeDetector
@@ -76,13 +71,16 @@ export const createBarcodeDetector = (options?: BarcodeDetectorOptions): Barcode
7671

7772
// Detect barcodes from video or canvas element using BarcodeDetector API
7873
export const detectBarcodesFromElement = async (
79-
detector: BarcodeDetector,
80-
element: HTMLVideoElement | HTMLCanvasElement
74+
detector: BarcodeDetector | null,
75+
element: HTMLVideoElement | HTMLCanvasElement | null
8176
): Promise<DetectedBarcode[]> => {
8277
try {
78+
if (!detector || !element || (element as HTMLVideoElement).readyState < HTMLMediaElement.HAVE_CURRENT_DATA) {
79+
return [];
80+
}
8381
return await detector.detect(element);
8482
} catch (error) {
85-
console.warn("BarcodeDetector failed to detect:", error);
83+
console.warn("BarcodeDetector failed to detect:", (element as HTMLVideoElement).readyState, error);
8684
return [];
8785
}
8886
};

packages/pluggableWidgets/barcode-scanner-web/src/helpers/utils.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export type ReaderProps = {
2626
barcodeFormats?: BarcodeFormatsType[];
2727
useAllFormats: boolean;
2828
canvasMiddleRef: RefObject<HTMLDivElement>;
29+
detectionLogic?: "zxing" | "native";
2930
};
3031

3132
export type UseReaderHook = (args: ReaderProps) => { ref: RefObject<HTMLVideoElement>; useBrowserAPI: boolean };

packages/pluggableWidgets/barcode-scanner-web/src/hooks/nativeReader.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { RefObject } from "react";
22
import { BarcodeDetector, MxBarcodeReader } from "../helpers/barcode-detector";
3-
import { createBarcodeDetector, createBarcodeDetectorOptions } from "../helpers/barcode-detector-utils";
3+
import {
4+
createBarcodeDetector,
5+
createBarcodeDetectorOptions,
6+
detectBarcodesFromElement
7+
} from "../helpers/barcode-detector-utils";
48
import { mediaStreamConstraints, ReaderProps } from "../helpers/utils";
59

610
export class Reader implements MxBarcodeReader {
@@ -57,20 +61,18 @@ export class Reader implements MxBarcodeReader {
5761
reject: (reason?: Error) => void
5862
): Promise<void> => {
5963
try {
60-
if (this.videoRef.current === null) {
61-
return;
62-
}
6364
if (this.decodeInterval) {
6465
clearTimeout(this.decodeInterval);
6566
}
66-
const detectionCode = await this.barcodeDetector?.detect(this.videoRef.current);
67+
const detectionCode = await detectBarcodesFromElement(this.barcodeDetector, this.videoRef.current);
6768

6869
if (detectionCode && detectionCode.length > 0) {
6970
if (resolve) resolve(detectionCode[0].rawValue);
7071
} else {
7172
this.decodeInterval = setTimeout(this.decodeStream, 50, resolve, reject);
7273
}
7374
} catch (error) {
75+
console.log("decodeStream error", error);
7476
reject(error);
7577
}
7678
};

packages/pluggableWidgets/barcode-scanner-web/src/hooks/useReader.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ export const useReader: UseReaderHook = args => {
1010
const videoRef = useRef<HTMLVideoElement>(null);
1111
const onSuccess = useEventCallback(args.onSuccess);
1212
const onError = useEventCallback(args.onError);
13-
const enableBrowserAPI = useMemo(() => isBarcodeDetectorSupported(), []);
13+
const enableBrowserAPI = useMemo(
14+
() => isBarcodeDetectorSupported() && args.detectionLogic === "native",
15+
[args.detectionLogic]
16+
);
1417

1518
const reader: MxBarcodeReader = useMemo(() => {
1619
return enableBrowserAPI ? new NativeReader(args, videoRef) : new ZxReader(args, videoRef);

packages/pluggableWidgets/barcode-scanner-web/typings/BarcodeScannerProps.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export type WidthUnitEnum = "percentage" | "pixels";
1616

1717
export type HeightUnitEnum = "percentageOfWidth" | "pixels" | "percentageOfParent";
1818

19+
export type DetectionLogicEnum = "zxing" | "native";
20+
1921
export interface BarcodeFormatsPreviewType {
2022
barcodeFormat: BarcodeFormatEnum;
2123
}
@@ -34,6 +36,7 @@ export interface BarcodeScannerContainerProps {
3436
width: number;
3537
heightUnit: HeightUnitEnum;
3638
height: number;
39+
detectionLogic: DetectionLogicEnum;
3740
}
3841

3942
export interface BarcodeScannerPreviewProps {
@@ -56,4 +59,5 @@ export interface BarcodeScannerPreviewProps {
5659
width: number | null;
5760
heightUnit: HeightUnitEnum;
5861
height: number | null;
62+
detectionLogic: DetectionLogicEnum;
5963
}

0 commit comments

Comments
 (0)