You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							282 lines
						
					
					
						
							8.0 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							282 lines
						
					
					
						
							8.0 KiB
						
					
					
				
								<template>
							 | 
						|
								  <QuickNav />
							 | 
						|
								
							 | 
						|
								  <!-- CONTENT -->
							 | 
						|
								  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
							 | 
						|
								    <!-- Breadcrumb -->
							 | 
						|
								    <div class="mb-8">
							 | 
						|
								      <!-- Back -->
							 | 
						|
								      <div class="text-lg text-center font-light relative px-7">
							 | 
						|
								        <h1
							 | 
						|
								          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
							 | 
						|
								          @click="$router.back()"
							 | 
						|
								        >
							 | 
						|
								          <fa icon="chevron-left" class="fa-fw"></fa>
							 | 
						|
								        </h1>
							 | 
						|
								      </div>
							 | 
						|
								
							 | 
						|
								      <!-- Heading -->
							 | 
						|
								      <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
							 | 
						|
								        Area for Nearby Search
							 | 
						|
								      </h1>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div class="px-2 py-4">
							 | 
						|
								      This location is only stored on your device. It is sometimes sent from
							 | 
						|
								      your device to run searches but it is not stored on our servers.
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div>
							 | 
						|
								      <button v-if="!searchBox && !isNewMarkerSet" class="m-4 px-4 py-2">
							 | 
						|
								        Click to Choose a Location for Nearby Search
							 | 
						|
								      </button>
							 | 
						|
								      <button
							 | 
						|
								        v-if="isNewMarkerSet"
							 | 
						|
								        class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
							 | 
						|
								        @click="storeSearchBox"
							 | 
						|
								      >
							 | 
						|
								        Store This 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 Stored Location
							 | 
						|
								      </button>
							 | 
						|
								      <button
							 | 
						|
								        v-if="searchBox"
							 | 
						|
								        class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
							 | 
						|
								        @click="resetLatLong"
							 | 
						|
								      >
							 | 
						|
								        Reset Marker
							 | 
						|
								      </button>
							 | 
						|
								      <button
							 | 
						|
								        v-if="isNewMarkerSet"
							 | 
						|
								        class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
							 | 
						|
								        @click="isNewMarkerSet = false"
							 | 
						|
								      >
							 | 
						|
								        Erase Marker
							 | 
						|
								      </button>
							 | 
						|
								      <div v-if="isNewMarkerSet">
							 | 
						|
								        Click on the pin to erase it. Click anywhere else to set a different
							 | 
						|
								        different corner.
							 | 
						|
								      </div>
							 | 
						|
								    </div>
							 | 
						|
								
							 | 
						|
								    <div class="mb-4 aspect-video">
							 | 
						|
								      <l-map
							 | 
						|
								        ref="map"
							 | 
						|
								        :center="[localCenterLat, localCenterLong]"
							 | 
						|
								        class="!z-40 rounded-md"
							 | 
						|
								        v-model:zoom="localZoom"
							 | 
						|
								        @click="setMapPoint"
							 | 
						|
								      >
							 | 
						|
								        <l-tile-layer
							 | 
						|
								          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
							 | 
						|
								          layer-type="base"
							 | 
						|
								          name="OpenStreetMap"
							 | 
						|
								        />
							 | 
						|
								        <l-marker
							 | 
						|
								          v-if="isNewMarkerSet"
							 | 
						|
								          :lat-lng="[localCenterLat, localCenterLong]"
							 | 
						|
								          @click="isNewMarkerSet = false"
							 | 
						|
								        />
							 | 
						|
								        <l-rectangle
							 | 
						|
								          v-if="isNewMarkerSet"
							 | 
						|
								          :bounds="[
							 | 
						|
								            [localCenterLat - localLatDiff, localCenterLong - localLongDiff],
							 | 
						|
								            [localCenterLat + localLatDiff, localCenterLong + localLongDiff],
							 | 
						|
								          ]"
							 | 
						|
								          :weight="1"
							 | 
						|
								        />
							 | 
						|
								      </l-map>
							 | 
						|
								    </div>
							 | 
						|
								  </section>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script lang="ts">
							 | 
						|
								import { LeafletMouseEvent } from "leaflet";
							 | 
						|
								import "leaflet/dist/leaflet.css";
							 | 
						|
								import { Component, Vue } from "vue-facing-decorator";
							 | 
						|
								import {
							 | 
						|
								  LMap,
							 | 
						|
								  LMarker,
							 | 
						|
								  LRectangle,
							 | 
						|
								  LTileLayer,
							 | 
						|
								} from "@vue-leaflet/vue-leaflet";
							 | 
						|
								
							 | 
						|
								import QuickNav from "@/components/QuickNav.vue";
							 | 
						|
								import { NotificationIface } from "@/constants/app";
							 | 
						|
								import { db } from "@/db/index";
							 | 
						|
								import { BoundingBox, MASTER_SETTINGS_KEY } from "@/db/tables/settings";
							 | 
						|
								
							 | 
						|
								const DEFAULT_LAT_LONG_DIFF = 0.01;
							 | 
						|
								const WORLD_ZOOM = 2;
							 | 
						|
								const DEFAULT_ZOOM = 2;
							 | 
						|
								
							 | 
						|
								@Component({
							 | 
						|
								  components: {
							 | 
						|
								    QuickNav,
							 | 
						|
								    LRectangle,
							 | 
						|
								    LMap,
							 | 
						|
								    LMarker,
							 | 
						|
								    LTileLayer,
							 | 
						|
								  },
							 | 
						|
								})
							 | 
						|
								export default class DiscoverView extends Vue {
							 | 
						|
								  $notify!: (notification: NotificationIface, timeout?: number) => void;
							 | 
						|
								
							 | 
						|
								  isChoosingSearchBox = false;
							 | 
						|
								  isNewMarkerSet = false;
							 | 
						|
								
							 | 
						|
								  // "local" vars are for the currently selected map box
							 | 
						|
								  localCenterLat = 0;
							 | 
						|
								  localCenterLong = 0;
							 | 
						|
								  localLatDiff = DEFAULT_LAT_LONG_DIFF;
							 | 
						|
								  localLongDiff = DEFAULT_LAT_LONG_DIFF;
							 | 
						|
								  localZoom = DEFAULT_ZOOM;
							 | 
						|
								
							 | 
						|
								  // searchBox reflects what is stored in the database
							 | 
						|
								  searchBox: { name: string; bbox: BoundingBox } | null = null;
							 | 
						|
								
							 | 
						|
								  async mounted() {
							 | 
						|
								    await db.open();
							 | 
						|
								    const settings = await db.settings.get(MASTER_SETTINGS_KEY);
							 | 
						|
								    this.searchBox = settings?.searchBoxes?.[0] || null;
							 | 
						|
								    this.resetLatLong();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  setMapPoint(event: LeafletMouseEvent) {
							 | 
						|
								    if (this.isNewMarkerSet) {
							 | 
						|
								      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.isNewMarkerSet = true;
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public resetLatLong() {
							 | 
						|
								    if (this.searchBox?.bbox) {
							 | 
						|
								      const bbox = this.searchBox.bbox;
							 | 
						|
								      this.localCenterLat = (bbox.maxLat + bbox.minLat) / 2;
							 | 
						|
								      this.localCenterLong = (bbox.eastLong + bbox.westLong) / 2;
							 | 
						|
								      this.localLatDiff = (bbox.maxLat - bbox.minLat) / 2;
							 | 
						|
								      this.localLongDiff = (bbox.eastLong - bbox.westLong) / 2;
							 | 
						|
								      this.localZoom = WORLD_ZOOM;
							 | 
						|
								      this.isNewMarkerSet = true;
							 | 
						|
								    } else {
							 | 
						|
								      this.isNewMarkerSet = false;
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public async storeSearchBox() {
							 | 
						|
								    if (this.localCenterLong || this.localCenterLat) {
							 | 
						|
								      try {
							 | 
						|
								        const newSearchBox = {
							 | 
						|
								          name: "Local",
							 | 
						|
								          bbox: {
							 | 
						|
								            eastLong: this.localCenterLong + this.localLongDiff,
							 | 
						|
								            maxLat: this.localCenterLat + this.localLatDiff,
							 | 
						|
								            minLat: this.localCenterLat - this.localLatDiff,
							 | 
						|
								            westLong: this.localCenterLong - this.localLongDiff,
							 | 
						|
								          },
							 | 
						|
								        };
							 | 
						|
								        await db.open();
							 | 
						|
								        db.settings.update(MASTER_SETTINGS_KEY, {
							 | 
						|
								          searchBoxes: [newSearchBox],
							 | 
						|
								        });
							 | 
						|
								        this.searchBox = newSearchBox;
							 | 
						|
								        this.isChoosingSearchBox = false;
							 | 
						|
								
							 | 
						|
								        this.$notify(
							 | 
						|
								          {
							 | 
						|
								            group: "alert",
							 | 
						|
								            type: "success",
							 | 
						|
								            title: "Saved",
							 | 
						|
								            text: "That has been saved in your preferences. You can now filter by it on your home screen feed.",
							 | 
						|
								          },
							 | 
						|
								          7000,
							 | 
						|
								        );
							 | 
						|
								        this.$router.back();
							 | 
						|
								      } 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: [],
							 | 
						|
								        filterFeedByNearby: false,
							 | 
						|
								      });
							 | 
						|
								      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;
							 | 
						|
								      this.isChoosingSearchBox = false;
							 | 
						|
								      this.isNewMarkerSet = false;
							 | 
						|
								    } 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;
							 | 
						|
								  }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								
							 |