timesafari
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.
 
 
 

108 lines
3.0 KiB

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;
}
}