add torch, use zxing library

This commit is contained in:
Darius
2025-11-22 01:30:01 +01:00
parent dafee157ed
commit c176ed7a8d

View File

@@ -617,7 +617,23 @@ body {
Point the camera at the barcode or QR code Point the camera at the barcode or QR code
</p> </p>
<button id="stop-scanner-btn" class="btn btn-cancel"> <div style="display: flex; gap: 0.5rem;">
<button id="toggle-torch-btn" class="btn btn-green" style="flex: 1;">
<svg
class="icon-sm"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
</svg>
Torch
</button>
<button id="stop-scanner-btn" class="btn btn-cancel" style="flex: 1;">
<svg <svg
class="icon-sm" class="icon-sm"
fill="none" fill="none"
@@ -633,6 +649,7 @@ body {
Cancel Cancel
</button> </button>
</div> </div>
</div>
<div <div
id="loading-view" id="loading-view"
@@ -659,15 +676,12 @@ body {
<script> <script>
import type { ProductAnalysis } from "../types"; import type { ProductAnalysis } from "../types";
import { analyzeProduct } from "../utils/productAnalysis"; import { analyzeProduct } from "../utils/productAnalysis";
import { BrowserMultiFormatReader } from "@zxing/library";
declare global { let codeReader: BrowserMultiFormatReader | null = null;
interface Window {
ZXing: any;
}
}
let codeReader: any = null;
let scanning = false; let scanning = false;
let torchEnabled = false;
let videoTrack: MediaStreamTrack | null = null;
// Get DOM elements // Get DOM elements
const initialView = document.getElementById("initial-view")!; const initialView = document.getElementById("initial-view")!;
@@ -891,24 +905,19 @@ body {
async function startScanner() { async function startScanner() {
try { try {
if (!window.ZXing) {
showError("Barcode scanner not yet loaded. Please wait...");
return;
}
scanning = true; scanning = true;
barcodeDisplay.style.display = "none"; barcodeDisplay.style.display = "none";
barcodeDisplay.textContent = ""; barcodeDisplay.textContent = "";
showView(scannerView); showView(scannerView);
codeReader = new window.ZXing.BrowserMultiFormatReader(); codeReader = new BrowserMultiFormatReader();
waitForElement('scanner-video', () => { waitForElement('scanner-video', () => {
codeReader.decodeFromVideoDevice(undefined, 'scanner-video', (result: unknown, err: unknown) => { codeReader!.decodeFromVideoDevice(undefined, 'scanner-video', (result: { getText: Function }, err: unknown) => {
if (result) { if (result) {
const code = result.getText(); const code = result.getText();
barcodeDisplay.textContent = code; barcodeDisplay.textContent = code;
barcodeDisplay.style.display = "block"; barcodeDisplay.style.display = "block";
codeReader.reset(); codeReader!.reset();
searchProduct(code); searchProduct(code);
} }
}) })
@@ -927,9 +936,50 @@ body {
codeReader.reset(); codeReader.reset();
} }
scanning = false; scanning = false;
torchEnabled = false;
videoTrack = null;
showView(initialView); 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 // Event listeners
document document
.getElementById("start-scanner-btn")! .getElementById("start-scanner-btn")!
@@ -937,6 +987,9 @@ body {
document document
.getElementById("stop-scanner-btn")! .getElementById("stop-scanner-btn")!
.addEventListener("click", stopScanner); .addEventListener("click", stopScanner);
document
.getElementById("toggle-torch-btn")!
.addEventListener("click", toggleTorch);
document.getElementById("error-back-btn")!.addEventListener("click", () => { document.getElementById("error-back-btn")!.addEventListener("click", () => {
showView(initialView); showView(initialView);
}); });