forked from jsnbuchanan/crowd-funder-for-time-pwa
feature(qrcode): reboot qrcode reader
This commit is contained in:
108
src/services/QRScanner/WebDialogQRScanner.ts
Normal file
108
src/services/QRScanner/WebDialogQRScanner.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
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<typeof QRScannerDialog> | null = null;
|
||||
private scanListener: ScanListener | null = null;
|
||||
private isScanning = false;
|
||||
|
||||
constructor(private options?: QRScannerOptions) {}
|
||||
|
||||
async checkPermissions(): Promise<boolean> {
|
||||
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<boolean> {
|
||||
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<boolean> {
|
||||
return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
|
||||
}
|
||||
|
||||
async startScan(): Promise<void> {
|
||||
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<typeof QRScannerDialog>;
|
||||
} 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<void> {
|
||||
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<void> {
|
||||
await this.stopScan();
|
||||
this.dialogComponent = null;
|
||||
this.dialogInstance = null;
|
||||
this.scanListener = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user