multi-qr-scanner-poc 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -58
- package/dist/App.d.ts +2 -0
- package/dist/components/MultiQRScanner.d.ts +26 -1
- package/dist/main.d.ts +0 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -1,67 +1,116 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- **Lỗi (Error - Đỏ)**: Check-in thất bại. Hệ thống sẽ cho phép thử lại (retry) sau một khoảng thời gian (ví dụ: 5 giây).
|
|
24
|
-
3. **Giao Diện Trực Quan (Visual Feedback)**:
|
|
25
|
-
- Vẽ khung bao (bounding box) quanh mã QR theo màu sắc trạng thái tương ứng.
|
|
26
|
-
|
|
27
|
-
## 4. Cơ Chế Hoạt Động (How it works)
|
|
28
|
-
1. **Khởi tạo Camera**: Ứng dụng xin quyền truy cập webcam và hiển thị luồng video (ưu tiên camera sau/môi trường trên mobile).
|
|
29
|
-
2. **Vòng lặp Phát hiện (Detection Loop)**:
|
|
30
|
-
- Sử dụng `BarcodeDetector.detect()` liên tục trên luồng video.
|
|
31
|
-
- Kết quả trả về là danh sách các mã QR có trong khung hình.
|
|
32
|
-
3. **Xử lý Logic (Scanning Logic)**:
|
|
33
|
-
- Với mỗi mã tìm thấy, kiểm tra trong bộ nhớ đệm (`scanStates` map):
|
|
34
|
-
- Nếu mã **chưa có** hoặc **đã từng lỗi (cách đây 5s)** -> Đánh dấu là `Processing` và gọi hàm `checkInUser` (Mock API).
|
|
35
|
-
- Nếu mã đang `Processing` hoặc đã `Success` -> Bỏ qua, không làm gì cả.
|
|
36
|
-
4. **Mock API**:
|
|
37
|
-
- Hàm `checkInUser` giả lập độ trễ mạng 2 giây.
|
|
38
|
-
- Nếu nội dung mã QR chứa từ "fail" -> trả về Lỗi, ngược lại -> Thành công.
|
|
39
|
-
|
|
40
|
-
## 5. Hướng Dẫn Cài Đặt & Chạy (Setup & Run)
|
|
41
|
-
Yêu cầu: Node.js version 18+ hoặc 20+.
|
|
1
|
+
# Multi QR Scanner POC
|
|
2
|
+
|
|
3
|
+
A high-performance React component capable of detecting and scanning **multiple QR codes simultaneously** in a single frame. Built with the native **Barcode Detection API** and optimized for performance using a state-driven approach.
|
|
4
|
+
|
|
5
|
+
This library is perfect for high-throughput scenarios like event check-ins, ticketing, or warehouse logistics where multiple codes need to be scanned efficiently.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
[](https://github.com/htsang1904/multi-qr)
|
|
9
|
+
[](https://htsang1904.github.io/multi-qr/)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- 🚀 **Multi-Code Detection**: Detects and reads multiple QR codes in the same frame.
|
|
15
|
+
- ⚡ **High Performance**: Uses the native `BarcodeDetector` API (Chrome/Android) for maximum speed.
|
|
16
|
+
- 🍎 **Cross-Platform**: Includes a polyfill for iOS (Safari) and environments without native support.
|
|
17
|
+
- 🎨 **Visual Feedback**: Draws bounding boxes around detected codes with color-coded status indicators.
|
|
18
|
+
- 🧠 **Smart De-duplication**: Built-in logic to handle `pending`, `success`, and `error` states to prevent duplicate API calls for the same code.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
Install the package via npm:
|
|
42
23
|
|
|
43
24
|
```bash
|
|
44
|
-
|
|
45
|
-
|
|
25
|
+
npm install multi-qr-scanner-poc
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Import the component and use it in your React application.
|
|
46
31
|
|
|
47
|
-
|
|
48
|
-
|
|
32
|
+
```tsx
|
|
33
|
+
import React, { useState } from 'react';
|
|
34
|
+
import MultiQRScanner, { DetectedBarcode, ScanStatus } from 'multi-qr-scanner-poc';
|
|
35
|
+
|
|
36
|
+
function App() {
|
|
37
|
+
// Map to track the status of each scanned QR code (e.g., 'processing', 'success')
|
|
38
|
+
const [codeStatuses, setCodeStatuses] = useState<Map<string, ScanStatus>>(new Map());
|
|
39
|
+
|
|
40
|
+
const handleScan = (codes: DetectedBarcode[]) => {
|
|
41
|
+
// 'codes' is an array of all QR codes detected in the current frame
|
|
42
|
+
codes.forEach((code) => {
|
|
43
|
+
const value = code.rawValue;
|
|
44
|
+
|
|
45
|
+
// Example logic: Only process new codes
|
|
46
|
+
if (!codeStatuses.has(value)) {
|
|
47
|
+
console.log('New QR Found:', value);
|
|
48
|
+
|
|
49
|
+
// 1. Mark as processing
|
|
50
|
+
updateStatus(value, 'processing');
|
|
51
|
+
|
|
52
|
+
// 2. Simulate API Call
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
// 3. Mark as success/error based on result
|
|
55
|
+
updateStatus(value, 'success');
|
|
56
|
+
}, 2000);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const updateStatus = (id: string, status: ScanStatus) => {
|
|
62
|
+
setCodeStatuses((prev) => {
|
|
63
|
+
const newMap = new Map(prev);
|
|
64
|
+
newMap.set(id, status);
|
|
65
|
+
return newMap;
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div style={{ width: '100%', maxWidth: '600px', margin: '0 auto' }}>
|
|
71
|
+
<h1>Multi QR Scanner</h1>
|
|
72
|
+
<MultiQRScanner
|
|
73
|
+
onCodesDetected={handleScan}
|
|
74
|
+
codeStatuses={codeStatuses}
|
|
75
|
+
scanInterval={500} // Optional: Scan every 500ms
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default App;
|
|
49
82
|
```
|
|
50
83
|
|
|
51
|
-
##
|
|
84
|
+
## Props
|
|
85
|
+
|
|
86
|
+
| Prop | Type | Default | Description |
|
|
87
|
+
|------|------|---------|-------------|
|
|
88
|
+
| `onCodesDetected` | `(codes: DetectedBarcode[]) => void` | **Required** | Callback function triggered when QR codes are detected. Receives an array of detected objects. |
|
|
89
|
+
| `codeStatuses` | `Map<string, ScanStatus>` | `new Map()` | A map of QR code values to their current status (`'pending'`, `'processing'`, `'success'`, `'error'`). Used to color-code the bounding boxes. |
|
|
90
|
+
| `scanInterval` | `number` | `600` | The interval (in ms) between scan attempts. Higher values reduce CPU usage but lower responsiveness. |
|
|
91
|
+
| `className` | `string` | `undefined` | Optional CSS class name for the wrapper div. |
|
|
92
|
+
| `style` | `React.CSSProperties` | `undefined` | Optional inline styles for the wrapper div. |
|
|
93
|
+
|
|
94
|
+
### Types
|
|
95
|
+
|
|
96
|
+
#### `DetectedBarcode`
|
|
97
|
+
Standard [Barcode Detection API](https://developer.mozilla.org/en-US/docs/Web/API/DetectedBarcode) interface:
|
|
98
|
+
- `rawValue`: string (The decoded text)
|
|
99
|
+
- `boundingBox`: DOMRectReadOnly (Position and size)
|
|
100
|
+
- `format`: string (Format, e.g., 'qr_code')
|
|
101
|
+
- `cornerPoints`: {x, y}[] (Coordinates of the 4 corners)
|
|
102
|
+
|
|
103
|
+
#### `ScanStatus`
|
|
104
|
+
- `'pending'`: Initial state (though usually `undefined` in the map means new).
|
|
105
|
+
- `'processing'`: Yellow bounding box.
|
|
106
|
+
- `'success'`: Green bounding box.
|
|
107
|
+
- `'error'`: Red bounding box.
|
|
52
108
|
|
|
53
|
-
|
|
109
|
+
## Browser Support
|
|
54
110
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- Sử dụng **WASM** (WebAssembly) cho các thuật toán xử lý ảnh chuyên sâu (nếu BarcodeDetector chưa đủ).
|
|
111
|
+
- **Android / Chrome / Edge**: Uses Native `BarcodeDetector` (Fastest).
|
|
112
|
+
- **iOS / Safari / Firefox**: Automatically falls back to `@undecaf/barcode-detector-polyfill` (WASM-based).
|
|
58
113
|
|
|
59
|
-
|
|
60
|
-
- Thay vì gọi API REST (`POST /check-in`), hãy chuyển sang dùng **WebSocket**.
|
|
61
|
-
- WebSocket giảm độ trễ kết nối, phù hợp cho việc check-in dòng người liên tục.
|
|
114
|
+
## License
|
|
62
115
|
|
|
63
|
-
|
|
64
|
-
- Thêm nút bật/tắt đèn Flash (Torch).
|
|
65
|
-
- Hỗ trợ Zoom Camera (sử dụng `imageCapture.setOptions`).
|
|
66
|
-
- Chuyển đổi linh hoạt giữa Camera trước/sau.
|
|
67
|
-
- Hỗ trợ đọc thêm Barcode 1D (EAN-13, UPC) song song với QR Code.
|
|
116
|
+
MIT © [Your Name / Organization]
|
package/dist/App.d.ts
ADDED
|
@@ -1 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
interface Point2D {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
}
|
|
6
|
+
export interface DetectedBarcode {
|
|
7
|
+
boundingBox: DOMRectReadOnly;
|
|
8
|
+
cornerPoints: Point2D[];
|
|
9
|
+
format: string;
|
|
10
|
+
rawValue: string;
|
|
11
|
+
}
|
|
12
|
+
declare global {
|
|
13
|
+
interface Window {
|
|
14
|
+
BarcodeDetector: any;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export type ScanStatus = 'pending' | 'processing' | 'success' | 'error';
|
|
18
|
+
export interface MultiQRScannerProps {
|
|
19
|
+
onCodesDetected: (codes: DetectedBarcode[]) => void;
|
|
20
|
+
codeStatuses?: Map<string, ScanStatus>;
|
|
21
|
+
scanInterval?: number;
|
|
22
|
+
className?: string;
|
|
23
|
+
style?: React.CSSProperties;
|
|
24
|
+
}
|
|
25
|
+
declare const MultiQRScanner: React.FC<MultiQRScannerProps>;
|
|
26
|
+
export default MultiQRScanner;
|
package/dist/main.d.ts
ADDED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multi-qr-scanner-poc",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/htsang1904/multi-qr.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://htsang1904.github.io/multi-qr/",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/htsang1904/multi-qr/issues"
|
|
12
|
+
},
|
|
5
13
|
"type": "module",
|
|
6
14
|
"main": "./dist/multi-qr-scanner.umd.cjs",
|
|
7
15
|
"module": "./dist/multi-qr-scanner.js",
|
|
8
16
|
"types": "./dist/components/MultiQRScanner.d.ts",
|
|
9
17
|
"exports": {
|
|
10
18
|
".": {
|
|
19
|
+
"types": "./dist/components/MultiQRScanner.d.ts",
|
|
11
20
|
"import": "./dist/multi-qr-scanner.js",
|
|
12
21
|
"require": "./dist/multi-qr-scanner.umd.cjs"
|
|
13
22
|
}
|