From 13114bd63f9a9cefb5fa3f4471193785c59dbef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20M=C3=BCllner?= Date: Wed, 4 Mar 2026 11:15:43 +0100 Subject: [PATCH] feat(scanner): add auto-scan cadence with pause/resume controls - Add periodic auto-capture loop for uninterrupted scanner workflow - Start auto-scan after camera init and stop cleanly on dispose - Gate scans by busy/camera-ready state to avoid overlapping captures - Add AUTO ON/OFF toggle in scanner status bar - Keep manual capture path available as fallback --- lib/scanner_screen.dart | 54 +++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/lib/scanner_screen.dart b/lib/scanner_screen.dart index fad1298..0774cf9 100644 --- a/lib/scanner_screen.dart +++ b/lib/scanner_screen.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; @@ -37,6 +38,8 @@ class _ScannerScreenState extends State { bool _scanAccepted = false; String _statusText = 'Ready to scan'; String? _activeCollectionId; + bool _autoScanEnabled = false; + Timer? _autoScanTimer; // Matches typical Hot Wheels model IDs: 2–5 uppercase letters followed by // 2–4 digits, e.g. JKF21, HCV73, GRX33, FYD83. @@ -46,6 +49,7 @@ class _ScannerScreenState extends State { void initState() { super.initState(); _activeCollectionId = widget.activeCollectionId; + _autoScanEnabled = widget.onDetected != null; _textRecognizer = TextRecognizer(); _initCamera(); } @@ -81,6 +85,22 @@ class _ScannerScreenState extends State { await _cameraController!.initialize(); if (!mounted) return; setState(() => _cameraReady = true); + _startAutoScanLoop(); + } + + void _startAutoScanLoop() { + _autoScanTimer?.cancel(); + _autoScanTimer = Timer.periodic(const Duration(milliseconds: 1400), (_) { + if (!_autoScanEnabled || _isBusy || !_cameraReady || !mounted) return; + _captureAndScan(); + }); + } + + void _toggleAutoScan() { + setState(() { + _autoScanEnabled = !_autoScanEnabled; + _statusText = _autoScanEnabled ? 'Auto scan enabled' : 'Auto scan paused'; + }); } /// Capture a photo, run OCR, and look for a Hot Wheels ID. @@ -187,6 +207,7 @@ class _ScannerScreenState extends State { @override void dispose() { + _autoScanTimer?.cancel(); _cameraController?.dispose(); _textRecognizer.close(); super.dispose(); @@ -243,14 +264,31 @@ class _ScannerScreenState extends State { color: _scanAccepted ? AppColors.success.withValues(alpha: 0.12) : Colors.black.withValues(alpha: 0.55), - child: Text( - _statusText, - textAlign: TextAlign.center, - style: TextStyle( - color: _scanAccepted ? AppColors.success : Colors.white, - fontSize: 12, - fontWeight: FontWeight.w600, - ), + child: Row( + children: [ + Expanded( + child: Text( + _statusText, + textAlign: TextAlign.center, + style: TextStyle( + color: _scanAccepted ? AppColors.success : Colors.white, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + ), + if (widget.onDetected != null) + TextButton( + onPressed: _isBusy ? null : _toggleAutoScan, + style: TextButton.styleFrom( + foregroundColor: + _autoScanEnabled ? AppColors.success : Colors.white, + minimumSize: const Size(0, 26), + padding: const EdgeInsets.symmetric(horizontal: 10), + ), + child: Text(_autoScanEnabled ? 'AUTO ON' : 'AUTO OFF'), + ), + ], ), ), // ── Camera preview ──