Zoom to geolocation automatically if within 60 seconds, fix reading the previous map location from local storage if not initialized, fix #724"

This commit is contained in:
pietervdvn 2022-04-09 19:29:51 +02:00
parent 0cb306e542
commit 49f26687e3
3 changed files with 72 additions and 38 deletions

View file

@ -6,6 +6,7 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
import {QueryParameters} from "../Web/QueryParameters"; import {QueryParameters} from "../Web/QueryParameters";
import FeatureSource from "../FeatureSource/FeatureSource"; import FeatureSource from "../FeatureSource/FeatureSource";
import {BBox} from "../BBox"; import {BBox} from "../BBox";
import Constants from "../../Models/Constants";
export interface GeoLocationPointProperties { export interface GeoLocationPointProperties {
id: "gps", id: "gps",
@ -25,13 +26,11 @@ export default class GeoLocationHandler extends VariableUiElement {
/** /**
* Wether or not the geolocation is active, aka the user requested the current location * Wether or not the geolocation is active, aka the user requested the current location
* @private
*/ */
private readonly _isActive: UIEventSource<boolean>; private readonly _isActive: UIEventSource<boolean>;
/** /**
* Wether or not the geolocation is locked, aka the user requested the current location and wants the crosshair to follow the user * Wether or not the geolocation is locked, aka the user requested the current location and wants the crosshair to follow the user
* @private
*/ */
private readonly _isLocked: UIEventSource<boolean>; private readonly _isLocked: UIEventSource<boolean>;
@ -54,9 +53,8 @@ export default class GeoLocationHandler extends VariableUiElement {
/** /**
* The date when the user requested the geolocation. If we have a location, it'll autozoom to it the first 30 secs * 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; private _lastUserRequest: UIEventSource<Date>;
/** /**
* A small flag on localstorage. If the user previously granted the geolocation, it will be set. * A small flag on localstorage. If the user previously granted the geolocation, it will be set.
@ -80,6 +78,8 @@ export default class GeoLocationHandler extends VariableUiElement {
) { ) {
const currentGPSLocation = new UIEventSource<Coordinates>(undefined, "GPS-coordinate") const currentGPSLocation = new UIEventSource<Coordinates>(undefined, "GPS-coordinate")
const leafletMap = state.leafletMap const leafletMap = state.leafletMap
const initedAt = new Date()
let autozoomDone = false;
const hasLocation = currentGPSLocation.map( const hasLocation = currentGPSLocation.map(
(location) => location !== undefined (location) => location !== undefined
); );
@ -97,13 +97,30 @@ export default class GeoLocationHandler extends VariableUiElement {
const timeDiff = (new Date().getTime() - lastClick.getTime()) / 1000 const timeDiff = (new Date().getTime() - lastClick.getTime()) / 1000
return timeDiff <= 3 return timeDiff <= 3
}) })
const latLonGiven = QueryParameters.wasInitialized("lat") && QueryParameters.wasInitialized("lon")
const willFocus = lastClick.map(lastUserRequest => {
const timeDiffInited = (new Date().getTime() - initedAt.getTime()) / 1000
console.log("TimeDiff with initedAtt is ", timeDiffInited)
if (!latLonGiven && !autozoomDone && timeDiffInited < Constants.zoomToLocationTimeout) {
return true
}
if (lastUserRequest === undefined) {
return false;
}
const timeDiff = (new Date().getTime() - lastUserRequest.getTime()) / 1000
console.log("TimeDiff with lastClick is ", timeDiff)
return timeDiff <= Constants.zoomToLocationTimeout
})
lastClick.addCallbackAndRunD(_ => { lastClick.addCallbackAndRunD(_ => {
window.setTimeout(() => { window.setTimeout(() => {
if (lastClickWithinThreeSecs.data) { if (lastClickWithinThreeSecs.data || willFocus.data) {
lastClick.ping() lastClick.ping()
} }
}, 500) }, 500)
}) })
super( super(
hasLocation.map( hasLocation.map(
(hasLocationData) => { (hasLocationData) => {
@ -116,7 +133,8 @@ export default class GeoLocationHandler extends VariableUiElement {
} }
if (!hasLocationData) { if (!hasLocationData) {
// Position not yet found but we are active: we spin to indicate activity // Position not yet found but we are active: we spin to indicate activity
const icon = Svg.location_empty_svg() // If will focus is active too, we indicate this differently
const icon = willFocus.data ? Svg.location_svg() : Svg.location_empty_svg()
icon.SetStyle("animation: spin 4s linear infinite;") icon.SetStyle("animation: spin 4s linear infinite;")
return icon; return icon;
} }
@ -130,7 +148,7 @@ export default class GeoLocationHandler extends VariableUiElement {
// We have a location, so we show a dot in the center // We have a location, so we show a dot in the center
return Svg.location_svg(); return Svg.location_svg();
}, },
[isActive, isLocked, permission, lastClickWithinThreeSecs] [isActive, isLocked, permission, lastClickWithinThreeSecs, willFocus]
) )
); );
this.SetClass("mapcontrol") this.SetClass("mapcontrol")
@ -142,6 +160,7 @@ export default class GeoLocationHandler extends VariableUiElement {
this._leafletMap = leafletMap; this._leafletMap = leafletMap;
this._layoutToUse = state.layoutToUse; this._layoutToUse = state.layoutToUse;
this._hasLocation = hasLocation; this._hasLocation = hasLocation;
this._lastUserRequest = lastClick
const self = this; const self = this;
const currentPointer = this._isActive.map( const currentPointer = this._isActive.map(
@ -183,7 +202,6 @@ export default class GeoLocationHandler extends VariableUiElement {
self.init(true, true); self.init(true, true);
}); });
const latLonGiven = QueryParameters.wasInitialized("lat") && QueryParameters.wasInitialized("lon")
const doAutoZoomToLocation = !latLonGiven && state.featureSwitchGeolocation.data && state.selectedElement.data !== undefined const doAutoZoomToLocation = !latLonGiven && state.featureSwitchGeolocation.data && state.selectedElement.data !== undefined
this.init(false, doAutoZoomToLocation); this.init(false, doAutoZoomToLocation);
@ -221,8 +239,12 @@ export default class GeoLocationHandler extends VariableUiElement {
self.currentLocation?.features?.setData([{feature, freshness: new Date()}]) self.currentLocation?.features?.setData([{feature, freshness: new Date()}])
const timeSinceRequest = const timeSinceRequest =
(new Date().getTime() - (self._lastUserRequest?.getTime() ?? 0)) / 1000; (new Date().getTime() - (self._lastUserRequest.data?.getTime() ?? 0)) / 1000;
if (timeSinceRequest < 30) {
if (willFocus.data) {
console.log("Zooming to user location: willFocus is set")
willFocus.setData(false)
autozoomDone = true;
self.MoveToCurrentLocation(16); self.MoveToCurrentLocation(16);
} else if (self._isLocked.data) { } else if (self._isLocked.data) {
self.MoveToCurrentLocation(); self.MoveToCurrentLocation();
@ -240,7 +262,7 @@ export default class GeoLocationHandler extends VariableUiElement {
return; return;
} }
if(typeof navigator === "undefined"){ if (typeof navigator === "undefined") {
return return
} }
@ -321,7 +343,7 @@ export default class GeoLocationHandler extends VariableUiElement {
*/ */
private MoveToCurrentLocation(targetZoom?: number) { private MoveToCurrentLocation(targetZoom?: number) {
const location = this._currentGPSLocation.data; const location = this._currentGPSLocation.data;
this._lastUserRequest = undefined; this._lastUserRequest.setData(undefined);
if ( if (
this._currentGPSLocation.data.latitude === 0 && this._currentGPSLocation.data.latitude === 0 &&
@ -356,7 +378,7 @@ export default class GeoLocationHandler extends VariableUiElement {
private StartGeolocating(zoomToGPS = true) { private StartGeolocating(zoomToGPS = true) {
const self = this; const self = this;
this._lastUserRequest = zoomToGPS ? new Date() : new Date(0); this._lastUserRequest.setData(zoomToGPS ? new Date() : new Date(0))
if (self._permission.data === "denied") { if (self._permission.data === "denied") {
self._previousLocationGrant.setData(""); self._previousLocationGrant.setData("");
self._isActive.setData(false) self._isActive.setData(false)

View file

@ -44,28 +44,33 @@ export default class ElementsState extends FeatureSwitchState {
constructor(layoutToUse: LayoutConfig) { constructor(layoutToUse: LayoutConfig) {
super(layoutToUse); super(layoutToUse);
function localStorageSynced(key: string, deflt: number, docs: string ): UIEventSource<number>{
const localStorage = LocalStorageSource.Get(key)
const previousValue = localStorage.data
const src = UIEventSource.asFloat(
QueryParameters.GetQueryParameter(
key,
"" + deflt,
docs
).syncWith(localStorage)
);
if(src.data === deflt){
const prev = Number(previousValue)
if(!isNaN(prev)){
src.setData(prev)
}
}
return src;
}
// -- Location control initialization // -- Location control initialization
const zoom = UIEventSource.asFloat( const zoom = localStorageSynced("z",(layoutToUse?.startZoom ?? 1),"The initial/current zoom level")
QueryParameters.GetQueryParameter( const lat = localStorageSynced("lat",(layoutToUse?.startLat ?? 0),"The initial/current latitude")
"z", const lon = localStorageSynced("lon",(layoutToUse?.startLon ?? 0),"The initial/current longitude of the app")
"" + (layoutToUse?.startZoom ?? 1),
"The initial/current zoom level"
).syncWith(LocalStorageSource.Get("zoom"))
);
const lat = UIEventSource.asFloat(
QueryParameters.GetQueryParameter(
"lat",
"" + (layoutToUse?.startLat ?? 0),
"The initial/current latitude"
).syncWith(LocalStorageSource.Get("lat"))
);
const lon = UIEventSource.asFloat(
QueryParameters.GetQueryParameter(
"lon",
"" + (layoutToUse?.startLon ?? 0),
"The initial/current longitude of the app"
).syncWith(LocalStorageSource.Get("lon"))
);
this.locationControl.setData({ this.locationControl.setData({
zoom: Utils.asFloat(zoom.data), zoom: Utils.asFloat(zoom.data),
@ -73,7 +78,7 @@ export default class ElementsState extends FeatureSwitchState {
lon: Utils.asFloat(lon.data), lon: Utils.asFloat(lon.data),
}) })
this.locationControl.addCallback((latlonz) => { this.locationControl.addCallback((latlonz) => {
// Sync th location controls // Sync the location controls
zoom.setData(latlonz.zoom); zoom.setData(latlonz.zoom);
lat.setData(latlonz.lat); lat.setData(latlonz.lat);
lon.setData(latlonz.lon); lon.setData(latlonz.lon);

View file

@ -62,6 +62,13 @@ export default class Constants {
*/ */
static distanceToChangeObjectBins = [25, 50, 100, 500, 1000, 5000, Number.MAX_VALUE] static distanceToChangeObjectBins = [25, 50, 100, 500, 1000, 5000, Number.MAX_VALUE]
static themeOrder = ["personal", "cyclofix", "waste" , "etymology", "food","cafes_and_pubs", "playgrounds", "hailhydrant", "toilets", "aed", "bookcases"]; static themeOrder = ["personal", "cyclofix", "waste" , "etymology", "food","cafes_and_pubs", "playgrounds", "hailhydrant", "toilets", "aed", "bookcases"];
/**
* Upon initialization, the GPS will search the location.
* If the location is found within the given timout, it'll automatically fly to it.
*
* In seconds
*/
static zoomToLocationTimeout = 60;
private static isRetina(): boolean { private static isRetina(): boolean {
if (Utils.runningFromConsole) { if (Utils.runningFromConsole) {