Add QR code scanning functionality with new QRScanner component

- Introduced a new QRScanner component to facilitate QR code scanning within the application.
- Integrated QR code scanning capabilities into the SendDialog.vue, allowing users to scan QR codes for payment destinations.
- Updated package.json and package-lock.json to include the qr-scanner library for QR code processing.
- Enhanced user experience by providing visual feedback and error handling during the scanning process.

These changes improve the payment workflow by enabling users to easily scan QR codes for transactions.
This commit is contained in:
padreug 2025-09-18 22:14:22 +02:00
parent c849258b5f
commit bebdc3c24c
5 changed files with 317 additions and 4 deletions

View file

@ -0,0 +1,111 @@
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
let videoElement: HTMLVideoElement | null = null
const startScanning = async (videoEl: HTMLVideoElement, onResult: (result: string) => void) => {
try {
error.value = null
videoElement = videoEl
// 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
}
}