fix: AI visual barcode fallback fires only once per scanner session
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.
This commit is contained in:
+11
-7
@@ -1944,6 +1944,7 @@ let aiStream = null;
|
|||||||
let _scanZoomLevel = 2; // always 2x
|
let _scanZoomLevel = 2; // always 2x
|
||||||
let _torchActive = false;
|
let _torchActive = false;
|
||||||
let _aiFallbackTimer = null;
|
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)
|
// Apply fixed 2x zoom (hardware if available, CSS fallback)
|
||||||
async function _applyFixedZoom() {
|
async function _applyFixedZoom() {
|
||||||
@@ -2174,17 +2175,19 @@ async function _tryGeminiVisualBarcode() {
|
|||||||
showToast(t('error.connection'), 'error');
|
showToast(t('error.connection'), 'error');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scanLog('AI visual: product not identified');
|
scanLog('AI visual: product not identified — exhausted for this session');
|
||||||
|
_aiFallbackExhausted = true;
|
||||||
showLoading(false);
|
showLoading(false);
|
||||||
showToast(t('scan.ai_fallback_not_found'), 'warning');
|
_setScanStatus(t('scan.ai_fallback_exhausted'), 'retry', '');
|
||||||
_setScanStatus(t('scan.status_ready'), '', '');
|
// Restart the scanner so the user can keep trying with the barcode reader,
|
||||||
// Restart scanner so user can try again
|
// but the 5s AI timer will NOT fire again (_aiFallbackExhausted=true).
|
||||||
setTimeout(() => initScanner(), 300);
|
setTimeout(() => initScanner(), 300);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
scanLog(`AI visual error: ${e.message}`);
|
scanLog(`AI visual error: ${e.message}`);
|
||||||
|
_aiFallbackExhausted = true;
|
||||||
showLoading(false);
|
showLoading(false);
|
||||||
showToast(t('error.connection'), 'error');
|
_setScanStatus(t('scan.ai_fallback_exhausted'), 'retry', '');
|
||||||
setTimeout(() => initScanner(), 300);
|
setTimeout(() => initScanner(), 300);
|
||||||
} finally {
|
} finally {
|
||||||
_aiBarcodeVisualRunning = false;
|
_aiBarcodeVisualRunning = false;
|
||||||
@@ -6615,10 +6618,10 @@ async function initScanner() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// After 5s without a scan, auto-trigger AI visual identification (if enabled)
|
// 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);
|
clearTimeout(_aiFallbackTimer);
|
||||||
_aiFallbackTimer = setTimeout(() => {
|
_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');
|
scanLog('5s elapsed without barcode — triggering AI visual fallback');
|
||||||
_tryGeminiVisualBarcode();
|
_tryGeminiVisualBarcode();
|
||||||
}
|
}
|
||||||
@@ -6948,6 +6951,7 @@ function stopScanner() {
|
|||||||
_scanZoomLevel = 2; // always 2x on next start
|
_scanZoomLevel = 2; // always 2x on next start
|
||||||
_torchActive = false;
|
_torchActive = false;
|
||||||
clearTimeout(_aiFallbackTimer); _aiFallbackTimer = null;
|
clearTimeout(_aiFallbackTimer); _aiFallbackTimer = null;
|
||||||
|
_aiFallbackExhausted = false; // reset so a new scanner session can try again
|
||||||
if (scannerStream) {
|
if (scannerStream) {
|
||||||
scannerStream.getTracks().forEach(t => t.stop());
|
scannerStream.getTracks().forEach(t => t.stop());
|
||||||
scannerStream = null;
|
scannerStream = null;
|
||||||
|
|||||||
@@ -223,7 +223,8 @@
|
|||||||
"status_parallel": "Kombinierter Scan aktiv...",
|
"status_parallel": "Kombinierter Scan aktiv...",
|
||||||
"ai_fallback_searching": "KI identifiziert Produkt...",
|
"ai_fallback_searching": "KI identifiziert Produkt...",
|
||||||
"ai_fallback_found": "Produkt von KI erkannt",
|
"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": {
|
"action": {
|
||||||
"title": "Was möchtest du tun?",
|
"title": "Was möchtest du tun?",
|
||||||
|
|||||||
@@ -223,7 +223,8 @@
|
|||||||
"status_parallel": "Using combined scan methods...",
|
"status_parallel": "Using combined scan methods...",
|
||||||
"ai_fallback_searching": "AI identifying product...",
|
"ai_fallback_searching": "AI identifying product...",
|
||||||
"ai_fallback_found": "Product identified by AI",
|
"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": {
|
"action": {
|
||||||
"title": "What do you want to do?",
|
"title": "What do you want to do?",
|
||||||
|
|||||||
@@ -220,7 +220,8 @@
|
|||||||
"status_parallel": "Escaneo combinado activo...",
|
"status_parallel": "Escaneo combinado activo...",
|
||||||
"ai_fallback_searching": "Identificación de IA en curso...",
|
"ai_fallback_searching": "Identificación de IA en curso...",
|
||||||
"ai_fallback_found": "Producto identificado por IA",
|
"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": {
|
"action": {
|
||||||
"title": "¿Qué quieres hacer?",
|
"title": "¿Qué quieres hacer?",
|
||||||
|
|||||||
@@ -220,7 +220,8 @@
|
|||||||
"status_parallel": "Scan combiné actif...",
|
"status_parallel": "Scan combiné actif...",
|
||||||
"ai_fallback_searching": "Identification IA en cours...",
|
"ai_fallback_searching": "Identification IA en cours...",
|
||||||
"ai_fallback_found": "Produit identifié par l'IA",
|
"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": {
|
"action": {
|
||||||
"title": "Que voulez-vous faire ?",
|
"title": "Que voulez-vous faire ?",
|
||||||
|
|||||||
@@ -223,7 +223,8 @@
|
|||||||
"status_parallel": "Doppia scansione attiva...",
|
"status_parallel": "Doppia scansione attiva...",
|
||||||
"ai_fallback_searching": "Identificazione AI in corso...",
|
"ai_fallback_searching": "Identificazione AI in corso...",
|
||||||
"ai_fallback_found": "Prodotto identificato dall'AI",
|
"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": {
|
"action": {
|
||||||
"title": "Cosa vuoi fare?",
|
"title": "Cosa vuoi fare?",
|
||||||
|
|||||||
Reference in New Issue
Block a user