|  |  | @ -62,6 +62,42 @@ | 
			
		
	
		
			
				
					|  |  |  |       </ul> | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <div v-if="isLocalActive"> | 
			
		
	
		
			
				
					|  |  |  |       <div v-if="!isChoosingSearchBox"> | 
			
		
	
		
			
				
					|  |  |  |         <button | 
			
		
	
		
			
				
					|  |  |  |           class="ml-2 px-4 py-2 rounded-md bg-blue-200 text-blue-500" | 
			
		
	
		
			
				
					|  |  |  |           @click="isChoosingSearchBox = true" | 
			
		
	
		
			
				
					|  |  |  |         > | 
			
		
	
		
			
				
					|  |  |  |           Select a {{ searchBox ? "Different" : "" }} Location for Nearby Search | 
			
		
	
		
			
				
					|  |  |  |         </button> | 
			
		
	
		
			
				
					|  |  |  |       </div> | 
			
		
	
		
			
				
					|  |  |  |       <div v-else> | 
			
		
	
		
			
				
					|  |  |  |         <button v-if="!searchBox && !isMarkerSet" class="m-4 px-4 py-2"> | 
			
		
	
		
			
				
					|  |  |  |           Choose Location Below for Nearby Search | 
			
		
	
		
			
				
					|  |  |  |         </button> | 
			
		
	
		
			
				
					|  |  |  |         <button | 
			
		
	
		
			
				
					|  |  |  |           v-if="!searchBox && isMarkerSet" | 
			
		
	
		
			
				
					|  |  |  |           class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500" | 
			
		
	
		
			
				
					|  |  |  |           @click="storeSearchBox" | 
			
		
	
		
			
				
					|  |  |  |         > | 
			
		
	
		
			
				
					|  |  |  |           Save Location for Nearby Search | 
			
		
	
		
			
				
					|  |  |  |         </button> | 
			
		
	
		
			
				
					|  |  |  |         <button | 
			
		
	
		
			
				
					|  |  |  |           v-if="searchBox" | 
			
		
	
		
			
				
					|  |  |  |           class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500" | 
			
		
	
		
			
				
					|  |  |  |           @click="forgetSearchBox" | 
			
		
	
		
			
				
					|  |  |  |         > | 
			
		
	
		
			
				
					|  |  |  |           Delete Location for Nearby Search | 
			
		
	
		
			
				
					|  |  |  |         </button> | 
			
		
	
		
			
				
					|  |  |  |         <button | 
			
		
	
		
			
				
					|  |  |  |           class="ml-2 px-4 py-2 rounded-md bg-blue-200 text-blue-500" | 
			
		
	
		
			
				
					|  |  |  |           @click="cancelSearchBoxSelect" | 
			
		
	
		
			
				
					|  |  |  |         > | 
			
		
	
		
			
				
					|  |  |  |           Cancel | 
			
		
	
		
			
				
					|  |  |  |         </button> | 
			
		
	
		
			
				
					|  |  |  |       </div> | 
			
		
	
		
			
				
					|  |  |  |     </div> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <!-- Loading Animation --> | 
			
		
	
		
			
				
					|  |  |  |     <div | 
			
		
	
		
			
				
					|  |  |  |       class="fixed left-6 bottom-24 text-center text-4xl leading-none bg-slate-400 text-white w-14 py-2.5 rounded-full" | 
			
		
	
	
		
			
				
					|  |  | @ -104,20 +140,12 @@ | 
			
		
	
		
			
				
					|  |  |  |       </ul> | 
			
		
	
		
			
				
					|  |  |  |     </InfiniteScroll> | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     <div | 
			
		
	
		
			
				
					|  |  |  |       v-if="isLocalActive && searchBoxes.length === 0" | 
			
		
	
		
			
				
					|  |  |  |       style="height: 600px; width: 800px" | 
			
		
	
		
			
				
					|  |  |  |     > | 
			
		
	
		
			
				
					|  |  |  |     <div v-if="isChoosingSearchBox" style="height: 600px; width: 800px"> | 
			
		
	
		
			
				
					|  |  |  |       <l-map | 
			
		
	
		
			
				
					|  |  |  |         ref="map" | 
			
		
	
		
			
				
					|  |  |  |         :center="[localCenterLat, localCenterLong]" | 
			
		
	
		
			
				
					|  |  |  |         v-model:zoom="localZoom" | 
			
		
	
		
			
				
					|  |  |  |         :center="[0, 0]" | 
			
		
	
		
			
				
					|  |  |  |         @click=" | 
			
		
	
		
			
				
					|  |  |  |           (event) => { | 
			
		
	
		
			
				
					|  |  |  |             localLatitude = event.latlng.lat; | 
			
		
	
		
			
				
					|  |  |  |             localLongitude = event.latlng.lng; | 
			
		
	
		
			
				
					|  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |         " | 
			
		
	
		
			
				
					|  |  |  |         @click="setMapPoint" | 
			
		
	
		
			
				
					|  |  |  |       > | 
			
		
	
		
			
				
					|  |  |  |         <l-tile-layer | 
			
		
	
		
			
				
					|  |  |  |           url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" | 
			
		
	
	
		
			
				
					|  |  | @ -125,15 +153,16 @@ | 
			
		
	
		
			
				
					|  |  |  |           name="OpenStreetMap" | 
			
		
	
		
			
				
					|  |  |  |         /> | 
			
		
	
		
			
				
					|  |  |  |         <l-marker | 
			
		
	
		
			
				
					|  |  |  |           v-if="localLatitude || localLongitude" | 
			
		
	
		
			
				
					|  |  |  |           :lat-lng="[localLatitude, localLongitude]" | 
			
		
	
		
			
				
					|  |  |  |           v-if="isMarkerSet" | 
			
		
	
		
			
				
					|  |  |  |           :lat-lng="[localCenterLat, localCenterLong]" | 
			
		
	
		
			
				
					|  |  |  |           @click="resetLatLong()" | 
			
		
	
		
			
				
					|  |  |  |         /> | 
			
		
	
		
			
				
					|  |  |  |         <l-rectangle | 
			
		
	
		
			
				
					|  |  |  |           v-if="isMarkerSet" | 
			
		
	
		
			
				
					|  |  |  |           :bounds="[ | 
			
		
	
		
			
				
					|  |  |  |             [localLatitude - 0.1, localLongitude - 0.1], | 
			
		
	
		
			
				
					|  |  |  |             [localLatitude + 0.1, localLongitude + 0.1], | 
			
		
	
		
			
				
					|  |  |  |             [localCenterLat - localLatDiff, localCenterLong - localLongDiff], | 
			
		
	
		
			
				
					|  |  |  |             [localCenterLat + localLatDiff, localCenterLong + localLongDiff], | 
			
		
	
		
			
				
					|  |  |  |           ]" | 
			
		
	
		
			
				
					|  |  |  |           :color="ff7800" | 
			
		
	
		
			
				
					|  |  |  |           :weight="1" | 
			
		
	
		
			
				
					|  |  |  |         /> | 
			
		
	
		
			
				
					|  |  |  |       </l-map> | 
			
		
	
	
		
			
				
					|  |  | @ -155,14 +184,18 @@ import { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | import { accountsDB, db } from "@/db"; | 
			
		
	
		
			
				
					|  |  |  | import { Contact } from "@/db/tables/contacts"; | 
			
		
	
		
			
				
					|  |  |  | import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { BoundingBox, MASTER_SETTINGS_KEY } from "@/db/tables/settings"; | 
			
		
	
		
			
				
					|  |  |  | import { accessToken } from "@/libs/crypto"; | 
			
		
	
		
			
				
					|  |  |  | import { didInfo } from "@/libs/endorserServer"; | 
			
		
	
		
			
				
					|  |  |  | import { didInfo, ProjectData } from "@/libs/endorserServer"; | 
			
		
	
		
			
				
					|  |  |  | import AlertMessage from "@/components/AlertMessage"; | 
			
		
	
		
			
				
					|  |  |  | import QuickNav from "@/components/QuickNav"; | 
			
		
	
		
			
				
					|  |  |  | import InfiniteScroll from "@/components/InfiniteScroll"; | 
			
		
	
		
			
				
					|  |  |  | import EntityIcon from "@/components/EntityIcon"; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | const DEFAULT_LAT_LONG_DIFF = 0.01; | 
			
		
	
		
			
				
					|  |  |  | const WORLD_ZOOM = 2; | 
			
		
	
		
			
				
					|  |  |  | const DEFAULT_ZOOM = 2; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | @Component({ | 
			
		
	
		
			
				
					|  |  |  |   components: { | 
			
		
	
		
			
				
					|  |  |  |     LRectangle, | 
			
		
	
	
		
			
				
					|  |  | @ -184,14 +217,18 @@ export default class DiscoverView extends Vue { | 
			
		
	
		
			
				
					|  |  |  |   alertMessage = ""; | 
			
		
	
		
			
				
					|  |  |  |   alertTitle = ""; | 
			
		
	
		
			
				
					|  |  |  |   projects: ProjectData[] = []; | 
			
		
	
		
			
				
					|  |  |  |   isChoosingSearchBox = false; | 
			
		
	
		
			
				
					|  |  |  |   isLocalActive = true; | 
			
		
	
		
			
				
					|  |  |  |   isRemoteActive = false; | 
			
		
	
		
			
				
					|  |  |  |   isMarkerSet = false; | 
			
		
	
		
			
				
					|  |  |  |   localCenterLat = 0; | 
			
		
	
		
			
				
					|  |  |  |   localCenterLong = 0; | 
			
		
	
		
			
				
					|  |  |  |   localLatDiff = DEFAULT_LAT_LONG_DIFF; | 
			
		
	
		
			
				
					|  |  |  |   localLongDiff = DEFAULT_LAT_LONG_DIFF; | 
			
		
	
		
			
				
					|  |  |  |   localCount = 0; | 
			
		
	
		
			
				
					|  |  |  |   localLatitude = 0; | 
			
		
	
		
			
				
					|  |  |  |   localLongitude = 0; | 
			
		
	
		
			
				
					|  |  |  |   localZoom = 2; | 
			
		
	
		
			
				
					|  |  |  |   localZoom = DEFAULT_ZOOM; | 
			
		
	
		
			
				
					|  |  |  |   remoteCount = 0; | 
			
		
	
		
			
				
					|  |  |  |   searchBoxes = []; | 
			
		
	
		
			
				
					|  |  |  |   searchBox: BoundingBox | null = null; | 
			
		
	
		
			
				
					|  |  |  |   isLoading = false; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   // make this function available to the Vue template | 
			
		
	
	
		
			
				
					|  |  | @ -202,7 +239,8 @@ export default class DiscoverView extends Vue { | 
			
		
	
		
			
				
					|  |  |  |     const settings = await db.settings.get(MASTER_SETTINGS_KEY); | 
			
		
	
		
			
				
					|  |  |  |     this.activeDid = settings?.activeDid || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.apiServer = settings?.apiServer || ""; | 
			
		
	
		
			
				
					|  |  |  |     this.searchBoxes = settings?.searchBoxes || []; | 
			
		
	
		
			
				
					|  |  |  |     this.searchBox = settings?.searchBoxes?.[0]; | 
			
		
	
		
			
				
					|  |  |  |     this.resetLatLong(); | 
			
		
	
		
			
				
					|  |  |  |     this.allContacts = await db.contacts.toArray(); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     await accountsDB.open(); | 
			
		
	
	
		
			
				
					|  |  | @ -399,6 +437,130 @@ export default class DiscoverView extends Vue { | 
			
		
	
		
			
				
					|  |  |  |     this.$router.push(route); | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   setMapPoint(event) { | 
			
		
	
		
			
				
					|  |  |  |     if (this.isMarkerSet) { | 
			
		
	
		
			
				
					|  |  |  |       this.localLatDiff = Math.abs(event.latlng.lat - this.localCenterLat); | 
			
		
	
		
			
				
					|  |  |  |       this.localLongDiff = Math.abs(event.latlng.lng - this.localCenterLong); | 
			
		
	
		
			
				
					|  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  |       // marker is not set | 
			
		
	
		
			
				
					|  |  |  |       this.localCenterLat = event.latlng.lat; | 
			
		
	
		
			
				
					|  |  |  |       this.localCenterLong = event.latlng.lng; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |       let latDiff = DEFAULT_LAT_LONG_DIFF; | 
			
		
	
		
			
				
					|  |  |  |       let longDiff = DEFAULT_LAT_LONG_DIFF; | 
			
		
	
		
			
				
					|  |  |  |       // Guess at a size for the bounding box. | 
			
		
	
		
			
				
					|  |  |  |       // This doesn't seem like the right approach but it's the only way I can find to get the screen bounds. | 
			
		
	
		
			
				
					|  |  |  |       const bounds = event.target.boxZoom?._map?.getBounds(); | 
			
		
	
		
			
				
					|  |  |  |       if (bounds) { | 
			
		
	
		
			
				
					|  |  |  |         latDiff = Math.abs(bounds._northEast.lat - bounds._southWest.lat) / 8; | 
			
		
	
		
			
				
					|  |  |  |         longDiff = Math.abs(bounds._northEast.lng - bounds._southWest.lng) / 8; | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |       this.localLatDiff = latDiff; | 
			
		
	
		
			
				
					|  |  |  |       this.localLongDiff = longDiff; | 
			
		
	
		
			
				
					|  |  |  |       this.isMarkerSet = true; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public resetLatLong() { | 
			
		
	
		
			
				
					|  |  |  |     if (this.searchBox) { | 
			
		
	
		
			
				
					|  |  |  |       this.localCenterLat = (this.searchBox.maxLat + this.searchBox.minLat) / 2; | 
			
		
	
		
			
				
					|  |  |  |       this.localCenterLong = | 
			
		
	
		
			
				
					|  |  |  |         (this.searchBox.eastLong + this.searchBox.westLong) / 2; | 
			
		
	
		
			
				
					|  |  |  |       this.localLatDiff = (this.searchBox.maxLat - this.searchBox.minLat) / 2; | 
			
		
	
		
			
				
					|  |  |  |       this.localLongDiff = | 
			
		
	
		
			
				
					|  |  |  |         (this.searchBox.eastLong - this.searchBox.westLong) / 2; | 
			
		
	
		
			
				
					|  |  |  |       this.localZoom = WORLD_ZOOM; | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |     // otherwise, don't change their viewport | 
			
		
	
		
			
				
					|  |  |  |     this.isMarkerSet = false; | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public async storeSearchBox() { | 
			
		
	
		
			
				
					|  |  |  |     if (this.localCenterLong || this.localCenterLat) { | 
			
		
	
		
			
				
					|  |  |  |       try { | 
			
		
	
		
			
				
					|  |  |  |         await db.open(); | 
			
		
	
		
			
				
					|  |  |  |         db.settings.update(MASTER_SETTINGS_KEY, { | 
			
		
	
		
			
				
					|  |  |  |           searchBoxes: [ | 
			
		
	
		
			
				
					|  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |               name: "Local", | 
			
		
	
		
			
				
					|  |  |  |               bbox: { | 
			
		
	
		
			
				
					|  |  |  |                 eastLong: this.localCenterLong + this.localLongDiff, | 
			
		
	
		
			
				
					|  |  |  |                 maxLat: this.localCenterLat + this.localLatDiff, | 
			
		
	
		
			
				
					|  |  |  |                 minLat: this.localCenterLat - this.localLatDiff, | 
			
		
	
		
			
				
					|  |  |  |                 westLong: this.localCenterLong - this.localLongDiff, | 
			
		
	
		
			
				
					|  |  |  |               }, | 
			
		
	
		
			
				
					|  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |           ], | 
			
		
	
		
			
				
					|  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |         this.searchBox = { | 
			
		
	
		
			
				
					|  |  |  |           eastLong: this.localCenterLong + this.localLongDiff, | 
			
		
	
		
			
				
					|  |  |  |           maxLat: this.localCenterLat + this.localLatDiff, | 
			
		
	
		
			
				
					|  |  |  |           minLat: this.localCenterLat - this.localLatDiff, | 
			
		
	
		
			
				
					|  |  |  |           westLong: this.localCenterLong - this.localLongDiff, | 
			
		
	
		
			
				
					|  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |         this.localZoom = WORLD_ZOOM; | 
			
		
	
		
			
				
					|  |  |  |       } catch (err) { | 
			
		
	
		
			
				
					|  |  |  |         this.$notify( | 
			
		
	
		
			
				
					|  |  |  |           { | 
			
		
	
		
			
				
					|  |  |  |             group: "alert", | 
			
		
	
		
			
				
					|  |  |  |             type: "danger", | 
			
		
	
		
			
				
					|  |  |  |             title: "Error Updating Search Settings", | 
			
		
	
		
			
				
					|  |  |  |             text: "Try going to a different page and then coming back.", | 
			
		
	
		
			
				
					|  |  |  |           }, | 
			
		
	
		
			
				
					|  |  |  |           -1, | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |         console.error( | 
			
		
	
		
			
				
					|  |  |  |           "Telling user to retry the location search setting because:", | 
			
		
	
		
			
				
					|  |  |  |           err, | 
			
		
	
		
			
				
					|  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  |       this.$notify( | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |           group: "alert", | 
			
		
	
		
			
				
					|  |  |  |           type: "warning", | 
			
		
	
		
			
				
					|  |  |  |           title: "No Location Selected", | 
			
		
	
		
			
				
					|  |  |  |           text: "Select a location on the map.", | 
			
		
	
		
			
				
					|  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |         -1, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public async forgetSearchBox() { | 
			
		
	
		
			
				
					|  |  |  |     try { | 
			
		
	
		
			
				
					|  |  |  |       await db.open(); | 
			
		
	
		
			
				
					|  |  |  |       db.settings.update(MASTER_SETTINGS_KEY, { | 
			
		
	
		
			
				
					|  |  |  |         searchBoxes: [], | 
			
		
	
		
			
				
					|  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |       this.searchBox = null; | 
			
		
	
		
			
				
					|  |  |  |       this.localCenterLat = 0; | 
			
		
	
		
			
				
					|  |  |  |       this.localCenterLong = 0; | 
			
		
	
		
			
				
					|  |  |  |       this.localLatDiff = DEFAULT_LAT_LONG_DIFF; | 
			
		
	
		
			
				
					|  |  |  |       this.localLongDiff = DEFAULT_LAT_LONG_DIFF; | 
			
		
	
		
			
				
					|  |  |  |       this.localZoom = DEFAULT_ZOOM; | 
			
		
	
		
			
				
					|  |  |  |     } catch (err) { | 
			
		
	
		
			
				
					|  |  |  |       this.$notify( | 
			
		
	
		
			
				
					|  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |           group: "alert", | 
			
		
	
		
			
				
					|  |  |  |           type: "danger", | 
			
		
	
		
			
				
					|  |  |  |           title: "Error Updating Search Settings", | 
			
		
	
		
			
				
					|  |  |  |           text: "Try going to a different page and then coming back.", | 
			
		
	
		
			
				
					|  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |         -1, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |       console.error( | 
			
		
	
		
			
				
					|  |  |  |         "Telling user to retry the location search setting because:", | 
			
		
	
		
			
				
					|  |  |  |         err, | 
			
		
	
		
			
				
					|  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public cancelSearchBoxSelect() { | 
			
		
	
		
			
				
					|  |  |  |     this.isChoosingSearchBox = false; | 
			
		
	
		
			
				
					|  |  |  |     this.localZoom = WORLD_ZOOM; | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |   public computedLocalTabClassNames() { | 
			
		
	
		
			
				
					|  |  |  |     return { | 
			
		
	
		
			
				
					|  |  |  |       "inline-block": true, | 
			
		
	
	
		
			
				
					|  |  | 
 |