import { createApp, App } from "vue"; import { QRScannerService, ScanListener, QRScannerOptions } from "./types"; import QRScannerDialog from "@/components/QRScanner/QRScannerDialog.vue"; import { logger } from "@/utils/logger"; export class WebDialogQRScanner implements QRScannerService { private dialogInstance: App | null = null; private dialogComponent: InstanceType | null = null; private scanListener: ScanListener | null = null; private isScanning = false; constructor(private options?: QRScannerOptions) {} async checkPermissions(): Promise { try { const permissions = await navigator.permissions.query({ name: "camera" as PermissionName, }); return permissions.state === "granted"; } catch (error) { logger.error("Error checking camera permissions:", error); return false; } } async requestPermissions(): Promise { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true }); stream.getTracks().forEach((track) => track.stop()); return true; } catch (error) { logger.error("Error requesting camera permissions:", error); return false; } } async isSupported(): Promise { return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia); } async startScan(): Promise { if (this.isScanning) { return; } try { this.isScanning = true; // Create and mount dialog component const container = document.createElement("div"); document.body.appendChild(container); this.dialogInstance = createApp(QRScannerDialog, { onScan: (result: string) => { if (this.scanListener) { this.scanListener.onScan(result); } }, onError: (error: Error) => { if (this.scanListener?.onError) { this.scanListener.onError(error); } }, options: this.options, }); this.dialogComponent = this.dialogInstance.mount(container).$refs .dialog as InstanceType; } catch (error) { this.isScanning = false; if (this.scanListener?.onError) { this.scanListener.onError( error instanceof Error ? error : new Error(String(error)), ); } logger.error("Error starting scan:", error); } } async stopScan(): Promise { if (!this.isScanning) { return; } try { if (this.dialogComponent) { await this.dialogComponent.close(); } if (this.dialogInstance) { this.dialogInstance.unmount(); } this.isScanning = false; } catch (error) { logger.error("Error stopping scan:", error); } } addListener(listener: ScanListener): void { this.scanListener = listener; } async cleanup(): Promise { await this.stopScan(); this.dialogComponent = null; this.dialogInstance = null; this.scanListener = null; } }