From 28bdd6aa5b98d24f0c993732fe8cbf42d3423ab5 Mon Sep 17 00:00:00 2001 From: varutasu <104105839+varutasu@users.noreply.github.com> Date: Sat, 15 Aug 2026 18:48:05 -0500 Subject: [PATCH] Fix scanner multi-card flow, frame overlay, and rate limits. (#166) Allow consecutive scans without refresh by resetting trackers and counting vision rate limits once per card. Add a fixed card guide, widen detection bounds, and correct object-cover overlay math. Co-authored-by: Cursor --- components/scanner/ScannerCamera.js | 329 ++++++++++++++---------- lib/rate-limit.js | 3 +- lib/scanner-card-detection.js | 35 ++- lib/scanner-video-layout.js | 98 +++++++ lib/use-camera-scanner.js | 13 + lib/use-scanner-identification.js | 36 ++- pages/api/scan/identify-by-image.js | 7 - pages/scanner.js | 1 + test/lib/scanner-card-detection.test.js | 59 ++++- test/lib/scanner-video-layout.test.js | 49 ++++ 10 files changed, 470 insertions(+), 160 deletions(-) create mode 100644 lib/scanner-video-layout.js create mode 100644 test/lib/scanner-video-layout.test.js diff --git a/components/scanner/ScannerCamera.js b/components/scanner/ScannerCamera.js index c4b2c78..ced464c 100644 --- a/components/scanner/ScannerCamera.js +++ b/components/scanner/ScannerCamera.js @@ -6,27 +6,63 @@ import ScannerScanPeek from './ScannerScanPeek.js'; import ScannerDisambiguation from './ScannerDisambiguation.js'; import { useScannerSound } from '../../lib/use-scanner-sound.js'; import { useScannerFlash } from '../../lib/use-scanner-flash.js'; +import { + cardGuideToContainerStyle, + computeObjectCoverLayout, + videoBoundsToContainerStyle, +} from '../../lib/scanner-video-layout.js'; const TOAST_DURATION_MS = 2500; -function DetectionFrame({ card, videoMetrics }) { +function CardGuideFrame({ layout }) { + if (!layout) return null; + + const style = cardGuideToContainerStyle(layout); + + return ( + + ); +} + +function DetectionFrame({ card, layout }) { const label = card.status === 'scanned' ? `Card ${card.id} scanned` : `Card ${card.id} identified`; + if (!layout) return null; + + const style = videoBoundsToContainerStyle(card.bounds, layout); + return (