feat: remove geolocation logic from components
This commit is contained in:
parent
100d329d47
commit
622c436a9f
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user