Harden scanner startup and defer polyfill loading

- Fix waitForVideoReady race by re-checking after listeners and timing out
- Serialize iOS native scans with an in-flight guard and chained timeouts
- Lazy-load @undecaf/barcode-detector-polyfill only when scanning starts

Co-authored-by: Ned Halksworth <hello@nedhalksworth.com>
This commit is contained in:
Cursor Agent
2026-05-27 22:01:48 +00:00
parent 64584315e5
commit aa1bf1b21f
3 changed files with 76 additions and 24 deletions
+17 -5
View File
@@ -1,7 +1,12 @@
import { BarcodeDetectorPolyfill } from "@undecaf/barcode-detector-polyfill";
type BarcodeDetectorConstructor = {
new (options?: { formats?: string[] }): {
detect: (source: ImageBitmapSource) => Promise<Array<{ rawValue?: string; format?: string }>>;
};
getSupportedFormats?: () => Promise<string[]>;
};
type WindowWithBarcodeDetector = Window & {
BarcodeDetector?: typeof BarcodeDetectorPolyfill;
BarcodeDetector?: BarcodeDetectorConstructor;
};
let detectorReady: Promise<void> | null = null;
@@ -12,6 +17,11 @@ export function isAppleMobileDevice() {
return /iPad|iPhone|iPod/i.test(ua) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
}
async function loadBarcodeDetectorPolyfill() {
const { BarcodeDetectorPolyfill } = await import("@undecaf/barcode-detector-polyfill");
return BarcodeDetectorPolyfill;
}
export function ensureBarcodeDetector() {
if (detectorReady) return detectorReady;
@@ -20,14 +30,16 @@ export function ensureBarcodeDetector() {
const shouldForcePolyfill = isAppleMobileDevice();
if (shouldForcePolyfill) {
globalWindow.BarcodeDetector = BarcodeDetectorPolyfill;
globalWindow.BarcodeDetector = await loadBarcodeDetectorPolyfill();
return;
}
try {
await globalWindow.BarcodeDetector?.getSupportedFormats();
const getSupportedFormats = globalWindow.BarcodeDetector?.getSupportedFormats;
if (!getSupportedFormats) return;
await getSupportedFormats.call(globalWindow.BarcodeDetector);
} catch {
globalWindow.BarcodeDetector = BarcodeDetectorPolyfill;
globalWindow.BarcodeDetector = await loadBarcodeDetectorPolyfill();
}
})();