From 622c436a9fb2c190589d469bec5c5c0d6599b759 Mon Sep 17 00:00:00 2001 From: log101 Date: Sun, 21 Jul 2024 20:11:44 +0300 Subject: [PATCH] feat: remove geolocation logic from components --- src/components/LeafletMap/controls.ts | 17 +--- src/components/LockedContent/geolocation.ts | 9 +- src/components/leaflet-map.ts | 68 ++++++--------- src/components/locked-content.ts | 92 ++++++--------------- 4 files changed, 51 insertions(+), 135 deletions(-) diff --git a/src/components/LeafletMap/controls.ts b/src/components/LeafletMap/controls.ts index af3963c..2b5d6ea 100644 --- a/src/components/LeafletMap/controls.ts +++ b/src/components/LeafletMap/controls.ts @@ -24,22 +24,11 @@ const GoToTargetControl = L.Control.extend({ }); const GeolocationControl = L.Control.extend({ - options: { - title: "Konum İzni Ver", - }, - _watchingLocation: false, _containerEl: null as HTMLButtonElement | null, _currentLocationMarker: null as L.Marker | null, setCurrentLocationMarker: function (marker?: L.Marker) { if (marker) this._currentLocationMarker = marker; }, - initialize: function (options: any) { - L.Util.setOptions(this, options); - }, - startWatching: function () { - this._watchingLocation = true; - if (this._containerEl) this._containerEl.textContent = "Konumuma Git"; - }, onAdd: function (map: L.Map) { const locationButton = document.createElement("button"); @@ -47,17 +36,15 @@ const GeolocationControl = L.Control.extend({ locationButton.id = "ask-permission-control-button"; - locationButton.textContent = this.options.title; + locationButton.textContent = "Konumuma Git"; locationButton.classList.add("custom-map-control-button"); locationButton.type = "button"; L.DomEvent.on(locationButton, "click", () => { - if (this._watchingLocation && this._currentLocationMarker) { + if (this._currentLocationMarker) { map.setView(this._currentLocationMarker.getLatLng(), 12); - } else { - this.startWatching(); } }); diff --git a/src/components/LockedContent/geolocation.ts b/src/components/LockedContent/geolocation.ts index 9fc6ec7..396aaa3 100644 --- a/src/components/LockedContent/geolocation.ts +++ b/src/components/LockedContent/geolocation.ts @@ -40,19 +40,14 @@ function errorCallback(err: GeolocationPositionError) { } function calculateDistance( - currentPosition: GeolocationPosition, + currentPosition: L.LatLngTuple, targetPosition: L.LatLngTuple ) { - const pos = { - lat: currentPosition.coords.latitude, - lng: currentPosition.coords.longitude, - }; - // Get target position in latitudes and longitudes const targetLatLng = L.latLng(targetPosition); // Get current position in latitudes and longitudes - const currentLatLng = L.latLng(pos); + const currentLatLng = L.latLng(currentPosition); // Calculate the distance between target and current position in meters const betweenMeters = currentLatLng.distanceTo(targetLatLng); diff --git a/src/components/leaflet-map.ts b/src/components/leaflet-map.ts index 6b637c9..3fbcd6a 100644 --- a/src/components/leaflet-map.ts +++ b/src/components/leaflet-map.ts @@ -1,5 +1,11 @@ // Lit -import { html, LitElement, unsafeCSS, type CSSResultGroup } from "lit"; +import { + html, + LitElement, + unsafeCSS, + type CSSResultGroup, + type PropertyValues, +} from "lit"; import { customElement, property, query, state } from "lit/decorators.js"; // Leaflet @@ -12,7 +18,6 @@ import { GeolocationControl, GoToTargetControl } from "./LeafletMap/controls"; import leafletStyles from "leaflet/dist/leaflet.css?inline"; import globalStyles from "@/styles/globals.css?inline"; import mapStyles from "@/styles/locked-page.css?inline"; -import { onLocationError, onLocationSuccess } from "./LeafletMap/geolocation"; @customElement("leaflet-map") export class LeafletMap extends LitElement { @@ -34,27 +39,19 @@ export class LeafletMap extends LitElement { _askPermissionButton!: HTMLButtonElement; // Properties and states - @property({ type: Object }) targetLocation?: LatLngTuple; + @property({ type: Object, noAccessor: true }) targetLocation?: LatLngTuple; + @property({ type: Object }) + currentPosition?: LatLngTuple; @state() protected _map?: L.Map; @state() - protected _geolocationPermissionStatus: PermissionState = "prompt"; - @state() protected _currentLocationMarker?: L.Marker; - @state() - protected _watchingLocation = false; firstUpdated(): void { if (!this._mapElement || !this.targetLocation) return; this._map = new Map(this._mapElement).setView(this.targetLocation, 13); - this._map.on("locationerror", onLocationError); - - this._map.on("locationfound", (ev) => - onLocationSuccess(ev, this._map!, this._currentLocationMarker) - ); - L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom: 19, attribution: @@ -81,38 +78,21 @@ export class LeafletMap extends LitElement { targetLocationControl.setTargetLocation(this.targetLocation); targetLocationControl.addTo(this._map); - // Check geolocation permission, if user has given permission before - // start watching user location - navigator.permissions - .query({ name: "geolocation" }) - .then((permissionStatus) => { - switch (permissionStatus.state) { - case "granted": - this._geolocationPermissionStatus = "granted"; - const locateUserControl = new GeolocationControl({ - // @ts-expect-error - title: "Konumuma Git", - position: "bottomleft", - }); - locateUserControl.setCurrentLocationMarker( - this._currentLocationMarker - ); - locateUserControl.addTo(this._map!); - break; - case "denied": - this._geolocationPermissionStatus = "denied"; - break; - case "prompt": - const askPermissionControl = new GeolocationControl({ - position: "bottomleft", - }); + const currentLocationControl = new GeolocationControl({ + position: "bottomleft", + }); - askPermissionControl.addTo(this._map!); - break; - default: - break; - } - }); + currentLocationControl.setCurrentLocationMarker( + this._currentLocationMarker + ); + currentLocationControl.addTo(this._map); + } + + protected update(changedProperties: PropertyValues): void { + super.update(changedProperties); + if (changedProperties.get("currentPosition")) { + this._currentLocationMarker?.setLatLng(this.currentPosition!); + } } render() { diff --git a/src/components/locked-content.ts b/src/components/locked-content.ts index 55459bb..2c1ff40 100644 --- a/src/components/locked-content.ts +++ b/src/components/locked-content.ts @@ -18,7 +18,7 @@ import { } from "./LockedContent/templates"; // Geolocation utils -import { calculateDistance, errorCallback } from "./LockedContent/geolocation"; +import { calculateDistance } from "./LockedContent/geolocation"; import { incrementUnlockCounter } from "./LockedContent/serverUtils"; // LockedContent is a custom element watching user location and blurring @@ -44,35 +44,16 @@ export class LockedContent extends LitElement { @property({ noAccessor: true }) readonly imageURL?: string; @property({ type: Object, noAccessor: true }) readonly targetPosition?: LatLngTuple; + @property({ type: Object }) + currentPosition?: LatLngTuple; // Reactive states, template is rendered according to this states @state() - protected _geolocationPermissionStatus: PermissionState = "prompt"; - @state() protected _unlocked = false; @state() protected _arrived = false; @state() protected _distanceText?: string; - @state() - protected _watchId?: number; - - // This callback will be fired when geolocation info is available - successCallback(position: GeolocationPosition) { - // Set hasGeolocationPermission state true to change the template - this._geolocationPermissionStatus = "granted"; - - // Target position must be set - if (!this.targetPosition) return; - - // Calculate the distance between target and current position in meters - const distance = calculateDistance(position, this.targetPosition); - - // Update the text based on the distance - this._updateDistanceText(distance); - - this._checkArrived(distance); - } private _updateDistanceText(distance: number) { // Update the proximity text according to the distance remaining @@ -86,10 +67,6 @@ export class LockedContent extends LitElement { private _checkArrived(distance: number) { // If target is close less then 100 meters user has arrived to target location if (distance < 100) { - if (this._watchId) { - // Stop watching location - navigator.geolocation.clearWatch(this._watchId); - } // Update state to reveal the image this._arrived = true; } @@ -98,11 +75,26 @@ export class LockedContent extends LitElement { // This template is shown when user hasn't give geolocation permission yet // When user click the button user is asked for geolocation permission private _permissionButtonTemplate = () => - permissionButtonTemplate(this._startWatchingLocation); + permissionButtonTemplate(() => null); // This template is shown when user has given permission but has not arrived yet - private _lockedButtonTemplate = () => - lockedButtonTemplate(this._distanceText); + private _lockedButtonTemplate = () => { + // Target position must be set + if (!this.targetPosition || !this.currentPosition) return; + + // Calculate the distance between target and current position in meters + const distance = calculateDistance( + this.currentPosition, + this.targetPosition + ); + + // Update the text based on the distance + this._updateDistanceText(distance); + + this._checkArrived(distance); + + return lockedButtonTemplate(this._distanceText); + }; // This template is shown when user has arrived to the target location // When user click the button counter at the bottom of the page is incremented @@ -113,46 +105,8 @@ export class LockedContent extends LitElement { this._unlocked = true; }); - // Start watching user location, if user has not given permission yet - // this will ask the user for permission and update the watch id - private _startWatchingLocation() { - // User is already being watched no need to - // watch position - if (this._watchId) return; - - const id = navigator.geolocation.watchPosition( - this.successCallback.bind(this), - (err) => { - if (err.code == GeolocationPositionError.PERMISSION_DENIED) { - this._geolocationPermissionStatus = "denied"; - } - errorCallback(err); - }, - this.geolocationOptions - ); - - this._watchId = id; - } - connectedCallback(): void { super.connectedCallback(); - - // Check geolocation permission, if user has given permission before - // start watching user location - navigator.permissions - .query({ name: "geolocation" }) - .then((permissionStatus) => { - switch (permissionStatus.state) { - case "granted": - this._startWatchingLocation(); - break; - case "denied": - this._geolocationPermissionStatus = "denied"; - case "prompt": - default: - break; - } - }); } render() { @@ -165,9 +119,9 @@ export class LockedContent extends LitElement { // 4 - User did not give geolocation permission if (this._arrived) { buttonTemplate = this._unlockedButtonTemplate; - } else if (this._geolocationPermissionStatus == "granted") { + } else if (this.currentPosition) { buttonTemplate = this._lockedButtonTemplate; - } else if (this._geolocationPermissionStatus == "prompt") { + } else if (!this.currentPosition) { buttonTemplate = this._permissionButtonTemplate; } else { buttonTemplate = permissionDeniedButtonTemplate;