From c176ed7a8d237442f304f27a40a4a4bc41c5f22e Mon Sep 17 00:00:00 2001 From: Darius Date: Sat, 22 Nov 2025 01:30:01 +0100 Subject: [PATCH] add torch, use zxing library --- src/components/Scanner.astro | 113 +++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 30 deletions(-) diff --git a/src/components/Scanner.astro b/src/components/Scanner.astro index 92f0fb2..706f703 100644 --- a/src/components/Scanner.astro +++ b/src/components/Scanner.astro @@ -617,21 +617,38 @@ body { Point the camera at the barcode or QR code

- +
+ + +
import type { ProductAnalysis } from "../types"; import { analyzeProduct } from "../utils/productAnalysis"; + import { BrowserMultiFormatReader } from "@zxing/library"; - declare global { - interface Window { - ZXing: any; - } - } - - let codeReader: any = null; + let codeReader: BrowserMultiFormatReader | null = null; let scanning = false; + let torchEnabled = false; + let videoTrack: MediaStreamTrack | null = null; // Get DOM elements const initialView = document.getElementById("initial-view")!; @@ -891,24 +905,19 @@ body { async function startScanner() { try { - if (!window.ZXing) { - showError("Barcode scanner not yet loaded. Please wait..."); - return; - } - scanning = true; barcodeDisplay.style.display = "none"; barcodeDisplay.textContent = ""; showView(scannerView); - codeReader = new window.ZXing.BrowserMultiFormatReader(); + codeReader = new BrowserMultiFormatReader(); waitForElement('scanner-video', () => { - codeReader.decodeFromVideoDevice(undefined, 'scanner-video', (result: unknown, err: unknown) => { + codeReader!.decodeFromVideoDevice(undefined, 'scanner-video', (result: { getText: Function }, err: unknown) => { if (result) { const code = result.getText(); barcodeDisplay.textContent = code; barcodeDisplay.style.display = "block"; - codeReader.reset(); + codeReader!.reset(); searchProduct(code); } }) @@ -927,9 +936,50 @@ body { codeReader.reset(); } scanning = false; + torchEnabled = false; + videoTrack = null; showView(initialView); } + async function toggleTorch() { + try { + if (!videoTrack) { + const videoElement = document.getElementById('scanner-video') as HTMLVideoElement; + if (videoElement && videoElement.srcObject) { + const stream = videoElement.srcObject as MediaStream; + const tracks = stream.getVideoTracks(); + if (tracks.length > 0) { + videoTrack = tracks[0]; + } + } + } + + if (!videoTrack) { + console.error('No video track available'); + return; + } + + const capabilities = videoTrack.getCapabilities() as any; + if (!capabilities.torch) { + showError('Torch is not supported on this device'); + return; + } + + torchEnabled = !torchEnabled; + await videoTrack.applyConstraints({ + advanced: [{ torch: torchEnabled } as any] + }); + + const torchBtn = document.getElementById('toggle-torch-btn'); + if (torchBtn) { + torchBtn.textContent = torchEnabled ? 'Torch On' : 'Torch Off'; + } + } catch (err) { + console.error('Error toggling torch:', err); + showError('Could not toggle torch. Feature may not be supported.'); + } + } + // Event listeners document .getElementById("start-scanner-btn")! @@ -937,6 +987,9 @@ body { document .getElementById("stop-scanner-btn")! .addEventListener("click", stopScanner); + document + .getElementById("toggle-torch-btn")! + .addEventListener("click", toggleTorch); document.getElementById("error-back-btn")!.addEventListener("click", () => { showView(initialView); });