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
This commit is contained in:
parent
4ba1fe19cc
commit
13114bd63f
1 changed files with 46 additions and 8 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -37,6 +38,8 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
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<ScannerScreen> {
|
|||
void initState() {
|
||||
super.initState();
|
||||
_activeCollectionId = widget.activeCollectionId;
|
||||
_autoScanEnabled = widget.onDetected != null;
|
||||
_textRecognizer = TextRecognizer();
|
||||
_initCamera();
|
||||
}
|
||||
|
|
@ -81,6 +85,22 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
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<ScannerScreen> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
_autoScanTimer?.cancel();
|
||||
_cameraController?.dispose();
|
||||
_textRecognizer.close();
|
||||
super.dispose();
|
||||
|
|
@ -243,6 +264,9 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
color: _scanAccepted
|
||||
? AppColors.success.withValues(alpha: 0.12)
|
||||
: Colors.black.withValues(alpha: 0.55),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
_statusText,
|
||||
textAlign: TextAlign.center,
|
||||
|
|
@ -253,6 +277,20 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
|||
),
|
||||
),
|
||||
),
|
||||
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 ──
|
||||
Expanded(
|
||||
child: _cameraReady
|
||||
|
|
|
|||
Loading…
Reference in a new issue