|  |  | @ -79,16 +79,25 @@ import { Component, Vue } from "vue-facing-decorator"; | 
			
		
	
		
			
				
					|  |  |  | import { QrcodeStream } from "vue-qrcode-reader"; | 
			
		
	
		
			
				
					|  |  |  | import { useClipboard } from "@vueuse/core"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | import QuickNav from "@/components/QuickNav.vue"; | 
			
		
	
		
			
				
					|  |  |  | import { NotificationIface } from "@/constants/app"; | 
			
		
	
		
			
				
					|  |  |  | import { accountsDB, db } from "@/db/index"; | 
			
		
	
		
			
				
					|  |  |  | import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { deriveAddress, nextDerivationPath, SimpleSigner } from "@/libs/crypto"; | 
			
		
	
		
			
				
					|  |  |  | import QuickNav from "@/components/QuickNav.vue"; | 
			
		
	
		
			
				
					|  |  |  | import { Account } from "@/db/tables/accounts"; | 
			
		
	
		
			
				
					|  |  |  | import { Contact } from "@/db/tables/contacts"; | 
			
		
	
		
			
				
					|  |  |  | import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   deriveAddress, | 
			
		
	
		
			
				
					|  |  |  |   getContactPayloadFromJwtUrl, | 
			
		
	
		
			
				
					|  |  |  |   nextDerivationPath, | 
			
		
	
		
			
				
					|  |  |  |   SimpleSigner, | 
			
		
	
		
			
				
					|  |  |  | } from "@/libs/crypto"; | 
			
		
	
		
			
				
					|  |  |  | import { | 
			
		
	
		
			
				
					|  |  |  |   CONTACT_URL_PREFIX, | 
			
		
	
		
			
				
					|  |  |  |   ENDORSER_JWT_URL_LOCATION, | 
			
		
	
		
			
				
					|  |  |  |   isDid, | 
			
		
	
		
			
				
					|  |  |  |   setVisibilityUtil, | 
			
		
	
		
			
				
					|  |  |  | } from "@/libs/endorserServer"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | import { Buffer } from "buffer/"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | @Component({ | 
			
		
	
	
		
			
				
					|  |  | @ -106,29 +115,12 @@ export default class ContactQRScanShow extends Vue { | 
			
		
	
		
			
				
					|  |  |  |   givenName = ""; | 
			
		
	
		
			
				
					|  |  |  |   qrValue = ""; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public async getIdentity(activeDid: string) { | 
			
		
	
		
			
				
					|  |  |  |     await accountsDB.open(); | 
			
		
	
		
			
				
					|  |  |  |     const accounts = await accountsDB.accounts.toArray(); | 
			
		
	
		
			
				
					|  |  |  |     const account: Account | undefined = R.find( | 
			
		
	
		
			
				
					|  |  |  |       (acc) => acc.did === activeDid, | 
			
		
	
		
			
				
					|  |  |  |       accounts, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     const identity = JSON.parse(account?.identity || "null"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (!identity) { | 
			
		
	
		
			
				
					|  |  |  |       throw new Error( | 
			
		
	
		
			
				
					|  |  |  |         "Attempted to show contact info with no identifier available.", | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |     return identity; | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async created() { | 
			
		
	
		
			
				
					|  |  |  |     await db.open(); | 
			
		
	
		
			
				
					|  |  |  |     const settings = await db.settings.get(MASTER_SETTINGS_KEY); | 
			
		
	
		
			
				
					|  |  |  |     this.activeDid = settings?.activeDid || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.apiServer = settings?.apiServer || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.givenName = settings?.firstName || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.activeDid = (settings?.activeDid as string) || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.apiServer = (settings?.apiServer as string) || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.givenName = (settings?.firstName as string) || ""; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     await accountsDB.open(); | 
			
		
	
		
			
				
					|  |  |  |     const accounts = await accountsDB.accounts.toArray(); | 
			
		
	
	
		
			
				
					|  |  | @ -172,25 +164,109 @@ export default class ContactQRScanShow extends Vue { | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   danger(message: string, title: string = "Error", timeout = 5000) { | 
			
		
	
		
			
				
					|  |  |  |     this.$notify( | 
			
		
	
		
			
				
					|  |  |  |       { | 
			
		
	
		
			
				
					|  |  |  |         group: "alert", | 
			
		
	
		
			
				
					|  |  |  |         type: "danger", | 
			
		
	
		
			
				
					|  |  |  |         title: title, | 
			
		
	
		
			
				
					|  |  |  |         text: message, | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
		
			
				
					|  |  |  |       timeout, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public async getIdentity(activeDid: string) { | 
			
		
	
		
			
				
					|  |  |  |     await accountsDB.open(); | 
			
		
	
		
			
				
					|  |  |  |     const accounts = await accountsDB.accounts.toArray(); | 
			
		
	
		
			
				
					|  |  |  |     const account: Account | undefined = R.find( | 
			
		
	
		
			
				
					|  |  |  |       (acc) => acc.did === activeDid, | 
			
		
	
		
			
				
					|  |  |  |       accounts, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     const identity = JSON.parse((account?.identity as string) || "null"); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     if (!identity) { | 
			
		
	
		
			
				
					|  |  |  |       throw new Error( | 
			
		
	
		
			
				
					|  |  |  |         "Attempted to show contact info with no identifier available.", | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |     return identity; | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   /** | 
			
		
	
		
			
				
					|  |  |  |    * | 
			
		
	
		
			
				
					|  |  |  |    * @param content is the result of a QR scan, an array with one item with a rawValue property | 
			
		
	
		
			
				
					|  |  |  |    */ | 
			
		
	
		
			
				
					|  |  |  |   // Unfortunately, there are not typescript definitions for the qrcode-stream component yet. | 
			
		
	
		
			
				
					|  |  |  |   // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
			
		
	
		
			
				
					|  |  |  |   onScanDetect(content: any) { | 
			
		
	
		
			
				
					|  |  |  |   async onScanDetect(content: any) { | 
			
		
	
		
			
				
					|  |  |  |     const url = content[0]?.rawValue; | 
			
		
	
		
			
				
					|  |  |  |     if (url) { | 
			
		
	
		
			
				
					|  |  |  |       let newContact: Contact; | 
			
		
	
		
			
				
					|  |  |  |       try { | 
			
		
	
		
			
				
					|  |  |  |         localStorage.setItem("contactEndorserUrl", url); | 
			
		
	
		
			
				
					|  |  |  |         this.$router.push({ name: "contacts" }); | 
			
		
	
		
			
				
					|  |  |  |         const payload = getContactPayloadFromJwtUrl(url); | 
			
		
	
		
			
				
					|  |  |  |         if (!payload) { | 
			
		
	
		
			
				
					|  |  |  |           this.$notify( | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |               group: "alert", | 
			
		
	
		
			
				
					|  |  |  |               type: "danger", | 
			
		
	
		
			
				
					|  |  |  |               title: "No Contact Info", | 
			
		
	
		
			
				
					|  |  |  |               text: "The contact info could not be parsed.", | 
			
		
	
		
			
				
					|  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |             3000, | 
			
		
	
		
			
				
					|  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |           return; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         newContact = { | 
			
		
	
		
			
				
					|  |  |  |           did: payload.iss as string, | 
			
		
	
		
			
				
					|  |  |  |           name: payload.own.name, | 
			
		
	
		
			
				
					|  |  |  |           nextPubKeyHashB64: payload.own.nextPublicEncKeyHash, | 
			
		
	
		
			
				
					|  |  |  |           profileImageUrl: payload.own.profileImageUrl, | 
			
		
	
		
			
				
					|  |  |  |           publicKeyBase64: payload.own.publicEncKey, | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |         if (!newContact.did) { | 
			
		
	
		
			
				
					|  |  |  |           this.danger("There is no DID.", "Incomplete Contact"); | 
			
		
	
		
			
				
					|  |  |  |           return; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         if (!isDid(newContact.did)) { | 
			
		
	
		
			
				
					|  |  |  |           this.danger("The DID must begin with 'did:'", "Invalid DID"); | 
			
		
	
		
			
				
					|  |  |  |           return; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |       } catch (e) { | 
			
		
	
		
			
				
					|  |  |  |         console.error("Error parsing QR info:", e); | 
			
		
	
		
			
				
					|  |  |  |         this.danger("Could not parse the QR info.", "Read Error"); | 
			
		
	
		
			
				
					|  |  |  |         return; | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       try { | 
			
		
	
		
			
				
					|  |  |  |         await db.open(); | 
			
		
	
		
			
				
					|  |  |  |         await db.contacts.add(newContact); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |         let addedMessage; | 
			
		
	
		
			
				
					|  |  |  |         if (this.activeDid) { | 
			
		
	
		
			
				
					|  |  |  |           await this.setVisibility(newContact, true); | 
			
		
	
		
			
				
					|  |  |  |           addedMessage = | 
			
		
	
		
			
				
					|  |  |  |             "They were added, and your activity is visible to them."; | 
			
		
	
		
			
				
					|  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |           addedMessage = "They were added."; | 
			
		
	
		
			
				
					|  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |         this.$notify( | 
			
		
	
		
			
				
					|  |  |  |           { | 
			
		
	
		
			
				
					|  |  |  |             group: "alert", | 
			
		
	
		
			
				
					|  |  |  |             type: "success", | 
			
		
	
		
			
				
					|  |  |  |             title: "Contact Added", | 
			
		
	
		
			
				
					|  |  |  |             text: addedMessage, | 
			
		
	
		
			
				
					|  |  |  |           }, | 
			
		
	
		
			
				
					|  |  |  |           3000, | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |       } catch (e) { | 
			
		
	
		
			
				
					|  |  |  |         console.error("Error saving contact info:", e); | 
			
		
	
		
			
				
					|  |  |  |         this.$notify( | 
			
		
	
		
			
				
					|  |  |  |           { | 
			
		
	
		
			
				
					|  |  |  |             group: "alert", | 
			
		
	
		
			
				
					|  |  |  |             type: "warning", | 
			
		
	
		
			
				
					|  |  |  |             title: "Invalid Contact QR Code", | 
			
		
	
		
			
				
					|  |  |  |             text: "The QR code isn't in the right format.", | 
			
		
	
		
			
				
					|  |  |  |             type: "danger", | 
			
		
	
		
			
				
					|  |  |  |             title: "Contact Error", | 
			
		
	
		
			
				
					|  |  |  |             text: "Could not save contact info. Check if it already exists.", | 
			
		
	
		
			
				
					|  |  |  |           }, | 
			
		
	
		
			
				
					|  |  |  |           5000, | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
	
		
			
				
					|  |  | @ -199,7 +275,7 @@ export default class ContactQRScanShow extends Vue { | 
			
		
	
		
			
				
					|  |  |  |       this.$notify( | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |           group: "alert", | 
			
		
	
		
			
				
					|  |  |  |           type: "warning", | 
			
		
	
		
			
				
					|  |  |  |           type: "danger", | 
			
		
	
		
			
				
					|  |  |  |           title: "Invalid Contact QR Code", | 
			
		
	
		
			
				
					|  |  |  |           text: "No QR code detected with contact information.", | 
			
		
	
		
			
				
					|  |  |  |         }, | 
			
		
	
	
		
			
				
					|  |  | @ -208,13 +284,29 @@ export default class ContactQRScanShow extends Vue { | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   async setVisibility(contact: Contact, visibility: boolean) { | 
			
		
	
		
			
				
					|  |  |  |     const result = await setVisibilityUtil( | 
			
		
	
		
			
				
					|  |  |  |       this.activeDid, | 
			
		
	
		
			
				
					|  |  |  |       this.apiServer, | 
			
		
	
		
			
				
					|  |  |  |       this.axios, | 
			
		
	
		
			
				
					|  |  |  |       db, | 
			
		
	
		
			
				
					|  |  |  |       contact, | 
			
		
	
		
			
				
					|  |  |  |       visibility, | 
			
		
	
		
			
				
					|  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |     if (result.error) { | 
			
		
	
		
			
				
					|  |  |  |       this.danger(result.error as string, "Error Setting Visibility"); | 
			
		
	
		
			
				
					|  |  |  |     } else if (!result.success) { | 
			
		
	
		
			
				
					|  |  |  |       console.error("Got strange result from setting visibility:", result); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   // eslint-disable-next-line @typescript-eslint/no-explicit-any | 
			
		
	
		
			
				
					|  |  |  |   onScanError(error: any) { | 
			
		
	
		
			
				
					|  |  |  |     console.error("Scan was invalid:", error); | 
			
		
	
		
			
				
					|  |  |  |     this.$notify( | 
			
		
	
		
			
				
					|  |  |  |       { | 
			
		
	
		
			
				
					|  |  |  |         group: "alert", | 
			
		
	
		
			
				
					|  |  |  |         type: "warning", | 
			
		
	
		
			
				
					|  |  |  |         type: "danger", | 
			
		
	
		
			
				
					|  |  |  |         title: "Invalid Scan", | 
			
		
	
		
			
				
					|  |  |  |         text: "The scan was invalid.", | 
			
		
	
		
			
				
					|  |  |  |       }, | 
			
		
	
	
		
			
				
					|  |  | @ -223,6 +315,7 @@ export default class ContactQRScanShow extends Vue { | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   onCopyToClipboard() { | 
			
		
	
		
			
				
					|  |  |  |     //this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing | 
			
		
	
		
			
				
					|  |  |  |     useClipboard() | 
			
		
	
		
			
				
					|  |  |  |       .copy(this.qrValue) | 
			
		
	
		
			
				
					|  |  |  |       .then(() => { | 
			
		
	
	
		
			
				
					|  |  | 
 |