- Updated the loading state condition in qr-scanner.vue to check for camera permission correctly. - Removed the unused videoElement reference in useQRScanner.ts to clean up the code. These changes improve the functionality and clarity of the QR scanner component.
109 lines
No EOL
2.6 KiB
TypeScript
109 lines
No EOL
2.6 KiB
TypeScript
import { ref, onUnmounted } from 'vue'
|
|
import QrScanner from 'qr-scanner'
|
|
|
|
export function useQRScanner() {
|
|
const isScanning = ref(false)
|
|
const hasPermission = ref<boolean | null>(null)
|
|
const error = ref<string | null>(null)
|
|
const scanResult = ref<string | null>(null)
|
|
|
|
let qrScanner: QrScanner | null = null
|
|
|
|
const startScanning = async (videoEl: HTMLVideoElement, onResult: (result: string) => void) => {
|
|
try {
|
|
error.value = null
|
|
|
|
// Check if camera is available
|
|
const hasCamera = await QrScanner.hasCamera()
|
|
if (!hasCamera) {
|
|
throw new Error('No camera found')
|
|
}
|
|
|
|
// Request camera permission
|
|
await navigator.mediaDevices.getUserMedia({ video: true })
|
|
hasPermission.value = true
|
|
|
|
// Create QR scanner instance
|
|
qrScanner = new QrScanner(
|
|
videoEl,
|
|
(result) => {
|
|
scanResult.value = result.data
|
|
onResult(result.data)
|
|
},
|
|
{
|
|
highlightScanRegion: true,
|
|
highlightCodeOutline: true,
|
|
maxScansPerSecond: 5,
|
|
}
|
|
)
|
|
|
|
await qrScanner.start()
|
|
isScanning.value = true
|
|
|
|
} catch (err) {
|
|
console.error('Failed to start QR scanner:', err)
|
|
hasPermission.value = false
|
|
|
|
if (err instanceof Error) {
|
|
if (err.name === 'NotAllowedError') {
|
|
error.value = 'Camera permission denied. Please allow camera access and try again.'
|
|
} else if (err.name === 'NotFoundError') {
|
|
error.value = 'No camera found on this device.'
|
|
} else if (err.name === 'NotSupportedError') {
|
|
error.value = 'Camera not supported on this device.'
|
|
} else {
|
|
error.value = err.message
|
|
}
|
|
} else {
|
|
error.value = 'Failed to access camera'
|
|
}
|
|
}
|
|
}
|
|
|
|
const stopScanning = () => {
|
|
if (qrScanner) {
|
|
qrScanner.stop()
|
|
qrScanner.destroy()
|
|
qrScanner = null
|
|
}
|
|
isScanning.value = false
|
|
scanResult.value = null
|
|
}
|
|
|
|
const toggleFlash = async () => {
|
|
if (qrScanner) {
|
|
try {
|
|
await qrScanner.toggleFlash()
|
|
} catch (err) {
|
|
console.error('Failed to toggle flash:', err)
|
|
}
|
|
}
|
|
}
|
|
|
|
const hasFlash = async (): Promise<boolean> => {
|
|
if (qrScanner) {
|
|
try {
|
|
return await qrScanner.hasFlash()
|
|
} catch (err) {
|
|
return false
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Cleanup on unmount
|
|
onUnmounted(() => {
|
|
stopScanning()
|
|
})
|
|
|
|
return {
|
|
isScanning,
|
|
hasPermission,
|
|
error,
|
|
scanResult,
|
|
startScanning,
|
|
stopScanning,
|
|
toggleFlash,
|
|
hasFlash
|
|
}
|
|
} |