From c3bd22fb835ae7e042c9f88351ed30c53198c47b Mon Sep 17 00:00:00 2001 From: Jose Olarte III Date: Mon, 28 Jul 2025 16:06:48 +0800 Subject: [PATCH] Fix: iOS copy function - Update ContactsView, ShareMyContactInfoView, ContactQRScanShowView to use new service - Replace unreliable web navigator.clipboard with native Capacitor clipboard - Add comprehensive error handling and logging for clipboard operations - Sync Capacitor plugins to include clipboard functionality --- src/views/ContactQRScanShowView.vue | 37 +++++++++++++++++----------- src/views/ContactsView.vue | 16 ++++++------ src/views/ShareMyContactInfoView.vue | 4 +-- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/views/ContactQRScanShowView.vue b/src/views/ContactQRScanShowView.vue index 4540a296..514f2a19 100644 --- a/src/views/ContactQRScanShowView.vue +++ b/src/views/ContactQRScanShowView.vue @@ -140,7 +140,7 @@ import { AxiosError } from "axios"; import { Buffer } from "buffer/"; import QRCodeVue3 from "qr-code-generator-vue3"; import { Component, Vue } from "vue-facing-decorator"; -import { useClipboard } from "@vueuse/core"; + import { QrcodeStream } from "vue-qrcode-reader"; import QuickNav from "../components/QuickNav.vue"; @@ -185,7 +185,7 @@ import { createQRContactAddedMessage, createQRRegistrationSuccessMessage, QR_TIMEOUT_SHORT, - QR_TIMEOUT_MEDIUM, + QR_TIMEOUT_STANDARD, QR_TIMEOUT_LONG, } from "@/constants/notifications"; @@ -547,8 +547,8 @@ export default class ContactQRScanShow extends Vue { name: contact.name, }); this.notify.toast( + NOTIFY_QR_REGISTRATION_SUBMITTED.title, NOTIFY_QR_REGISTRATION_SUBMITTED.message, - QR_TIMEOUT_SHORT, ); try { @@ -621,24 +621,33 @@ export default class ContactQRScanShow extends Vue { this.profileImageUrl, true, ); - useClipboard() - .copy(jwtUrl) - .then(() => { - this.notify.toast(NOTIFY_QR_URL_COPIED.message, QR_TIMEOUT_MEDIUM); - }); + try { + const { copyToClipboard } = await import("../services/ClipboardService"); + await copyToClipboard(jwtUrl); + this.notify.toast( + NOTIFY_QR_URL_COPIED.title, + NOTIFY_QR_URL_COPIED.message, + ); + } catch (error) { + this.$logAndConsole(`Error copying URL to clipboard: ${error}`, true); + this.notify.error("Failed to copy URL to clipboard."); + } } toastQRCodeHelp() { this.notify.info(NOTIFY_QR_CODE_HELP.message, QR_TIMEOUT_LONG); } - onCopyDidToClipboard() { + async onCopyDidToClipboard() { //this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing - useClipboard() - .copy(this.activeDid) - .then(() => { - this.notify.info(NOTIFY_QR_DID_COPIED.message, QR_TIMEOUT_LONG); - }); + try { + const { copyToClipboard } = await import("../services/ClipboardService"); + await copyToClipboard(this.activeDid); + this.notify.info(NOTIFY_QR_DID_COPIED.message, QR_TIMEOUT_LONG); + } catch (error) { + this.$logAndConsole(`Error copying DID to clipboard: ${error}`, true); + this.notify.error("Failed to copy DID to clipboard."); + } } openUserNameDialog() { diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 3d5576e7..0b9df9c8 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -126,10 +126,10 @@ import { JWTPayload } from "did-jwt"; import * as R from "ramda"; import { Component, Vue } from "vue-facing-decorator"; import { RouteLocationNormalizedLoaded, Router } from "vue-router"; -import { useClipboard } from "@vueuse/core"; import { Capacitor } from "@capacitor/core"; import QuickNav from "../components/QuickNav.vue"; +import { copyToClipboard } from "../services/ClipboardService"; import EntityIcon from "../components/EntityIcon.vue"; import GiftedDialog from "../components/GiftedDialog.vue"; import OfferDialog from "../components/OfferDialog.vue"; @@ -1172,12 +1172,14 @@ export default class ContactsView extends Vue { }); // Use production URL for sharing to avoid localhost issues in development const contactsJwtUrl = `${APP_SERVER}/deep-link/contact-import/${contactsJwt}`; - useClipboard() - .copy(contactsJwtUrl) - .then(() => { - // Use notification helper - this.notify.copied(NOTIFY_CONTACT_LINK_COPIED.message); - }); + try { + await copyToClipboard(contactsJwtUrl); + // Use notification helper + this.notify.copied(NOTIFY_CONTACT_LINK_COPIED.message); + } catch (error) { + this.$logAndConsole(`Error copying to clipboard: ${error}`, true); + this.notify.error("Failed to copy to clipboard. Please try again."); + } } private showCopySelectionsInfo() { diff --git a/src/views/ShareMyContactInfoView.vue b/src/views/ShareMyContactInfoView.vue index 93a39f0c..cd77022a 100644 --- a/src/views/ShareMyContactInfoView.vue +++ b/src/views/ShareMyContactInfoView.vue @@ -150,8 +150,8 @@ export default class ShareMyContactInfoView extends Vue { * Copy the contact message to clipboard */ private async copyToClipboard(message: string): Promise { - const { useClipboard } = await import("@vueuse/core"); - await useClipboard().copy(message); + const { copyToClipboard } = await import("../services/ClipboardService"); + await copyToClipboard(message); } /**