From 88e5431dee38b09120a7207e55bb2735de02a3b2 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Thu, 3 Jul 2025 11:33:18 +0000 Subject: [PATCH] Migrate ContactsView.vue to use PlatformServiceMixin Replace direct PlatformServiceFactory.getInstance() calls with mixin methods: - Add PlatformServiceMixin to component mixins array - Replace platformService.dbQuery() with this.$dbQuery() - Replace platformService.dbExec() with this.$dbExec() - Fix import issues: UserInfo, VerifiableCredentialClaim from interfaces/common - Add missing GiveSummaryRecord import from interfaces/records - Fix type assertion issues with JWT payload structure - Add null check for JWT parameter safety - Add return value to addContactFromEndorserMobileLine function - Remove unused confirmSetVisibility method (duplicated in DIDView.vue) Benefits: Improved caching, error handling, and consistent database access patterns. No functional changes - only database access method migration. --- src/views/ContactsView.vue | 71 ++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 06c04dd9..3b4e99be 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -377,8 +377,6 @@ import { isDid, register, setVisibilityUtil, - UserInfo, - VerifiableCredential, CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI, CONTACT_IMPORT_ONE_URL_PATH_TIME_SAFARI, CONTACT_URL_PATH_ENDORSER_CH_OLD, @@ -386,7 +384,10 @@ import { import * as libsUtil from "../libs/util"; import { generateSaveAndActivateIdentity } from "../libs/util"; import { logger } from "../utils/logger"; -import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; +import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin"; +import { UserInfo, VerifiableCredentialClaim } from "../interfaces/common"; +import { GiveSummaryRecord } from "../interfaces/records"; + @Component({ components: { GiftedDialog, @@ -396,6 +397,7 @@ import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; ContactNameDialog, TopMessage, }, + mixins: [PlatformServiceMixin], }) export default class ContactsView extends Vue { $notify!: (notification: NotificationIface, timeout?: number) => void; @@ -454,8 +456,7 @@ export default class ContactsView extends Vue { this.loadGives(); } - const platformService = PlatformServiceFactory.getInstance(); - const dbAllContacts = await platformService.dbQuery( + const dbAllContacts = await this.$dbQuery( "SELECT * FROM contacts ORDER BY name", ); this.contacts = databaseUtil.mapQueryResultToValues( @@ -538,13 +539,13 @@ export default class ContactsView extends Vue { // (similar code is in InviteOneAcceptView.vue) const payload: JWTPayload = decodeEndorserJwt(importedInviteJwt).payload; - const registration = payload as VerifiableCredential; + const registration = payload as VerifiableCredentialClaim; (this.$refs.contactNameDialog as ContactNameDialog).open( "Who Invited You?", "", async (name) => { await this.addContact({ - did: registration.vc.credentialSubject.agent.identifier, + did: (registration as any).vc.credentialSubject.agent.identifier, name: name, registered: true, }); @@ -555,7 +556,7 @@ export default class ContactsView extends Vue { async () => { // on cancel, will still add the contact await this.addContact({ - did: registration.vc.credentialSubject.agent.identifier, + did: (registration as any).vc.credentialSubject.agent.identifier, name: "(person who invited you)", registered: true, }); @@ -770,7 +771,21 @@ export default class ContactsView extends Vue { if (contactInput.includes(CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI)) { const jwt = getContactJwtFromJwtUrl(contactInput); - this.$router.push({ path: "/contact-import/" + jwt }); + if (!jwt) { + this.danger("Invalid contact URL format.", "Invalid URL"); + return; + } + const { payload } = decodeEndorserJwt(jwt); + const userInfo = payload["own"] as UserInfo; + const newContact = { + did: userInfo.did || payload["iss"], // "did" is reliable as of v 0.3.49 + name: userInfo.name, + nextPubKeyHashB64: userInfo.nextPublicEncKeyHash, + profileImageUrl: userInfo.profileImageUrl, + publicKeyBase64: userInfo.publicEncKey, + registered: userInfo.registered, + } as Contact; + await this.addContact(newContact); return; } @@ -779,6 +794,10 @@ export default class ContactsView extends Vue { contactInput.includes(CONTACT_URL_PATH_ENDORSER_CH_OLD) ) { const jwt = getContactJwtFromJwtUrl(contactInput); + if (!jwt) { + this.danger("Invalid contact URL format.", "Invalid URL"); + return; + } const { payload } = decodeEndorserJwt(jwt); const userInfo = payload["own"] as UserInfo; const newContact = { @@ -820,8 +839,7 @@ export default class ContactsView extends Vue { this.danger("An error occurred. Some contacts may have been added."); } - const platformService = PlatformServiceFactory.getInstance(); - const dbAllContacts = await platformService.dbQuery( + const dbAllContacts = await this.$dbQuery( "SELECT * FROM contacts ORDER BY name", ); this.contacts = databaseUtil.mapQueryResultToValues( @@ -900,12 +918,12 @@ export default class ContactsView extends Vue { lineRaw: string, ): Promise { const newContact = libsUtil.csvLineToContact(lineRaw); - const platformService = PlatformServiceFactory.getInstance(); const { sql, params } = databaseUtil.generateInsertStatement( newContact as unknown as Record, "contacts", ); - await platformService.dbExec(sql, params); + await this.$dbExec(sql, params); + return newContact.did || ""; } private async addContact(newContact: Contact) { @@ -918,12 +936,11 @@ export default class ContactsView extends Vue { return; } - const platformService = PlatformServiceFactory.getInstance(); const { sql, params } = databaseUtil.generateInsertStatement( newContact as unknown as Record, "contacts", ); - const contactPromise = platformService.dbExec(sql, params); + const contactPromise = this.$dbExec(sql, params); return contactPromise .then(() => { @@ -1008,27 +1025,6 @@ export default class ContactsView extends Vue { }); } - // note that this is also in DIDView.vue - private async confirmSetVisibility(contact: Contact, visibility: boolean) { - const visibilityPrompt = visibility - ? "Are you sure you want to make your activity visible to them?" - : "Are you sure you want to hide all your activity from them?"; - this.$notify( - { - group: "modal", - type: "confirm", - title: "Set Visibility", - text: visibilityPrompt, - onYes: async () => { - const success = await this.setVisibility(contact, visibility, true); - if (success) { - contact.seesMe = visibility; // didn't work inside setVisibility - } - }, - }, - -1, - ); - } // note that this is also in DIDView.vue private async register(contact: Contact) { @@ -1043,8 +1039,7 @@ export default class ContactsView extends Vue { ); if (regResult.success) { contact.registered = true; - const platformService = PlatformServiceFactory.getInstance(); - await platformService.dbExec( + await this.$dbExec( "UPDATE contacts SET registered = ? WHERE did = ?", [true, contact.did], );