De-coupled web and mobile QR scanner views

- Separate scanner views for web and mobile platforms: different libraries, similar layouts
- Mobile: QR code overlaid on top of full-screen camera view
- Mobile: added framing box + instruction text
- Mobile: increased debounce time to compensate for behavior of MLkit scanner
- Web: removed Capacitor-related code and platform-specific conditions
- Web: adjusted max-size of QR code and camera view to better fit newer iOS device screens
- Web + mobile: camera view remains active when a QR scan is triggered
This commit is contained in:
Jose Olarte III
2025-05-22 19:46:19 +08:00
parent 10df60316a
commit e2787e3afa
5 changed files with 229 additions and 61 deletions

View File

@@ -42,7 +42,7 @@
<div
v-if="activeDid && activeDid.startsWith(ETHR_DID_PREFIX)"
class="block w-[90vw] max-w-[40vh] mx-auto my-4"
class="block w-[90vw] max-w-[calc((100vh-env(safe-area-inset-top)-env(safe-area-inset-bottom))*0.4)] mx-auto my-4"
@click="onCopyUrlToClipboard()"
>
<!--
@@ -75,13 +75,13 @@
create your identifier.
</router-link>
<br />
If you don't that first, these contacts won't see your activity.
If you don't do that first, these contacts won't see your activity.
</div>
<div class="text-center mt-6">
<div
v-if="isScanning && !isNativePlatform"
class="relative aspect-square overflow-hidden bg-slate-800 w-[90vw] max-w-[40vh] mx-auto"
v-if="isScanning"
class="relative aspect-square overflow-hidden bg-slate-800 w-[90vw] max-w-[calc((100vh-env(safe-area-inset-top)-env(safe-area-inset-bottom))*0.4)] mx-auto"
>
<!-- Status Message -->
<div
@@ -142,7 +142,7 @@
</div>
<qrcode-stream
v-if="useQRReader && !isNativePlatform"
v-if="useQRReader"
:camera="preferredCamera"
@decode="onDecode"
@init="onInit"
@@ -167,17 +167,9 @@
</div>
<div
v-else
class="flex items-center justify-center aspect-square overflow-hidden bg-slate-800 w-[90vw] max-w-[40vh] mx-auto"
class="flex items-center justify-center aspect-square overflow-hidden bg-slate-800 w-[90vw] max-w-[calc((100vh-env(safe-area-inset-top)-env(safe-area-inset-bottom))*0.4)] mx-auto"
>
<button
v-if="isNativePlatform"
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white text-lg px-3 py-2 rounded-lg"
@click="$router.push({ name: 'contact-qr-scan-full' })"
>
Scan QR Code
</button>
<button
v-else
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white text-lg px-3 py-2 rounded-lg"
@click="startScanning"
>
@@ -193,7 +185,6 @@ import { AxiosError } from "axios";
import QRCodeVue3 from "qr-code-generator-vue3";
import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core";
import { Capacitor } from "@capacitor/core";
import { QrcodeStream } from "vue-qrcode-reader";
import QuickNav from "../components/QuickNav.vue";
@@ -244,7 +235,6 @@ export default class ContactQRScanShow extends Vue {
qrValue = "";
isScanning = false;
error: string | null = null;
isNativePlatform = Capacitor.isNativePlatform();
// QR Scanner properties
isInitializing = true;
@@ -534,13 +524,12 @@ export default class ContactQRScanShow extends Vue {
notes: contactInfo.notes || "",
};
// Add contact and stop scanning
// Add contact but keep scanning
logger.info("Adding new contact to database:", {
did: contact.did,
name: contact.name,
});
await this.addNewContact(contact);
await this.stopScanning();
} catch (error) {
logger.error("Error processing contact QR code:", {
error: error instanceof Error ? error.message : String(error),
@@ -692,6 +681,7 @@ export default class ContactQRScanShow extends Vue {
{
group: "alert",
type: "info",
title: "QR Code Help",
text: "Click the QR code to copy your contact info to your clipboard.",
},
5000,
@@ -726,10 +716,8 @@ export default class ContactQRScanShow extends Vue {
this.isMounted = true;
document.addEventListener("pause", this.handleAppPause);
document.addEventListener("resume", this.handleAppResume);
// Start scanning automatically when view is loaded, but only on web platform
if (!this.isNativePlatform) {
this.startScanning();
}
// Start scanning automatically when view is loaded
this.startScanning();
}
beforeDestroy() {
@@ -856,11 +844,6 @@ export default class ContactQRScanShow extends Vue {
async onInit(promise: Promise<void>): Promise<void> {
logger.log("[QRScanner] onInit called");
if (this.isNativePlatform) {
logger.log("Skipping QR scanner initialization on native platform");
return;
}
try {
await promise;
this.isInitializing = false;
@@ -889,7 +872,7 @@ export default class ContactQRScanShow extends Vue {
onDetect(result: unknown): void {
this.isScanning = true;
this.cameraState = "detecting";
this.cameraState = "active";
try {
let rawValue: string | undefined;
if (
@@ -899,7 +882,7 @@ export default class ContactQRScanShow extends Vue {
) {
rawValue = result[0].rawValue;
} else if (result && typeof result === "object" && "rawValue" in result) {
rawValue = result.rawValue;
rawValue = (result as { rawValue: string }).rawValue;
}
if (rawValue) {
this.isInitializing = false;
@@ -909,7 +892,6 @@ export default class ContactQRScanShow extends Vue {
} catch (error) {
this.handleError(error);
} finally {
this.isScanning = false;
this.cameraState = "active";
}
}