From b1bcf9e714dec17af21cc7dd75cbb1f768a7e826 Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Fri, 29 May 2026 17:43:55 +0000 Subject: [PATCH] fix: AI visual barcode fallback fires only once per scanner session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Gemini cannot identify the product visually, mark _aiFallbackExhausted=true for the current scanner session so the 5s timer never fires again. The scanner restarts normally (user can keep trying with the barcode reader) and a persistent status message is shown: 'AI: product not recognized — try scanning the barcode'. _aiFallbackExhausted resets to false in stopScanner() so the next camera session starts fresh. --- assets/js/app.js | 18 +++++++++++------- translations/de.json | 3 ++- translations/en.json | 3 ++- translations/es.json | 3 ++- translations/fr.json | 3 ++- translations/it.json | 3 ++- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 9c28947..8f8c3c2 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1944,6 +1944,7 @@ let aiStream = null; let _scanZoomLevel = 2; // always 2x let _torchActive = false; let _aiFallbackTimer = null; +let _aiFallbackExhausted = false; // true after one failed AI visual attempt — reset when scanner is closed // Apply fixed 2x zoom (hardware if available, CSS fallback) async function _applyFixedZoom() { @@ -2174,17 +2175,19 @@ async function _tryGeminiVisualBarcode() { showToast(t('error.connection'), 'error'); } } else { - scanLog('AI visual: product not identified'); + scanLog('AI visual: product not identified — exhausted for this session'); + _aiFallbackExhausted = true; showLoading(false); - showToast(t('scan.ai_fallback_not_found'), 'warning'); - _setScanStatus(t('scan.status_ready'), '', ''); - // Restart scanner so user can try again + _setScanStatus(t('scan.ai_fallback_exhausted'), 'retry', ''); + // Restart the scanner so the user can keep trying with the barcode reader, + // but the 5s AI timer will NOT fire again (_aiFallbackExhausted=true). setTimeout(() => initScanner(), 300); } } catch (e) { scanLog(`AI visual error: ${e.message}`); + _aiFallbackExhausted = true; showLoading(false); - showToast(t('error.connection'), 'error'); + _setScanStatus(t('scan.ai_fallback_exhausted'), 'retry', ''); setTimeout(() => initScanner(), 300); } finally { _aiBarcodeVisualRunning = false; @@ -6615,10 +6618,10 @@ async function initScanner() { } // After 5s without a scan, auto-trigger AI visual identification (if enabled) - if (_geminiAvailable && getSettings().barcode_ai_fallback) { + if (_geminiAvailable && getSettings().barcode_ai_fallback && !_aiFallbackExhausted) { clearTimeout(_aiFallbackTimer); _aiFallbackTimer = setTimeout(() => { - if (scannerStream) { // still scanning — no barcode found yet + if (scannerStream && !_aiFallbackExhausted) { // still scanning — no barcode found yet scanLog('5s elapsed without barcode — triggering AI visual fallback'); _tryGeminiVisualBarcode(); } @@ -6948,6 +6951,7 @@ function stopScanner() { _scanZoomLevel = 2; // always 2x on next start _torchActive = false; clearTimeout(_aiFallbackTimer); _aiFallbackTimer = null; + _aiFallbackExhausted = false; // reset so a new scanner session can try again if (scannerStream) { scannerStream.getTracks().forEach(t => t.stop()); scannerStream = null; diff --git a/translations/de.json b/translations/de.json index 13492c0..cbc4a43 100644 --- a/translations/de.json +++ b/translations/de.json @@ -223,7 +223,8 @@ "status_parallel": "Kombinierter Scan aktiv...", "ai_fallback_searching": "KI identifiziert Produkt...", "ai_fallback_found": "Produkt von KI erkannt", - "ai_fallback_not_found": "KI: Produkt nicht erkannt" + "ai_fallback_not_found": "KI: Produkt nicht erkannt", + "ai_fallback_exhausted": "KI: Produkt nicht erkannt — Barcode erneut scannen" }, "action": { "title": "Was möchtest du tun?", diff --git a/translations/en.json b/translations/en.json index 1536460..e35b37c 100644 --- a/translations/en.json +++ b/translations/en.json @@ -223,7 +223,8 @@ "status_parallel": "Using combined scan methods...", "ai_fallback_searching": "AI identifying product...", "ai_fallback_found": "Product identified by AI", - "ai_fallback_not_found": "AI: product not recognized" + "ai_fallback_not_found": "AI: product not recognized", + "ai_fallback_exhausted": "AI: product not recognized — try scanning the barcode" }, "action": { "title": "What do you want to do?", diff --git a/translations/es.json b/translations/es.json index f7714bb..be44d15 100644 --- a/translations/es.json +++ b/translations/es.json @@ -220,7 +220,8 @@ "status_parallel": "Escaneo combinado activo...", "ai_fallback_searching": "Identificación de IA en curso...", "ai_fallback_found": "Producto identificado por IA", - "ai_fallback_not_found": "IA: producto no reconocido" + "ai_fallback_not_found": "IA: producto no reconocido", + "ai_fallback_exhausted": "IA: producto no reconocido — prueba a escanear el código" }, "action": { "title": "¿Qué quieres hacer?", diff --git a/translations/fr.json b/translations/fr.json index 1070b5b..d7c5de9 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -220,7 +220,8 @@ "status_parallel": "Scan combiné actif...", "ai_fallback_searching": "Identification IA en cours...", "ai_fallback_found": "Produit identifié par l'IA", - "ai_fallback_not_found": "IA : produit non reconnu" + "ai_fallback_not_found": "IA : produit non reconnu", + "ai_fallback_exhausted": "IA : produit non reconnu — réessayez avec le code-barres" }, "action": { "title": "Que voulez-vous faire ?", diff --git a/translations/it.json b/translations/it.json index b597cd2..83cde5d 100644 --- a/translations/it.json +++ b/translations/it.json @@ -223,7 +223,8 @@ "status_parallel": "Doppia scansione attiva...", "ai_fallback_searching": "Identificazione AI in corso...", "ai_fallback_found": "Prodotto identificato dall'AI", - "ai_fallback_not_found": "AI: prodotto non riconosciuto" + "ai_fallback_not_found": "AI: prodotto non riconosciuto", + "ai_fallback_exhausted": "AI: prodotto non riconosciuto — riprova con il barcode" }, "action": { "title": "Cosa vuoi fare?",