perf: reduce scanner OCR workload

This commit is contained in:
Lukas Müllner 2026-03-05 08:37:13 +01:00
parent abf1b9d788
commit 07b1df3369

View file

@ -31,6 +31,11 @@ class ScannerScreen extends StatefulWidget {
}
class _ScannerScreenState extends State<ScannerScreen> {
static const _autoScanTickInterval = Duration(milliseconds: 700);
static const _scanCooldownSuccess = Duration(milliseconds: 1500);
static const _scanCooldownNoMatch = Duration(milliseconds: 2200);
static const _scanCooldownError = Duration(milliseconds: 2600);
CameraController? _cameraController;
late final TextRecognizer _textRecognizer;
bool _isBusy = false;
@ -42,6 +47,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
String? _activeCollectionId;
bool _autoScanEnabled = false;
Timer? _autoScanTimer;
DateTime _nextScanAllowedAt = DateTime.fromMillisecondsSinceEpoch(0);
@override
void initState() {
@ -76,7 +82,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
_cameraController = CameraController(
backCamera,
ResolutionPreset.high,
ResolutionPreset.medium,
enableAudio: false,
);
@ -88,8 +94,9 @@ class _ScannerScreenState extends State<ScannerScreen> {
void _startAutoScanLoop() {
_autoScanTimer?.cancel();
_autoScanTimer = Timer.periodic(const Duration(milliseconds: 1400), (_) {
_autoScanTimer = Timer.periodic(_autoScanTickInterval, (_) {
if (!_autoScanEnabled || _isBusy || !_cameraReady || !mounted) return;
if (DateTime.now().isBefore(_nextScanAllowedAt)) return;
_captureAndScan();
});
}
@ -105,6 +112,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
/// Capture a photo, run OCR, and look for a Hot Wheels ID.
Future<void> _captureAndScan() async {
if (_isBusy || _cameraController == null || !_cameraController!.value.isInitialized) return;
if (_cameraController!.value.isTakingPicture) return;
setState(() {
_isBusy = true;
@ -131,11 +139,13 @@ class _ScannerScreenState extends State<ScannerScreen> {
if (!mounted) return;
if (found != null) {
_nextScanAllowedAt = DateTime.now().add(_scanCooldownSuccess);
setState(() => _lastDetected = found);
if (widget.onDetected != null) {
await _submitDetected(found);
}
} else {
_nextScanAllowedAt = DateTime.now().add(_scanCooldownNoMatch);
setState(() {
_scanAccepted = false;
_scanNotFound = true;
@ -143,6 +153,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
});
}
} catch (e) {
_nextScanAllowedAt = DateTime.now().add(_scanCooldownError);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Scan error: $e'), backgroundColor: Colors.red),