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 FeatureSource from "../FeatureSource/FeatureSource";
import {BBox} from "../BBox";
import Constants from "../../Models/Constants";
export interface GeoLocationPointProperties {
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
* @private
*/
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
* @private
*/
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
* @private
*/
private _lastUserRequest: Date;
private _lastUserRequest: UIEventSource<Date>;
/**
* 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 leafletMap = state.leafletMap
const initedAt = new Date()
let autozoomDone = false;
const hasLocation = currentGPSLocation.map(
(location) => location !== undefined
);
@ -97,13 +97,30 @@ export default class GeoLocationHandler extends VariableUiElement {
const timeDiff = (new Date().getTime() - lastClick.getTime()) / 1000
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(_ => {
window.setTimeout(() => {
if (lastClickWithinThreeSecs.data) {
if (lastClickWithinThreeSecs.data || willFocus.data) {
lastClick.ping()
}
}, 500)
})
super(
hasLocation.map(
(hasLocationData) => {
@ -116,7 +133,8 @@ export default class GeoLocationHandler extends VariableUiElement {
}
if (!hasLocationData) {
// 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;")
return icon;
}
@ -130,7 +148,7 @@ export default class GeoLocationHandler extends VariableUiElement {
// We have a location, so we show a dot in the center
return Svg.location_svg();
},
[isActive, isLocked, permission, lastClickWithinThreeSecs]
[isActive, isLocked, permission, lastClickWithinThreeSecs, willFocus]
)
);
this.SetClass("mapcontrol")
@ -142,6 +160,7 @@ export default class GeoLocationHandler extends VariableUiElement {
this._leafletMap = leafletMap;
this._layoutToUse = state.layoutToUse;
this._hasLocation = hasLocation;
this._lastUserRequest = lastClick
const self = this;
const currentPointer = this._isActive.map(
@ -183,8 +202,7 @@ export default class GeoLocationHandler extends VariableUiElement {
self.init(true, true);
});
const latLonGiven = QueryParameters.wasInitialized("lat") && QueryParameters.wasInitialized("lon")
const doAutoZoomToLocation = !latLonGiven && state.featureSwitchGeolocation.data && state.selectedElement.data !== undefined
this.init(false, doAutoZoomToLocation);
@ -221,8 +239,12 @@ export default class GeoLocationHandler extends VariableUiElement {
self.currentLocation?.features?.setData([{feature, freshness: new Date()}])
const timeSinceRequest =
(new Date().getTime() - (self._lastUserRequest?.getTime() ?? 0)) / 1000;
if (timeSinceRequest < 30) {
(new Date().getTime() - (self._lastUserRequest.data?.getTime() ?? 0)) / 1000;
if (willFocus.data) {
console.log("Zooming to user location: willFocus is set")
willFocus.setData(false)
autozoomDone = true;
self.MoveToCurrentLocation(16);
} else if (self._isLocked.data) {
self.MoveToCurrentLocation();
@ -239,8 +261,8 @@ export default class GeoLocationHandler extends VariableUiElement {
self.MoveToCurrentLocation(16);
return;
}
if(typeof navigator === "undefined"){
if (typeof navigator === "undefined") {
return
}
@ -271,7 +293,7 @@ export default class GeoLocationHandler extends VariableUiElement {
/**
* Moves to the currently loaded location.
*
*
* // Should move to any location
* let resultingLocation = undefined
* let resultingzoom = 1
@ -321,7 +343,7 @@ export default class GeoLocationHandler extends VariableUiElement {
*/
private MoveToCurrentLocation(targetZoom?: number) {
const location = this._currentGPSLocation.data;
this._lastUserRequest = undefined;
this._lastUserRequest.setData(undefined);
if (
this._currentGPSLocation.data.latitude === 0 &&
@ -356,7 +378,7 @@ export default class GeoLocationHandler extends VariableUiElement {
private StartGeolocating(zoomToGPS = true) {
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") {
self._previousLocationGrant.setData("");
self._isActive.setData(false)

View file

@ -43,29 +43,34 @@ export default class ElementsState extends FeatureSwitchState {
constructor(layoutToUse: LayoutConfig) {
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
const zoom = UIEventSource.asFloat(
QueryParameters.GetQueryParameter(
"z",
"" + (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"))
);
const zoom = localStorageSynced("z",(layoutToUse?.startZoom ?? 1),"The initial/current zoom level")
const lat = localStorageSynced("lat",(layoutToUse?.startLat ?? 0),"The initial/current latitude")
const lon = localStorageSynced("lon",(layoutToUse?.startLon ?? 0),"The initial/current longitude of the app")
this.locationControl.setData({
zoom: Utils.asFloat(zoom.data),
@ -73,7 +78,7 @@ export default class ElementsState extends FeatureSwitchState {
lon: Utils.asFloat(lon.data),
})
this.locationControl.addCallback((latlonz) => {
// Sync th location controls
// Sync the location controls
zoom.setData(latlonz.zoom);
lat.setData(latlonz.lat);
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 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 {
if (Utils.runningFromConsole) {