Skip to content

feat(qr): QR scanner (stage C item 2) - #75

Merged
TTigger merged 1 commit into
masterfrom
feat/qr-scanner
Jul 13, 2026
Merged

feat(qr): QR scanner (stage C item 2)#75
TTigger merged 1 commit into
masterfrom
feat/qr-scanner

Conversation

@TTigger

@TTigger TTigger commented Jul 13, 2026

Copy link
Copy Markdown
Owner

摘要

階段 C 第 2 項:QR 掃描 —— 補齊 QR 產生器的另一半。相機或圖片掃描,解碼完全在瀏覽器本機,零上傳。

設計取捨

  • jsQR 取代 handoff 提的 barcode-detector:原生 BarcodeDetector API 在 Safari / Firefox 不支援,wasm ponyfill(zxing-wasm)逾 1MB;jsQR 純 JS、QR-only 正好符合工具範圍,headless e2e 行為也確定。
  • src/lib/qrScan.tsqrFormats.ts 產生器的反向操作(WIFI:/vCard 跳脫反解、RFC 摺行展開),單元測試直接拿產生器做往返驗證。
  • 安全:只有 http/https 給可點連結(rel=noopener noreferrer,e2e 釘住);javascript: 等一律當純文字。

功能

  • 圖片分頁:點選/拖放/Ctrl+V 貼上;大圖縮到 1024 邊長再解(更快更準)
  • 相機分頁:getUserMedia 後鏡頭優先、~150ms 節流掃描、對到自動停、權限被拒有明確訊息
  • 結果卡:網址/WiFi(SSID+密碼一鍵複製)/名片欄位結構化顯示+原始內容

驗證

  • typecheck:api ✓ / 537 unit ✓(+7)/ 60 e2e ✓(+3)
  • OG 卡 70 張重生成,兩張新卡已目測;工具頁 WiFi 掃描結果已截圖目測
  • 相機路徑無法在 headless 覆蓋,已手動檢視程式碼的資源清理(unmount 停 track)

🤖 Generated with Claude Code

補齊 QR 產生器的另一半:相機或圖片掃描,純前端零上傳。

- 解碼引擎選 jsQR(新依賴)而非 handoff 提的 barcode-detector:
  原生 BarcodeDetector 在 Safari/Firefox 缺席,wasm ponyfill 逾 1MB;
  jsQR 純 JS、QR-only 正好符合範圍,且 headless e2e 行為確定。
- src/lib/qrScan.ts:內容分類與解析(TDD 7 tests),是 qrFormats.ts
  產生器的反向——WIFI:/vCard 跳脫反解、RFC 摺行展開、往返測試釘住;
  javascript:/ftp: 等連結一律當純文字,不給可點的 <a>。
- src/tools/QrScanner.tsx:圖片分頁(點選/拖放/Ctrl+V 貼上,
  大圖縮到 1024 邊長再解)+相機分頁(getUserMedia,~150ms 節流
  掃描,對到自動停);網址/WiFi/名片結構化顯示與複製。
- 中英頁面、tools.ts 註冊(實用工具 📷)、OG 卡 70 張(守門測試同步)。
- e2e:qrcode 套件現做 QR 圖上傳,涵蓋網址(rel=noopener 斷言)、
  WiFi 解析、無 QR 圖片的明確錯誤(+3)。

測試:typecheck:api ✓ / 537 unit ✓(+7)/ 60 e2e ✓(+3)
純前端,不碰 api/。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
tiglet Ready Ready Preview, Comment Jul 13, 2026 1:58pm

@TTigger
TTigger merged commit 5e46f86 into master Jul 13, 2026
3 checks passed
@TTigger
TTigger deleted the feat/qr-scanner branch July 13, 2026 14:00
TTigger added a commit that referenced this pull request Jul 13, 2026
The other half of the QR generator: scan from camera or image, fully
client-side with zero upload.

- Decoder is jsQR (new dependency) instead of the handoff's
  barcode-detector suggestion: the native BarcodeDetector API is absent
  in Safari/Firefox and the wasm ponyfill exceeds 1MB; jsQR is pure JS,
  QR-only (exactly the scope), and deterministic in headless e2e.
- src/lib/qrScan.ts: content classification and parsing (TDD 7 tests),
  the inverse of the qrFormats.ts generators — WIFI:/vCard unescaping,
  RFC line unfolding, round-trip tests against the generators;
  javascript:/ftp: style links are treated as plain text, never
  rendered as clickable anchors.
- src/tools/QrScanner.tsx: image tab (click / drag / Ctrl+V paste,
  large images downscaled to 1024px before decoding) and camera tab
  (getUserMedia, ~150ms throttled scan loop, auto-stop on hit);
  URL / WiFi / vCard results shown as structured fields with copy.
- zh/en pages, tools.ts entry (📷), OG cards regenerated (70 total).
- e2e: QR PNGs generated on the fly with the qrcode package — URL
  (rel=noopener asserted), WiFi parsing, clear error on a QR-less
  image (+3).

Tests: typecheck:api / 537 unit (+7) / 60 e2e (+3).
Frontend only; api/ untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@TTigger TTigger changed the title feat(qr): QR 掃描 (stage C item 2) feat(qr): QR scanner (stage C item 2) Jul 13, 2026
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