--- 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; requestPermissions(): Promise; isSupported(): Promise; startScan(options?: QRScannerOptions): Promise; stopScan(): Promise; addListener(listener: ScanListener): void; onStream(callback: (stream: MediaStream | null) => void): void; cleanup(): Promise; } interface ScanListener { onScan: (result: string) => void; onError?: (error: Error) => void; } interface QRScannerOptions { camera?: "front" | "back"; showPreview?: boolean; playSound?: boolean; }