From aef7b8a6847cfa5acea85d60d51d7191d67a96f5 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Thu, 19 Aug 2021 23:41:48 +0200 Subject: [PATCH] Decent fix of gps-locking behaviour: single click will zoom, second click within 3sec will lock the gps location + better icons + disable of dragging while locked, fix of #458 --- Logic/Actors/GeoLocationHandler.ts | 87 ++++++++++++++++++++++++------ UI/BigComponents/RightControls.ts | 10 ++-- assets/svg/location-circle.svg | 62 --------------------- assets/svg/location-empty.svg | 10 +++- assets/svg/location-refused.svg | 40 ++++++++++++++ assets/svg/location.svg | 62 +++++++++++++++++++-- assets/svg/location_locked.svg | 61 +++++++++++++++++++++ assets/svg/location_unlocked.svg | 59 ++++++++++++++++++++ assets/svg/min-zoom.svg | 3 -- assets/svg/plus-zoom.svg | 5 -- 10 files changed, 305 insertions(+), 94 deletions(-) delete mode 100644 assets/svg/location-circle.svg create mode 100644 assets/svg/location-refused.svg create mode 100644 assets/svg/location_locked.svg create mode 100644 assets/svg/location_unlocked.svg delete mode 100644 assets/svg/min-zoom.svg delete mode 100644 assets/svg/plus-zoom.svg diff --git a/Logic/Actors/GeoLocationHandler.ts b/Logic/Actors/GeoLocationHandler.ts index f96a2c62f..2433246dc 100644 --- a/Logic/Actors/GeoLocationHandler.ts +++ b/Logic/Actors/GeoLocationHandler.ts @@ -44,13 +44,13 @@ export default class GeoLocationHandler extends VariableUiElement { * @private */ private readonly _leafletMap: UIEventSource; - + /** * The date when the user requested the geolocation. If we have a location, it'll autozoom to it the first 30 secs * @private */ private _lastUserRequest: Date; - + /** * A small flag on localstorage. If the user previously granted the geolocation, it will be set. * On firefox, the permissions api is broken (probably fingerprint resistiance) and "granted + don't ask again" doesn't stick between sessions. @@ -75,30 +75,57 @@ export default class GeoLocationHandler extends VariableUiElement { ); const isActive = new UIEventSource(false); const isLocked = new UIEventSource(false); - + const permission = new UIEventSource(""); + const lastClick = new UIEventSource(undefined); + const lastClickWithinThreeSecs = lastClick.map(lastClick => { + if (lastClick === undefined) { + return false; + } + const timeDiff = (new Date().getTime() - lastClick.getTime()) / 1000 + return timeDiff <= 3 + }) + lastClick.addCallbackAndRunD(_ => { + window.setTimeout(() => { + if (lastClickWithinThreeSecs.data) { + lastClick.ping() + } + }, 500) + }) super( hasLocation.map( (hasLocationData) => { let icon: BaseUIElement; - - if (isLocked.data) { - icon = Svg.location_svg(); - } else if (hasLocationData) { - icon = Svg.location_empty_svg(); - } else if (isActive.data) { - icon = Svg.location_empty_svg(); - } else { - icon = Svg.location_circle_svg(); + console.log("Determining icon:", permission.data, isActive.data, hasLocationData, isLocked.data, lastClickWithinThreeSecs.data) + if (permission.data === "denied") { + return Svg.location_refused_svg(); } - return icon + + if (!isActive.data) { + return Svg.location_empty_svg() + } + if (!hasLocationData) { + // Position not yet found but we are active: we spin to indicate activity + const icon = Svg.location_empty_svg() + icon.SetStyle("animation: spin 4s linear infinite;") + return icon; + } + if (isLocked.data) { + return Svg.location_locked_svg() + } + if (lastClickWithinThreeSecs.data) { + return Svg.location_unlocked_svg() + } + + // We have a location, so we show a dot in the center + return Svg.location_svg(); }, - [isActive, isLocked] + [isActive, isLocked, permission, lastClickWithinThreeSecs] ) ); this.SetClass("mapcontrol") this._isActive = isActive; this._isLocked = isLocked; - this._permission = new UIEventSource(""); + this._permission = permission this._previousLocationGrant = previousLocationGrant; this._currentGPSLocation = currentGPSLocation; this._leafletMap = leafletMap; @@ -119,14 +146,39 @@ export default class GeoLocationHandler extends VariableUiElement { self.SetClass(pointerClass); }); + this.onClick(() => { + /* + * If the previous click was within 3 seconds (and we have an active location), then we lock to the location + */ if (self._hasLocation.data) { - self._isLocked.setData(!self._isLocked.data); + if (isLocked.data) { + isLocked.setData(false) + } else if (lastClick.data !== undefined) { + const timeDiff = (new Date().getTime() - lastClick.data.getTime()) / 1000 + if (timeDiff <= 3) { + isLocked.setData(true) + lastClick.setData(undefined) + } else { + lastClick.setData(new Date()) + } + }else{ + lastClick.setData(new Date()) + } } + self.init(true); }); this.init(false); + isLocked.addCallbackAndRunD(isLocked => { + if (isLocked) { + leafletMap.data?.dragging?.disable() + } else { + leafletMap.data?.dragging?.enable() + } + }) + this._currentGPSLocation.addCallback((location) => { self._previousLocationGrant.setData("granted"); @@ -147,7 +199,7 @@ export default class GeoLocationHandler extends VariableUiElement { console.error(e); } const icon = L.icon({ - iconUrl: Img.AsData(Svg.crosshair.replace(/#000000/g, color)), + iconUrl: Img.AsData(Svg.location.replace(/#000000/g, color).replace(/#000/g, color)), iconSize: [40, 40], // size of the icon iconAnchor: [20, 20], // point of the icon which will correspond to marker's location }); @@ -240,6 +292,7 @@ export default class GeoLocationHandler extends VariableUiElement { this._lastUserRequest = zoomToGPS ? new Date() : new Date(0); if (self._permission.data === "denied") { self._previousLocationGrant.setData(""); + self._isActive.setData(false) return ""; } if (this._currentGPSLocation.data !== undefined) { diff --git a/UI/BigComponents/RightControls.ts b/UI/BigComponents/RightControls.ts index dd4282b35..10e86c914 100644 --- a/UI/BigComponents/RightControls.ts +++ b/UI/BigComponents/RightControls.ts @@ -23,21 +23,25 @@ export default class RightControls extends Combine { ); const plus = new MapControlButton( - Svg.plus_zoom_svg() + Svg.plus_svg(),{ + dontStyle:true + } ).onClick(() => { State.state.locationControl.data.zoom++; State.state.locationControl.ping(); }); const min = new MapControlButton( - Svg.min_zoom_svg() + Svg.min_svg(),{ + dontStyle: true + } ).onClick(() => { State.state.locationControl.data.zoom--; State.state.locationControl.ping(); }); super([plus, min, geolocationButton].map(el => el.SetClass("m-0.5 md:m-1"))) - this.SetClass("flex flex-col") + this.SetClass("flex flex-col items-center") } } \ No newline at end of file diff --git a/assets/svg/location-circle.svg b/assets/svg/location-circle.svg deleted file mode 100644 index 6689a4bdf..000000000 --- a/assets/svg/location-circle.svg +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/assets/svg/location-empty.svg b/assets/svg/location-empty.svg index d95789ccc..adf75bec1 100644 --- a/assets/svg/location-empty.svg +++ b/assets/svg/location-empty.svg @@ -1 +1,9 @@ - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/assets/svg/location-refused.svg b/assets/svg/location-refused.svg new file mode 100644 index 000000000..bdc5f1dcc --- /dev/null +++ b/assets/svg/location-refused.svg @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/assets/svg/location.svg b/assets/svg/location.svg index 3c4d168d6..015fdd83c 100644 --- a/assets/svg/location.svg +++ b/assets/svg/location.svg @@ -1,4 +1,60 @@ - - - + + + + + + image/svg+xml + + + + + + + + diff --git a/assets/svg/location_locked.svg b/assets/svg/location_locked.svg new file mode 100644 index 000000000..cc4267bd3 --- /dev/null +++ b/assets/svg/location_locked.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/assets/svg/location_unlocked.svg b/assets/svg/location_unlocked.svg new file mode 100644 index 000000000..632a47cc5 --- /dev/null +++ b/assets/svg/location_unlocked.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/assets/svg/min-zoom.svg b/assets/svg/min-zoom.svg deleted file mode 100644 index f617af197..000000000 --- a/assets/svg/min-zoom.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/assets/svg/plus-zoom.svg b/assets/svg/plus-zoom.svg deleted file mode 100644 index fc9ff3c80..000000000 --- a/assets/svg/plus-zoom.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - -