feature(qrcode): reboot qrcode reader

This commit is contained in:
Matthew Raymer
2025-04-21 10:13:12 +00:00
parent 2b7b07441e
commit ff605b3676
11 changed files with 1676 additions and 0 deletions

View File

@@ -0,0 +1,158 @@
<!-- QRScannerDialog.vue -->
<template>
<div
v-if="visible && !isNativePlatform"
class="dialog-overlay z-[60] fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"
>
<div
class="dialog relative bg-white rounded-lg shadow-xl max-w-lg w-full mx-4"
>
<!-- Header -->
<div class="p-4 border-b border-gray-200">
<h3 class="text-lg font-medium text-gray-900">Scan QR Code</h3>
<button
class="absolute top-4 right-4 text-gray-400 hover:text-gray-500"
aria-label="Close dialog"
@click="close"
>
<svg
class="h-6 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<!-- Scanner -->
<div class="p-4">
<div v-if="useQRReader && !isNativePlatform" class="relative aspect-square">
<qrcode-stream
:camera="options?.camera === 'front' ? 'user' : 'environment'"
@decode="onDecode"
@init="onInit"
/>
<div
class="absolute inset-0 border-2 border-blue-500 opacity-50 pointer-events-none"
></div>
</div>
<div v-else class="text-center py-8">
<p class="text-gray-500">
{{ isNativePlatform ? 'Using native camera scanner...' : 'QR code scanning is not supported in this browser.' }}
</p>
</div>
</div>
<!-- Footer -->
<div class="p-4 border-t border-gray-200">
<p v-if="error" class="text-red-500 text-sm mb-4">{{ error }}</p>
<div class="flex justify-end">
<button
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200"
@click="close"
>
Cancel
</button>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator";
import { QrcodeStream } from "vue-qrcode-reader";
import { QRScannerOptions } from "@/services/QRScanner/types";
import { logger } from "@/utils/logger";
import { Capacitor } from "@capacitor/core";
@Component({
components: {
QrcodeStream,
},
})
export default class QRScannerDialog extends Vue {
@Prop({ type: Function, required: true }) onScan!: (result: string) => void;
@Prop({ type: Function }) onError?: (error: Error) => void;
@Prop({ type: Object }) options?: QRScannerOptions;
visible = true;
error: string | null = null;
useQRReader = __USE_QR_READER__;
isNativePlatform = Capacitor.isNativePlatform() || __IS_MOBILE__ || Capacitor.getPlatform() === 'android' || Capacitor.getPlatform() === 'ios';
created() {
logger.log('QRScannerDialog platform detection:', {
capacitorNative: Capacitor.isNativePlatform(),
isMobile: __IS_MOBILE__,
platform: Capacitor.getPlatform(),
useQRReader: this.useQRReader,
isNativePlatform: this.isNativePlatform
});
// If on native platform, close immediately and don't initialize web scanner
if (this.isNativePlatform) {
logger.log('Closing QR dialog on native platform');
this.$nextTick(() => this.close());
}
}
async onInit(promise: Promise<void>): Promise<void> {
// Don't initialize on mobile platforms
if (this.isNativePlatform) {
logger.log('Skipping web scanner initialization on native platform');
return;
}
try {
await promise;
this.error = null;
} catch (error) {
this.error = error instanceof Error ? error.message : String(error);
if (this.onError) {
this.onError(error instanceof Error ? error : new Error(String(error)));
}
logger.error("Error initializing QR scanner:", error);
}
}
onDecode(result: string): void {
try {
this.onScan(result);
this.close();
} catch (error) {
this.error = error instanceof Error ? error.message : String(error);
if (this.onError) {
this.onError(error instanceof Error ? error : new Error(String(error)));
}
logger.error("Error handling QR scan result:", error);
}
}
async close(): Promise<void> {
this.visible = false;
await this.$nextTick();
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el);
}
}
}
</script>
<style scoped>
.dialog-overlay {
backdrop-filter: blur(4px);
}
.qrcode-stream {
width: 100%;
height: 100%;
}
</style>