Skip to content

refactor(qr): shared useQrScanner hook dedupes Verify + ScanUpdate - #27

Merged
abhinav-phi merged 1 commit into
mainfrom
abhinav-pr/24-qr-scanner-hook
Aug 29, 2026
Merged

refactor(qr): shared useQrScanner hook dedupes Verify + ScanUpdate#27
abhinav-phi merged 1 commit into
mainfrom
abhinav-pr/24-qr-scanner-hook

Conversation

@abhinav-phi

Copy link
Copy Markdown
Owner

Problem

The QR scanner logic was duplicated across two pages (audit Code Quality + the report's #10 priority): Verify.tsx and ScanUpdate.tsx each grew their own ~80-line html5-qrcode setup/stop/cleanup copy, with different configs (fps 30 vs 12, responsive vs fixed qrbox, BarcodeDetector on vs off), duplicated single-fire guards, and independently hand-rolled stop/clear error handling. Any camera fix had to be applied twice — and drift was already visible.

Fix

New shared hook — src/hooks/use-qr-scanner.ts (useQrScanner):

  • Full html5-qrcode lifecycle: instance management, optimistic start (UI flips to "scanning" immediately, matching the old behavior), awaited stop+clear, container reset between sessions, and unmount cleanup (R8 — camera streams always released, including after a start failure).
  • Single-fire guard per session: the first usable decode stops the camera before the caller takes over.
  • Caller-controlled validity: onDecode may return false to keep scanning (Verify uses this when a decoded payload doesn't extract to a product code — preserving its exact old semantics).
  • Configurable fps, fixed-or-functional qrbox (Verify passes a responsive one computed from container width), and useBarCodeDetectorIfSupported.
  • Callbacks are held in refs so start/stop stay referentially stable and the cleanup can never capture a stale closure.

src/pages/Verify.tsx:

  • Replaced ~140 lines of camera plumbing with the hook (fps 30, responsive qrbox, BarcodeDetector on — same config as before).
  • Its friendly camera-error mapping (permission / no camera / HTTPS / busy) moves into onError, unchanged.
  • The 20s "having trouble?" nudge (AppFlow §4.2) now keys off the hook's activeRef; geo-after-camera behavior untouched.

src/pages/ScanUpdate.tsx:

  • Replaced its private scanner (~55 lines) with the hook; URL→product-code extraction and toasts stay in onDecode. Net: the page shrank by ~50 lines.

Files Changed

  • src/hooks/use-qr-scanner.ts — new shared scanner hook.
  • src/pages/Verify.tsx, src/pages/ScanUpdate.tsx — consumers; duplicate lifecycle code deleted.

Verification

  • npx tsc --noEmit -p tsconfig.app.jsonexit 0 (strict mode).
  • npm run build✓ built; npm test35/35 passing.

Manual Test (post-deploy)

  1. Verify page: Start Camera → scan a product QR → camera stops and verification runs (single decode, no double-fire).
  2. Point at a non-product QR (plain URL) → camera keeps scanning, only product codes trigger.
  3. Scan & Update: same flow; Cancel releases the camera; navigating away mid-scan also releases it.

Both pages carried their own ~80-line html5-qrcode setup/stop/cleanup copy with
drifting configs. Extract useQrScanner: instance lifecycle, optimistic start,
awaited stop+clear, per-session single-fire guard, caller-rejectable decodes
(return false = keep scanning), responsive qrbox support and unmount cleanup
(R8). Verify keeps its fps=30/BarcodeDetector/responsive-qrbox config and
friendly error mapping; ScanUpdate shrinks by ~50 lines.
@abhinav-phi
abhinav-phi merged commit 2e4674e into main Aug 29, 2026
3 checks passed
@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
authchain Ready Ready Preview Aug 29, 2026 2:06pm

@abhinav-phi
abhinav-phi deleted the abhinav-pr/24-qr-scanner-hook branch August 29, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant