diff --git a/src/components/QRScanner/QRScannerDialog.vue b/src/components/QRScanner/QRScannerDialog.vue index ed9818ab..11ed0d12 100644 --- a/src/components/QRScanner/QRScannerDialog.vue +++ b/src/components/QRScanner/QRScannerDialog.vue @@ -37,6 +37,16 @@ v-if="useQRReader && !isNativePlatform" class="relative aspect-square" > + +
+

Initializing camera...

+

Position QR code in the frame

+

{{ error }}

+

Ready to scan

+
+ + +
+ + +

@@ -56,19 +101,43 @@ : "QR code scanning is not supported in this browser." }}

+

+ Please ensure you're using a modern browser with camera access. +

-

{{ error }}

-
- +
+ +
+
    +
  • Ensure the QR code is well-lit and in focus
  • +
  • Hold your device steady
  • +
  • The QR code should fit within the scanning frame
  • +
+
+ + +

{{ error }}

+ + +
+ + +
@@ -106,6 +175,10 @@ export default class QRScannerDialog extends Vue { __IS_MOBILE__ || Capacitor.getPlatform() === "android" || Capacitor.getPlatform() === "ios"; + + isInitializing = true; + isScanning = false; + preferredCamera: 'user' | 'environment' = 'environment'; created() { logger.log("QRScannerDialog platform detection:", { @@ -133,10 +206,13 @@ export default class QRScannerDialog extends Vue { return; } + this.isInitializing = true; + this.error = null; logger.log("Initializing QR scanner..."); + try { await promise; - this.error = null; + this.isInitializing = false; logger.log("QR scanner initialized successfully"); } catch (error) { const wrappedError = @@ -150,10 +226,13 @@ export default class QRScannerDialog extends Vue { stack: wrappedError.stack, name: wrappedError.name, }); + } finally { + this.isInitializing = false; } } onDetect(promise: Promise): void { + this.isScanning = true; logger.log("QR code detected, processing..."); promise .then((result) => { @@ -164,6 +243,9 @@ export default class QRScannerDialog extends Vue { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, }); + }) + .finally(() => { + this.isScanning = false; }); } @@ -188,6 +270,7 @@ export default class QRScannerDialog extends Vue { } onError(error: Error): void { + this.isScanning = false; logger.error("QR scanner error:", { error: error.message, stack: error.stack, @@ -199,6 +282,16 @@ export default class QRScannerDialog extends Vue { } } + toggleCamera(): void { + this.preferredCamera = this.preferredCamera === 'user' ? 'environment' : 'user'; + } + + retryScanning(): void { + this.error = null; + this.isInitializing = true; + // The QR scanner component will automatically reinitialize + } + async close(): Promise { logger.log("Closing QR scanner dialog"); this.visible = false; @@ -219,4 +312,20 @@ export default class QRScannerDialog extends Vue { width: 100%; height: 100%; } + +@keyframes pulse { + 0% { + opacity: 0.5; + } + 50% { + opacity: 0.75; + } + 100% { + opacity: 0.5; + } +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +}