|  | @ -41,14 +41,43 @@ | 
			
		
	
		
		
			
				
					|  |  |       </button> |  |  |       </button> | 
			
		
	
		
		
			
				
					|  |  |     </div> |  |  |     </div> | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |     <div class="w-full text-right"> |  |  |     <div class="flex justify-between"> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       <button |  |  |       <div class="w-full text-left"> | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         href="" |  |  |         <input | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         class="text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1 py-1 rounded-md" |  |  |           type="checkbox" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         @click="toggleShowContactAmounts()" |  |  |           v-if="!showGiveNumbers" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       > |  |  |           :checked="contactsSelected.length === contacts.length" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         {{ showGiveNumbers ? "Hide Given Hours" : "Show Given Hours" }} |  |  |           @click=" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       </button> |  |  |             contactsSelected.length === contacts.length | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |               ? (contactsSelected = []) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               : (contactsSelected = contacts.map((contact) => contact.did)) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           " | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           class="align-middle ml-2 h-6 w-6" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         /> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         <button | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           href="" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           class="text-md bg-gradient-to-b shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1 py-1 ml-2 rounded-md" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           :style=" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             contactsSelected.length > 0 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               ? 'background-image: linear-gradient(to bottom, #3b82f6, #1e40af);' | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               : 'background-image: linear-gradient(to bottom, #94a3b8, #374151);' | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           " | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           @click="copySelectedContacts()" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           v-if="!showGiveNumbers" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         > | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           Copy Selected Contacts | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         </button> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       </div> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       <div class="w-full text-right"> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         <button | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           href="" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           class="text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1 py-1 rounded-md" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           @click="toggleShowContactAmounts()" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         > | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           {{ showGiveNumbers ? "Hide Given Hours" : "Show Given Hours" }} | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         </button> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       </div> | 
			
		
	
		
		
			
				
					|  |  |     </div> |  |  |     </div> | 
			
		
	
		
		
			
				
					|  |  |     <div class="flex justify-between mt-1" v-if="showGiveNumbers"> |  |  |     <div class="flex justify-between mt-1" v-if="showGiveNumbers"> | 
			
		
	
		
		
			
				
					|  |  |       <div class="w-full text-right"> |  |  |       <div class="w-full text-right"> | 
			
		
	
	
		
		
			
				
					|  | @ -86,18 +115,37 @@ | 
			
		
	
		
		
			
				
					|  |  |     > |  |  |     > | 
			
		
	
		
		
			
				
					|  |  |       <li |  |  |       <li | 
			
		
	
		
		
			
				
					|  |  |         class="border-b border-slate-300 pt-1 pb-1" |  |  |         class="border-b border-slate-300 pt-1 pb-1" | 
			
		
	
		
		
			
				
					
					|  |  |         v-for="contact in contacts" |  |  |         v-for="contact in filteredContacts()" | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |         :key="contact.did" |  |  |         :key="contact.did" | 
			
		
	
		
		
			
				
					|  |  |       > |  |  |       > | 
			
		
	
		
		
			
				
					|  |  |         <div class="grow overflow-hidden"> |  |  |         <div class="grow overflow-hidden"> | 
			
		
	
		
		
			
				
					
					|  |  |           <h2 class="text-base font-semibold"> |  |  |           <div class="flex items-center"> | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |             <EntityIcon |  |  |             <EntityIcon | 
			
		
	
		
		
			
				
					|  |  |               :contact="contact" |  |  |               :contact="contact" | 
			
		
	
		
		
			
				
					|  |  |               :iconSize="24" |  |  |               :iconSize="24" | 
			
		
	
		
		
			
				
					|  |  |               class="inline-block align-text-bottom border border-slate-300 rounded cursor-pointer" |  |  |               class="inline-block align-text-bottom border border-slate-300 rounded cursor-pointer" | 
			
		
	
		
		
			
				
					|  |  |               @click="showLargeIdenticon = contact" |  |  |               @click="showLargeIdenticon = contact" | 
			
		
	
		
		
			
				
					|  |  |             /> |  |  |             /> | 
			
		
	
		
		
			
				
					
					|  |  |             {{ contact.name || AppString.NO_CONTACT_NAME }} |  |  | 
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |             <input | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               type="checkbox" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               v-if="!showGiveNumbers" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               :checked="contactsSelected.includes(contact.did)" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               @click=" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                 contactsSelected.includes(contact.did) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                   ? contactsSelected.splice( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                       contactsSelected.indexOf(contact.did), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                       1, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                     ) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |                   : contactsSelected.push(contact.did) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               " | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               class="ml-2 h-6 w-6" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             /> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             <h2 class="text-base font-semibold ml-2"> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |               {{ contact.name || AppString.NO_CONTACT_NAME }} | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             </h2> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |             <router-link |  |  |             <router-link | 
			
		
	
		
		
			
				
					|  |  |               :to="{ |  |  |               :to="{ | 
			
		
	
		
		
			
				
					|  |  |                 path: '/did/' + encodeURIComponent(contact.did), |  |  |                 path: '/did/' + encodeURIComponent(contact.did), | 
			
		
	
	
		
		
			
				
					|  | @ -106,7 +154,7 @@ | 
			
		
	
		
		
			
				
					|  |  |             > |  |  |             > | 
			
		
	
		
		
			
				
					|  |  |               <fa icon="circle-info" class="text-blue-500 ml-4" /> |  |  |               <fa icon="circle-info" class="text-blue-500 ml-4" /> | 
			
		
	
		
		
			
				
					|  |  |             </router-link> |  |  |             </router-link> | 
			
		
	
		
		
			
				
					
					|  |  |           </h2> |  |  |           </div> | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |           <div id="ContactActions" class="flex gap-1.5 mt-2"> |  |  |           <div id="ContactActions" class="flex gap-1.5 mt-2"> | 
			
		
	
		
		
			
				
					|  |  |             <div |  |  |             <div | 
			
		
	
		
		
			
				
					|  |  |               v-if="showGiveNumbers && contact.did != activeDid" |  |  |               v-if="showGiveNumbers && contact.did != activeDid" | 
			
		
	
	
		
		
			
				
					|  | @ -178,6 +226,22 @@ | 
			
		
	
		
		
			
				
					|  |  |     </ul> |  |  |     </ul> | 
			
		
	
		
		
			
				
					|  |  |     <p v-else>There are no contacts.</p> |  |  |     <p v-else>There are no contacts.</p> | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     <div class="w-full text-left"> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       <button | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         href="" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         class="text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1 py-1 rounded-md" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         :style=" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           contactsSelected.length > 0 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             ? 'background-image: linear-gradient(to bottom, #3b82f6, #1e40af);' | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             : 'background-image: linear-gradient(to bottom, #94a3b8, #374151);' | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         " | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         @click="copySelectedContacts()" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         v-if="!showGiveNumbers" | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       > | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         Copy Selected Contacts | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       </button> | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     </div> | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     <GiftedDialog ref="customGivenDialog" /> |  |  |     <GiftedDialog ref="customGivenDialog" /> | 
			
		
	
		
		
			
				
					|  |  |     <OfferDialog ref="customOfferDialog" /> |  |  |     <OfferDialog ref="customOfferDialog" /> | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  | @ -203,6 +267,7 @@ import { IndexableType } from "dexie"; | 
			
		
	
		
		
			
				
					|  |  | import * as R from "ramda"; |  |  | import * as R from "ramda"; | 
			
		
	
		
		
			
				
					|  |  | import { Component, Vue } from "vue-facing-decorator"; |  |  | import { Component, Vue } from "vue-facing-decorator"; | 
			
		
	
		
		
			
				
					|  |  | import { Router } from "vue-router"; |  |  | import { Router } from "vue-router"; | 
			
		
	
		
		
			
				
					|  |  |  |  |  | import { useClipboard } from "@vueuse/core"; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | import { AppString, NotificationIface } from "@/constants/app"; |  |  | import { AppString, NotificationIface } from "@/constants/app"; | 
			
		
	
		
		
			
				
					|  |  | import { db } from "@/db/index"; |  |  | import { db } from "@/db/index"; | 
			
		
	
	
		
		
			
				
					|  | @ -237,6 +302,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |   contactInput = ""; |  |  |   contactInput = ""; | 
			
		
	
		
		
			
				
					|  |  |   contactEdit: Contact | null = null; |  |  |   contactEdit: Contact | null = null; | 
			
		
	
		
		
			
				
					|  |  |   contactNewName = ""; |  |  |   contactNewName = ""; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   contactsSelected: Array<string> = []; | 
			
		
	
		
		
			
				
					|  |  |   // { "did:...": concatenated-descriptions } entry for each contact |  |  |   // { "did:...": concatenated-descriptions } entry for each contact | 
			
		
	
		
		
			
				
					|  |  |   givenByMeDescriptions: Record<string, string> = {}; |  |  |   givenByMeDescriptions: Record<string, string> = {}; | 
			
		
	
		
		
			
				
					|  |  |   // { "did:...": amount } entry for each contact |  |  |   // { "did:...": amount } entry for each contact | 
			
		
	
	
		
		
			
				
					|  | @ -262,7 +328,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |   AppString = AppString; |  |  |   AppString = AppString; | 
			
		
	
		
		
			
				
					|  |  |   libsUtil = libsUtil; |  |  |   libsUtil = libsUtil; | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   async created() { |  |  |   public async created() { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     await db.open(); |  |  |     await db.open(); | 
			
		
	
		
		
			
				
					|  |  |     const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings; |  |  |     const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings; | 
			
		
	
		
		
			
				
					|  |  |     this.activeDid = settings?.activeDid || ""; |  |  |     this.activeDid = settings?.activeDid || ""; | 
			
		
	
	
		
		
			
				
					|  | @ -285,7 +351,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     ); |  |  |     ); | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   danger(message: string, title: string = "Error", timeout = 5000) { |  |  |   private danger(message: string, title: string = "Error", timeout = 5000) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     this.$notify( |  |  |     this.$notify( | 
			
		
	
		
		
			
				
					|  |  |       { |  |  |       { | 
			
		
	
		
		
			
				
					|  |  |         group: "alert", |  |  |         group: "alert", | 
			
		
	
	
		
		
			
				
					|  | @ -297,7 +363,17 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     ); |  |  |     ); | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   async loadGives() { |  |  |   private filteredContacts() { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |     return this.showGiveNumbers | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       ? this.contactsSelected.length === 0 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         ? this.contacts | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         : this.contacts.filter((contact) => | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             this.contactsSelected.includes(contact.did), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           ) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       : this.contacts; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   private async loadGives() { | 
			
		
	
		
		
			
				
					|  |  |     if (!this.activeDid) { |  |  |     if (!this.activeDid) { | 
			
		
	
		
		
			
				
					|  |  |       return; |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
	
		
		
			
				
					|  | @ -404,19 +480,20 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   async onClickNewContact(): Promise<void> { |  |  |   private async onClickNewContact(): Promise<void> { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     if (!this.contactInput) { |  |  |     const contactInput = this.contactInput.trim(); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |     if (!contactInput) { | 
			
		
	
		
		
			
				
					|  |  |       this.danger("There was no contact info to add.", "No Contact"); |  |  |       this.danger("There was no contact info to add.", "No Contact"); | 
			
		
	
		
		
			
				
					|  |  |       return; |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |     if (this.contactInput.startsWith(CONTACT_URL_PREFIX)) { |  |  |     if (contactInput.startsWith(CONTACT_URL_PREFIX)) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       await this.addContactFromScan(this.contactInput); |  |  |       await this.addContactFromScan(contactInput); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |       return; |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |     if (this.contactInput.startsWith(CONTACT_CSV_HEADER)) { |  |  |     if (contactInput.startsWith(CONTACT_CSV_HEADER)) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       const lines = this.contactInput.split(/\n/); |  |  |       const lines = contactInput.split(/\n/); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |       const lineAdded = []; |  |  |       const lineAdded = []; | 
			
		
	
		
		
			
				
					|  |  |       for (const line of lines) { |  |  |       for (const line of lines) { | 
			
		
	
		
		
			
				
					|  |  |         if (!line.trim() || line.startsWith(CONTACT_CSV_HEADER)) { |  |  |         if (!line.trim() || line.startsWith(CONTACT_CSV_HEADER)) { | 
			
		
	
	
		
		
			
				
					|  | @ -448,44 +525,71 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |       return; |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |     let did = this.contactInput; |  |  |     if (contactInput.startsWith("did:")) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     let name, publicKeyInput, nextPublicKeyHashInput; |  |  |       let did = contactInput; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     const commaPos1 = this.contactInput.indexOf(","); |  |  |       let name, publicKeyInput, nextPublicKeyHashInput; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     if (commaPos1 > -1) { |  |  |       const commaPos1 = contactInput.indexOf(","); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       did = this.contactInput.substring(0, commaPos1).trim(); |  |  |       if (commaPos1 > -1) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       name = this.contactInput.substring(commaPos1 + 1).trim(); |  |  |         did = contactInput.substring(0, commaPos1).trim(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       const commaPos2 = this.contactInput.indexOf(",", commaPos1 + 1); |  |  |         name = contactInput.substring(commaPos1 + 1).trim(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       if (commaPos2 > -1) { |  |  |         const commaPos2 = contactInput.indexOf(",", commaPos1 + 1); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         name = this.contactInput.substring(commaPos1 + 1, commaPos2).trim(); |  |  |         if (commaPos2 > -1) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         publicKeyInput = this.contactInput.substring(commaPos2 + 1).trim(); |  |  |           name = contactInput.substring(commaPos1 + 1, commaPos2).trim(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         const commaPos3 = this.contactInput.indexOf(",", commaPos2 + 1); |  |  |           publicKeyInput = contactInput.substring(commaPos2 + 1).trim(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |         if (commaPos3 > -1) { |  |  |           const commaPos3 = contactInput.indexOf(",", commaPos2 + 1); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |           publicKeyInput = this.contactInput.substring(commaPos2 + 1, commaPos3).trim(); // eslint-disable-line prettier/prettier |  |  |           if (commaPos3 > -1) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |           nextPublicKeyHashInput = this.contactInput.substring(commaPos3 + 1).trim(); // eslint-disable-line prettier/prettier |  |  |             publicKeyInput = contactInput.substring(commaPos2 + 1, commaPos3).trim(); // eslint-disable-line prettier/prettier | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |             nextPublicKeyHashInput = contactInput.substring(commaPos3 + 1).trim(); // eslint-disable-line prettier/prettier | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           } | 
			
		
	
		
		
			
				
					|  |  |         } |  |  |         } | 
			
		
	
		
		
			
				
					|  |  |       } |  |  |       } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       // help with potential mistakes while this sharing requires copy-and-paste | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       let publicKeyBase64 = publicKeyInput; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       if (publicKeyBase64 && /^[0-9A-Fa-f]{66}$/i.test(publicKeyBase64)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         // it must be all hex (compressed public key), so convert | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         publicKeyBase64 = Buffer.from(publicKeyBase64, "hex").toString( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           "base64", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       let nextPubKeyHashB64 = nextPublicKeyHashInput; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       if (nextPubKeyHashB64 && /^[0-9A-Fa-f]{66}$/i.test(nextPubKeyHashB64)) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         // it must be all hex (compressed public key), so convert | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         nextPubKeyHashB64 = Buffer.from(nextPubKeyHashB64, "hex").toString("base64"); // eslint-disable-line prettier/prettier | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       const newContact = { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         did, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         name, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         publicKeyBase64, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         nextPubKeyHashB64: nextPubKeyHashB64, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       }; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       await this.addContact(newContact); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |     // help with potential mistakes while this sharing requires copy-and-paste |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     let publicKeyBase64 = publicKeyInput; |  |  |     if (contactInput.includes("[")) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     if (publicKeyBase64 && /^[0-9A-Fa-f]{66}$/i.test(publicKeyBase64)) { |  |  |       // assume there's a JSON array of contacts in the input | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       // it must be all hex (compressed public key), so convert |  |  |       const jsonContactInput = contactInput.substring( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       publicKeyBase64 = Buffer.from(publicKeyBase64, "hex").toString("base64"); |  |  |         contactInput.indexOf("["), | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     } |  |  |         contactInput.lastIndexOf("]") + 1, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     let nextPubKeyHashB64 = nextPublicKeyHashInput; |  |  |       ); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |     if (nextPubKeyHashB64 && /^[0-9A-Fa-f]{66}$/i.test(nextPubKeyHashB64)) { |  |  |       try { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       // it must be all hex (compressed public key), so convert |  |  |         const contacts = JSON.parse(jsonContactInput); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       nextPubKeyHashB64 = Buffer.from(nextPubKeyHashB64, "hex").toString("base64"); // eslint-disable-line prettier/prettier |  |  |         (this.$router as Router).push({ | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |           name: "contact-import", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           query: { contacts: JSON.stringify(contacts) }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } catch (e) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         this.danger("The input could not be parsed.", "Invalid Contact List"); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |     const newContact = { |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |       did, |  |  |     this.danger("No contact info was found in that input.", "No Contact Info"); | 
			
				
				
			
		
	
		
		
			
				
					|  |  |       name, |  |  |  | 
			
		
	
		
		
			
				
					|  |  |       publicKeyBase64, |  |  |  | 
			
		
	
		
		
			
				
					|  |  |       nextPubKeyHashB64: nextPubKeyHashB64, |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     }; |  |  |  | 
			
		
	
		
		
			
				
					|  |  |     await this.addContact(newContact); |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   async addContactFromEndorserMobileLine(line: string): Promise<IndexableType> { |  |  |   private async addContactFromEndorserMobileLine( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  |     line: string, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   ): Promise<IndexableType> { | 
			
		
	
		
		
			
				
					|  |  |     // Note that Endorser Mobile puts name first, then did, etc. |  |  |     // Note that Endorser Mobile puts name first, then did, etc. | 
			
		
	
		
		
			
				
					|  |  |     let name = line; |  |  |     let name = line; | 
			
		
	
		
		
			
				
					|  |  |     let did = ""; |  |  |     let did = ""; | 
			
		
	
	
		
		
			
				
					|  | @ -526,7 +630,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     return db.contacts.add(newContact); |  |  |     return db.contacts.add(newContact); | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   async addContactFromScan(url: string): Promise<void> { |  |  |   private async addContactFromScan(url: string): Promise<void> { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     const payload = getContactPayloadFromJwtUrl(url); |  |  |     const payload = getContactPayloadFromJwtUrl(url); | 
			
		
	
		
		
			
				
					|  |  |     if (!payload) { |  |  |     if (!payload) { | 
			
		
	
		
		
			
				
					|  |  |       this.$notify( |  |  |       this.$notify( | 
			
		
	
	
		
		
			
				
					|  | @ -551,7 +655,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   async addContact(newContact: Contact) { |  |  |   private async addContact(newContact: Contact) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     if (!newContact.did) { |  |  |     if (!newContact.did) { | 
			
		
	
		
		
			
				
					|  |  |       this.danger("Cannot add a contact without a DID.", "Incomplete Contact"); |  |  |       this.danger("Cannot add a contact without a DID.", "Incomplete Contact"); | 
			
		
	
		
		
			
				
					|  |  |       return; |  |  |       return; | 
			
		
	
	
		
		
			
				
					|  | @ -641,7 +745,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |   // note that this is also in DIDView.vue |  |  |   // note that this is also in DIDView.vue | 
			
		
	
		
		
			
				
					
					|  |  |   async confirmSetVisibility(contact: Contact, visibility: boolean) { |  |  |   private async confirmSetVisibility(contact: Contact, visibility: boolean) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     const visibilityPrompt = visibility |  |  |     const visibilityPrompt = visibility | 
			
		
	
		
		
			
				
					|  |  |       ? "Are you sure you want to make your activity visible to them?" |  |  |       ? "Are you sure you want to make your activity visible to them?" | 
			
		
	
		
		
			
				
					|  |  |       : "Are you sure you want to hide all your activity from them?"; |  |  |       : "Are you sure you want to hide all your activity from them?"; | 
			
		
	
	
		
		
			
				
					|  | @ -663,7 +767,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |   // note that this is also in DIDView.vue |  |  |   // note that this is also in DIDView.vue | 
			
		
	
		
		
			
				
					
					|  |  |   async register(contact: Contact) { |  |  |   private async register(contact: Contact) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     this.$notify({ group: "alert", type: "toast", title: "Sent..." }, 1000); |  |  |     this.$notify({ group: "alert", type: "toast", title: "Sent..." }, 1000); | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |     try { |  |  |     try { | 
			
		
	
	
		
		
			
				
					|  | @ -729,7 +833,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |   // note that this is also in DIDView.vue |  |  |   // note that this is also in DIDView.vue | 
			
		
	
		
		
			
				
					
					|  |  |   async setVisibility( |  |  |   private async setVisibility( | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     contact: Contact, |  |  |     contact: Contact, | 
			
		
	
		
		
			
				
					|  |  |     visibility: boolean, |  |  |     visibility: boolean, | 
			
		
	
		
		
			
				
					|  |  |     showSuccessAlert: boolean, |  |  |     showSuccessAlert: boolean, | 
			
		
	
	
		
		
			
				
					|  | @ -779,7 +883,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |   // note that this is also in DIDView.vue |  |  |   // note that this is also in DIDView.vue | 
			
		
	
		
		
			
				
					
					|  |  |   async checkVisibility(contact: Contact) { |  |  |   private async checkVisibility(contact: Contact) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     const url = |  |  |     const url = | 
			
		
	
		
		
			
				
					|  |  |       this.apiServer + |  |  |       this.apiServer + | 
			
		
	
		
		
			
				
					|  |  |       "/api/report/canDidExplicitlySeeMe?did=" + |  |  |       "/api/report/canDidExplicitlySeeMe?did=" + | 
			
		
	
	
		
		
			
				
					|  | @ -846,7 +950,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   confirmShowGiftedDialog(giverDid: string, recipientDid: string) { |  |  |   private confirmShowGiftedDialog(giverDid: string, recipientDid: string) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     // if they have unconfirmed amounts, ask to confirm those |  |  |     // if they have unconfirmed amounts, ask to confirm those | 
			
		
	
		
		
			
				
					|  |  |     if ( |  |  |     if ( | 
			
		
	
		
		
			
				
					|  |  |       recipientDid === this.activeDid && |  |  |       recipientDid === this.activeDid && | 
			
		
	
	
		
		
			
				
					|  | @ -936,7 +1040,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     ); |  |  |     ); | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   public async toggleShowContactAmounts() { |  |  |   private async toggleShowContactAmounts() { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     const newShowValue = !this.showGiveNumbers; |  |  |     const newShowValue = !this.showGiveNumbers; | 
			
		
	
		
		
			
				
					|  |  |     try { |  |  |     try { | 
			
		
	
		
		
			
				
					|  |  |       await db.open(); |  |  |       await db.open(); | 
			
		
	
	
		
		
			
				
					|  | @ -972,7 +1076,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |       this.loadGives(); |  |  |       this.loadGives(); | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |   public toggleShowGiveTotals() { |  |  |   private toggleShowGiveTotals() { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     if (this.showGiveTotals) { |  |  |     if (this.showGiveTotals) { | 
			
		
	
		
		
			
				
					|  |  |       this.showGiveTotals = false; |  |  |       this.showGiveTotals = false; | 
			
		
	
		
		
			
				
					|  |  |       this.showGiveConfirmed = true; |  |  |       this.showGiveConfirmed = true; | 
			
		
	
	
		
		
			
				
					|  | @ -985,7 +1089,7 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |     } |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |   public showGiveAmountsClassNames() { |  |  |   private showGiveAmountsClassNames() { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |     return { |  |  |     return { | 
			
		
	
		
		
			
				
					|  |  |       "from-slate-400": this.showGiveTotals, |  |  |       "from-slate-400": this.showGiveTotals, | 
			
		
	
		
		
			
				
					|  |  |       "to-slate-700": this.showGiveTotals, |  |  |       "to-slate-700": this.showGiveTotals, | 
			
		
	
	
		
		
			
				
					|  | @ -995,5 +1099,31 @@ export default class ContactsView extends Vue { | 
			
		
	
		
		
			
				
					|  |  |       "to-yellow-700": !this.showGiveTotals && !this.showGiveConfirmed, |  |  |       "to-yellow-700": !this.showGiveTotals && !this.showGiveConfirmed, | 
			
		
	
		
		
			
				
					|  |  |     }; |  |  |     }; | 
			
		
	
		
		
			
				
					|  |  |   } |  |  |   } | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   private copySelectedContacts() { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     if (this.contactsSelected.length === 0) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       this.danger("You must select contacts to copy."); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       return; | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     const selectedContacts = this.contacts.filter((c) => | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       this.contactsSelected.includes(c.did), | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     ); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     const message = | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       "To add contacts, paste this into the box on the 'People' screen.\n\n" + | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       JSON.stringify(selectedContacts, null, 2); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |     useClipboard() | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       .copy(message) | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       .then(() => { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         this.$notify( | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           { | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             group: "alert", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             type: "info", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             title: "Copied", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |             text: "Those contacts were copied to the clipboard. Have them paste it in the box on their 'People' screen.", | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           }, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |           5000, | 
			
		
	
		
		
			
				
					|  |  |  |  |  |         ); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |       }); | 
			
		
	
		
		
			
				
					|  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					|  |  | } |  |  | } | 
			
		
	
		
		
			
				
					|  |  | </script> |  |  | </script> | 
			
		
	
	
		
		
			
				
					|  | 
 |