forked from trent_larson/crowd-funder-for-time-pwa
- Fix Vue template syntax in App.vue by using proper event handler format - Update Vite config to properly handle ESM imports and crypto modules - Add manual chunks for better code splitting - Improve environment variable handling in vite-env.d.ts - Fix TypeScript linting errors in App.vue
91 lines
2.5 KiB
TypeScript
91 lines
2.5 KiB
TypeScript
import type { QRScannerService, ScanListener } from './types'
|
|
import QRScannerDialog from '../../components/QRScannerDialog.vue'
|
|
import { createApp, type App } from 'vue'
|
|
import { logger } from '../../utils/logger'
|
|
|
|
// Import platform-specific flags from Vite config
|
|
declare const __USE_QR_READER__: boolean
|
|
|
|
export class WebDialogQRScanner implements QRScannerService {
|
|
private dialogInstance: App | null = null
|
|
private dialogComponent: InstanceType<typeof QRScannerDialog> | null = null
|
|
private scanListener: ScanListener | null = null
|
|
|
|
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: { facingMode: 'environment' }
|
|
})
|
|
stream.getTracks().forEach((track) => track.stop())
|
|
return true
|
|
} catch (error) {
|
|
logger.error('Error requesting camera permissions:', error)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async isSupported(): Promise<boolean> {
|
|
if (!__USE_QR_READER__) {
|
|
return false
|
|
}
|
|
return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)
|
|
}
|
|
|
|
async startScan(): Promise<void> {
|
|
if (!__USE_QR_READER__) {
|
|
throw new Error('Web QR scanner is not supported on this platform')
|
|
}
|
|
|
|
if (!this.dialogInstance) {
|
|
const div = document.createElement('div')
|
|
document.body.appendChild(div)
|
|
|
|
this.dialogInstance = createApp(QRScannerDialog)
|
|
this.dialogComponent = this.dialogInstance.mount(div) as InstanceType<
|
|
typeof QRScannerDialog
|
|
>
|
|
}
|
|
|
|
if (this.dialogComponent && this.scanListener) {
|
|
this.dialogComponent.open((result: string) => {
|
|
if (this.scanListener) {
|
|
this.scanListener.onScan(result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
async stopScan(): Promise<void> {
|
|
if (this.dialogComponent) {
|
|
this.dialogComponent.close()
|
|
}
|
|
}
|
|
|
|
addListener(listener: ScanListener): void {
|
|
this.scanListener = listener
|
|
}
|
|
|
|
async cleanup(): Promise<void> {
|
|
if (this.dialogComponent) {
|
|
this.dialogComponent.close()
|
|
}
|
|
if (this.dialogInstance) {
|
|
this.dialogInstance.unmount()
|
|
this.dialogInstance = null
|
|
this.dialogComponent = null
|
|
}
|
|
}
|
|
}
|