You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
4.1 KiB

---
description:
globs:
alwaysApply: true
---
# QR Code Handling Rule
## Architecture Overview
The QR code scanning functionality follows a platform-agnostic design using a factory pattern that provides different implementations for web and mobile platforms.
### Core Components
1. **Factory Pattern**
- `QRScannerFactory` - Creates appropriate scanner instance based on platform
- Common interface `QRScannerService` implemented by all scanners
- Platform detection via Capacitor and build flags
2. **Platform-Specific Implementations**
- `CapacitorQRScanner` - Native mobile implementation using MLKit
- `WebInlineQRScanner` - Web browser implementation using MediaDevices API
- `QRScannerDialog.vue` - Shared UI component
## Mobile Implementation (Capacitor)
### Technology Stack
- Uses `@capacitor-mlkit/barcode-scanning` plugin
- Configured in `capacitor.config.ts`
- Native camera access through platform APIs
### Key Features
- Direct camera access via native APIs
- Optimized for mobile performance
- Supports both iOS and Android
- Real-time QR code detection
- Back camera preferred for scanning
### Configuration
```typescript
MLKitBarcodeScanner: {
formats: ['QR_CODE'],
detectorSize: 1.0,
lensFacing: 'back',
googleBarcodeScannerModuleInstallState: true
}
```
### Permissions Handling
1. Check permissions via `BarcodeScanner.checkPermissions()`
2. Request permissions if needed
3. Handle permission states (granted/denied)
4. Graceful fallbacks for permission issues
## Web Implementation
### Technology Stack
- Uses browser's MediaDevices API
- Vue.js components for UI
- EventEmitter for stream management
### Key Features
- Browser-based camera access
- Inline camera preview
- Responsive design
- Cross-browser compatibility
- Progressive enhancement
### Permissions Handling
1. Uses browser's permission API
2. MediaDevices API for camera access
3. Handles secure context requirements
4. Provides user feedback for permission states
## Shared Features
### Error Handling
1. Permission denied scenarios
2. Device compatibility checks
3. Camera access failures
4. QR code validation
5. Network connectivity issues
### User Experience
1. Clear feedback during scanning
2. Loading states
3. Error messages
4. Success confirmations
5. Camera preview
### Security
1. HTTPS requirement for web
2. Permission validation
3. Data validation
4. Safe error handling
## Usage Guidelines
### Platform Detection
```typescript
const isNative = QRScannerFactory.isNativePlatform();
if (isNative) {
// Use native scanner
} else {
// Use web scanner
}
```
### Implementation Example
```typescript
const scanner = QRScannerFactory.getInstance();
await scanner.checkPermissions();
await scanner.startScan();
scanner.addListener({
onScan: (result) => {
// Handle scan result
},
onError: (error) => {
// Handle error
}
});
```
### Best Practices
1. Always check permissions before starting scan
2. Clean up resources after scanning
3. Handle all error cases
4. Provide clear user feedback
5. Test on multiple devices/browsers
## Platform-Specific Notes
### Mobile (Capacitor)
1. Use native camera API when available
2. Handle device rotation
3. Support both front/back cameras
4. Manage system permissions properly
5. Handle app lifecycle events
### Web
1. Check browser compatibility
2. Handle secure context requirement
3. Manage memory usage
4. Clean up MediaStream
5. Handle tab visibility changes
## Testing Requirements
1. Test on multiple devices
2. Verify permission flows
3. Check error handling
4. Validate cleanup
5. Verify cross-platform behavior
## Service Interface
```typescript
interface QRScannerService {
checkPermissions(): Promise<boolean>;
requestPermissions(): Promise<boolean>;
isSupported(): Promise<boolean>;
startScan(options?: QRScannerOptions): Promise<void>;
stopScan(): Promise<void>;
addListener(listener: ScanListener): void;
onStream(callback: (stream: MediaStream | null) => void): void;
cleanup(): Promise<void>;
}
interface ScanListener {
onScan: (result: string) => void;
onError?: (error: Error) => void;
}
interface QRScannerOptions {
camera?: "front" | "back";
showPreview?: boolean;
playSound?: boolean;
}