| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import { Store, UIEventSource } from "../UIEventSource" | 
					
						
							|  |  |  | import Svg from "../../Svg" | 
					
						
							|  |  |  | import { LocalStorageSource } from "../Web/LocalStorageSource" | 
					
						
							|  |  |  | import { VariableUiElement } from "../../UI/Base/VariableUIElement" | 
					
						
							|  |  |  | import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" | 
					
						
							|  |  |  | import { QueryParameters } from "../Web/QueryParameters" | 
					
						
							|  |  |  | import { BBox } from "../BBox" | 
					
						
							|  |  |  | import Constants from "../../Models/Constants" | 
					
						
							|  |  |  | import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface GeoLocationPointProperties { | 
					
						
							|  |  |  |     id: "gps" | 
					
						
							|  |  |  |     "user:location": "yes" | 
					
						
							|  |  |  |     date: string | 
					
						
							|  |  |  |     latitude: number | 
					
						
							|  |  |  |     longitude: number | 
					
						
							|  |  |  |     speed: number | 
					
						
							|  |  |  |     accuracy: number | 
					
						
							|  |  |  |     heading: number | 
					
						
							|  |  |  |     altitude: number | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-28 00:45:49 +02:00
										 |  |  | export default class GeoLocationHandler extends VariableUiElement { | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |     private readonly currentLocation?: SimpleFeatureSource | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Wether or not the geolocation is active, aka the user requested the current location | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _isActive: UIEventSource<boolean> | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Wether or not the geolocation is locked, aka the user requested the current location and wants the crosshair to follow the user | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _isLocked: UIEventSource<boolean> | 
					
						
							| 
									
										
										
										
											2021-07-13 14:39:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The callback over the permission API | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _permission: UIEventSource<string> | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Literally: _currentGPSLocation.data != undefined | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _hasLocation: Store<boolean> | 
					
						
							|  |  |  |     private readonly _currentGPSLocation: UIEventSource<GeolocationCoordinates> | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Kept in order to update the marker | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _leafletMap: UIEventSource<L.Map> | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * The date when the user requested the geolocation. If we have a location, it'll autozoom to it the first 30 secs | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private _lastUserRequest: UIEventSource<Date> | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * 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. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Instead, we set this flag. If this flag is set upon loading the page, we start geolocating immediately. | 
					
						
							|  |  |  |      * If the user denies the geolocation this time, we unset this flag | 
					
						
							|  |  |  |      * @private | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly _previousLocationGrant: UIEventSource<string> | 
					
						
							|  |  |  |     private readonly _layoutToUse: LayoutConfig | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor(state: { | 
					
						
							|  |  |  |         selectedElement: UIEventSource<any> | 
					
						
							|  |  |  |         currentUserLocation?: SimpleFeatureSource | 
					
						
							|  |  |  |         leafletMap: UIEventSource<any> | 
					
						
							|  |  |  |         layoutToUse: LayoutConfig | 
					
						
							|  |  |  |         featureSwitchGeolocation: UIEventSource<boolean> | 
					
						
							|  |  |  |     }) { | 
					
						
							|  |  |  |         const currentGPSLocation = new UIEventSource<GeolocationCoordinates>( | 
					
						
							|  |  |  |             undefined, | 
					
						
							|  |  |  |             "GPS-coordinate" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-11-04 02:16:07 +01:00
										 |  |  |         const leafletMap = state.leafletMap | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |         const initedAt = new Date() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let autozoomDone = false | 
					
						
							|  |  |  |         const hasLocation = currentGPSLocation.map((location) => location !== undefined) | 
					
						
							|  |  |  |         const previousLocationGrant = LocalStorageSource.Get("geolocation-permissions") | 
					
						
							|  |  |  |         const isActive = new UIEventSource<boolean>(false) | 
					
						
							|  |  |  |         const isLocked = new UIEventSource<boolean>(false) | 
					
						
							|  |  |  |         const permission = new UIEventSource<string>("") | 
					
						
							|  |  |  |         const lastClick = new UIEventSource<Date>(undefined) | 
					
						
							|  |  |  |         const lastClickWithinThreeSecs = lastClick.map((lastClick) => { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |             if (lastClick === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return false | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             const timeDiff = (new Date().getTime() - lastClick.getTime()) / 1000 | 
					
						
							|  |  |  |             return timeDiff <= 3 | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const latLonGiven = | 
					
						
							|  |  |  |             QueryParameters.wasInitialized("lat") && QueryParameters.wasInitialized("lon") | 
					
						
							|  |  |  |         const willFocus = lastClick.map((lastUserRequest) => { | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |             const timeDiffInited = (new Date().getTime() - initedAt.getTime()) / 1000 | 
					
						
							|  |  |  |             if (!latLonGiven && !autozoomDone && timeDiffInited < Constants.zoomToLocationTimeout) { | 
					
						
							|  |  |  |                 return true | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (lastUserRequest === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return false | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             const timeDiff = (new Date().getTime() - lastUserRequest.getTime()) / 1000 | 
					
						
							|  |  |  |             return timeDiff <= Constants.zoomToLocationTimeout | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         lastClick.addCallbackAndRunD((_) => { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |             window.setTimeout(() => { | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |                 if (lastClickWithinThreeSecs.data || willFocus.data) { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     lastClick.ping() | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, 500) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         super( | 
					
						
							|  |  |  |             hasLocation.map( | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |                 (hasLocationData) => { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     if (permission.data === "denied") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         return Svg.location_refused_svg() | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-07-13 14:39:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     if (!isActive.data) { | 
					
						
							|  |  |  |                         return Svg.location_empty_svg() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (!hasLocationData) { | 
					
						
							|  |  |  |                         // Position not yet found but we are active: we spin to indicate activity
 | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |                         // If will focus is active too, we indicate this differently
 | 
					
						
							|  |  |  |                         const icon = willFocus.data ? Svg.location_svg() : Svg.location_empty_svg() | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                         icon.SetStyle("animation: spin 4s linear infinite;") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         return icon | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |                     if (isLocked.data) { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                         return Svg.location_locked_svg() | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     if (lastClickWithinThreeSecs.data) { | 
					
						
							|  |  |  |                         return Svg.location_unlocked_svg() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     // We have a location, so we show a dot in the center
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return Svg.location_svg() | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |                 [isActive, isLocked, permission, lastClickWithinThreeSecs, willFocus] | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-07-27 21:02:30 +02:00
										 |  |  |         this.SetClass("mapcontrol") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._isActive = isActive | 
					
						
							|  |  |  |         this._isLocked = isLocked | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |         this._permission = permission | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this._previousLocationGrant = previousLocationGrant | 
					
						
							|  |  |  |         this._currentGPSLocation = currentGPSLocation | 
					
						
							|  |  |  |         this._leafletMap = leafletMap | 
					
						
							|  |  |  |         this._layoutToUse = state.layoutToUse | 
					
						
							|  |  |  |         this._hasLocation = hasLocation | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |         this._lastUserRequest = lastClick | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         const currentPointer = this._isActive.map( | 
					
						
							|  |  |  |             (isActive) => { | 
					
						
							|  |  |  |                 if (isActive && !self._hasLocation.data) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return "cursor-wait" | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return "cursor-pointer" | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |             [this._hasLocation] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         currentPointer.addCallbackAndRun((pointerClass) => { | 
					
						
							| 
									
										
										
										
											2021-10-14 17:39:31 +02:00
										 |  |  |             self.RemoveClass("cursor-wait") | 
					
						
							|  |  |  |             self.RemoveClass("cursor-pointer") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self.SetClass(pointerClass) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |         this.onClick(() => { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |             /* | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |              * If the previous click was within 3 seconds (and we have an active location), then we lock to the location | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |              */ | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |             if (self._hasLocation.data) { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                 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()) | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |                     lastClick.setData(new Date()) | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self.init(true, true) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-04-13 01:26:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const doAutoZoomToLocation = | 
					
						
							|  |  |  |             !latLonGiven && | 
					
						
							|  |  |  |             state.featureSwitchGeolocation.data && | 
					
						
							|  |  |  |             state.selectedElement.data !== undefined | 
					
						
							|  |  |  |         this.init(false, doAutoZoomToLocation) | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         isLocked.addCallbackAndRunD((isLocked) => { | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |             if (isLocked) { | 
					
						
							|  |  |  |                 leafletMap.data?.dragging?.disable() | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 leafletMap.data?.dragging?.enable() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 02:36:01 +01:00
										 |  |  |         this.currentLocation = state.currentUserLocation | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         this._currentGPSLocation.addCallback((location) => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self._previousLocationGrant.setData("granted") | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |             const feature = { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 type: "Feature", | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |                 properties: <GeoLocationPointProperties>{ | 
					
						
							| 
									
										
										
										
											2021-11-08 02:36:01 +01:00
										 |  |  |                     id: "gps", | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                     "user:location": "yes", | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     date: new Date().toISOString(), | 
					
						
							|  |  |  |                     latitude: location.latitude, | 
					
						
							|  |  |  |                     longitude: location.longitude, | 
					
						
							|  |  |  |                     speed: location.speed, | 
					
						
							|  |  |  |                     accuracy: location.accuracy, | 
					
						
							|  |  |  |                     heading: location.heading, | 
					
						
							|  |  |  |                     altitude: location.altitude, | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                 geometry: { | 
					
						
							|  |  |  |                     type: "Point", | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |                     coordinates: [location.longitude, location.latitude], | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self.currentLocation?.features?.setData([{ feature, freshness: new Date() }]) | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |             if (willFocus.data) { | 
					
						
							|  |  |  |                 console.log("Zooming to user location: willFocus is set") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 lastClick.setData(undefined) | 
					
						
							|  |  |  |                 autozoomDone = true | 
					
						
							|  |  |  |                 self.MoveToCurrentLocation(16) | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |             } else if (self._isLocked.data) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 self.MoveToCurrentLocation() | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2020-06-28 02:42:22 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-04 02:16:07 +01:00
										 |  |  |     private init(askPermission: boolean, zoomToLocation: boolean) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-07-13 14:39:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |         if (self._isActive.data) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self.MoveToCurrentLocation(16) | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (typeof navigator === "undefined") { | 
					
						
							| 
									
										
										
										
											2022-03-28 21:56:25 +02:00
										 |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-13 14:39:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             navigator?.permissions?.query({ name: "geolocation" })?.then(function (status) { | 
					
						
							|  |  |  |                 console.log("Geolocation permission is ", status.state) | 
					
						
							|  |  |  |                 if (status.state === "granted") { | 
					
						
							|  |  |  |                     self.StartGeolocating(zoomToLocation) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 self._permission.setData(status.state) | 
					
						
							|  |  |  |                 status.onchange = function () { | 
					
						
							|  |  |  |                     self._permission.setData(status.state) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } catch (e) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.error(e) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-18 19:48:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         if (askPermission) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self.StartGeolocating(zoomToLocation) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } else if (this._previousLocationGrant.data === "granted") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this._previousLocationGrant.setData("") | 
					
						
							|  |  |  |             self.StartGeolocating(zoomToLocation) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-28 21:56:25 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Moves to the currently loaded location. | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-28 21:56:25 +02:00
										 |  |  |      * // Should move to any location
 | 
					
						
							|  |  |  |      * let resultingLocation = undefined | 
					
						
							|  |  |  |      * let resultingzoom = 1 | 
					
						
							|  |  |  |      * const state = { | 
					
						
							|  |  |  |      *             selectedElement: new UIEventSource<any>(undefined); | 
					
						
							|  |  |  |      *             currentUserLocation: undefined , | 
					
						
							|  |  |  |      *             leafletMap: new UIEventSource<any>({getZoom: () => resultingzoom; setView: (loc, zoom) => {resultingLocation = loc; resultingzoom = zoom}), | 
					
						
							|  |  |  |      *             layoutToUse: new LayoutConfig(<any>{ | 
					
						
							|  |  |  |      *                 id: 'test', | 
					
						
							|  |  |  |      *                 title: {"en":"test"} | 
					
						
							|  |  |  |      *                description: "A testing theme", | 
					
						
							|  |  |  |      *                layers: [] | 
					
						
							|  |  |  |      *             }), | 
					
						
							|  |  |  |      *             featureSwitchGeolocation : new UIEventSource<boolean>(true) | 
					
						
							|  |  |  |      *         } | 
					
						
							|  |  |  |      * const handler = new GeoLocationHandler(state) | 
					
						
							|  |  |  |      * handler._currentGPSLocation.setData(<any> {latitude : 51.3, longitude: 4.1}) | 
					
						
							|  |  |  |      * handler.MoveToCurrentLocation() | 
					
						
							|  |  |  |      * resultingLocation // => [51.3, 4.1]
 | 
					
						
							|  |  |  |      * handler._currentGPSLocation.setData(<any> {latitude : 60, longitude: 60) // out of bounds
 | 
					
						
							|  |  |  |      * handler.MoveToCurrentLocation() | 
					
						
							|  |  |  |      * resultingLocation // => [60, 60]
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-28 21:56:25 +02:00
										 |  |  |      * // should refuse to move if out of bounds
 | 
					
						
							|  |  |  |      * let resultingLocation = undefined | 
					
						
							|  |  |  |      * let resultingzoom = 1 | 
					
						
							|  |  |  |      * const state = { | 
					
						
							|  |  |  |      *             selectedElement: new UIEventSource<any>(undefined); | 
					
						
							|  |  |  |      *             currentUserLocation: undefined , | 
					
						
							|  |  |  |      *             leafletMap: new UIEventSource<any>({getZoom: () => resultingzoom; setView: (loc, zoom) => {resultingLocation = loc; resultingzoom = zoom}), | 
					
						
							|  |  |  |      *             layoutToUse: new LayoutConfig(<any>{ | 
					
						
							|  |  |  |      *                 id: 'test', | 
					
						
							|  |  |  |      *                 title: {"en":"test"} | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      *                "lockLocation": [ [ 2.1, 50.4], [6.4, 51.54 ]], | 
					
						
							| 
									
										
										
										
											2022-03-28 21:56:25 +02:00
										 |  |  |      *                description: "A testing theme", | 
					
						
							|  |  |  |      *                layers: [] | 
					
						
							|  |  |  |      *             }), | 
					
						
							|  |  |  |      *             featureSwitchGeolocation : new UIEventSource<boolean>(true) | 
					
						
							|  |  |  |      *         } | 
					
						
							|  |  |  |      * const handler = new GeoLocationHandler(state) | 
					
						
							|  |  |  |      * handler._currentGPSLocation.setData(<any> {latitude : 51.3, longitude: 4.1}) | 
					
						
							|  |  |  |      * handler.MoveToCurrentLocation() | 
					
						
							|  |  |  |      * resultingLocation // => [51.3, 4.1]
 | 
					
						
							|  |  |  |      * handler._currentGPSLocation.setData(<any> {latitude : 60, longitude: 60) // out of bounds
 | 
					
						
							|  |  |  |      * handler.MoveToCurrentLocation() | 
					
						
							|  |  |  |      * resultingLocation // => [51.3, 4.1]
 | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private MoveToCurrentLocation(targetZoom?: number) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const location = this._currentGPSLocation.data | 
					
						
							|  |  |  |         this._lastUserRequest.setData(undefined) | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         if ( | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |             this._currentGPSLocation.data.latitude === 0 && | 
					
						
							|  |  |  |             this._currentGPSLocation.data.longitude === 0 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         ) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.debug("Not moving to GPS-location: it is null island") | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-01-02 21:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         // We check that the GPS location is not out of bounds
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const b = this._layoutToUse.lockLocation | 
					
						
							|  |  |  |         let inRange = true | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         if (b) { | 
					
						
							|  |  |  |             if (b !== true) { | 
					
						
							|  |  |  |                 // B is an array with our locklocation
 | 
					
						
							| 
									
										
										
										
											2022-03-28 21:56:25 +02:00
										 |  |  |                 inRange = new BBox(b).contains([location.longitude, location.latitude]) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!inRange) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             console.log("Not zooming to GPS location: out of bounds", b, location) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-11-03 00:55:38 +01:00
										 |  |  |             const currentZoom = this._leafletMap.data.getZoom() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this._leafletMap.data.setView( | 
					
						
							|  |  |  |                 [location.latitude, location.longitude], | 
					
						
							|  |  |  |                 Math.max(targetZoom ?? 0, currentZoom) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-29 20:30:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |     private StartGeolocating(zoomToGPS = true) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-05-29 20:30:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-09 19:29:51 +02:00
										 |  |  |         this._lastUserRequest.setData(zoomToGPS ? new Date() : new Date(0)) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         if (self._permission.data === "denied") { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             self._previousLocationGrant.setData("") | 
					
						
							| 
									
										
										
										
											2021-08-19 23:41:48 +02:00
										 |  |  |             self._isActive.setData(false) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return "" | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (this._currentGPSLocation.data !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             this.MoveToCurrentLocation(16) | 
					
						
							| 
									
										
										
										
											2021-07-23 15:56:22 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-29 20:30:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |         if (self._isActive.data) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2020-06-28 02:42:22 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         self._isActive.setData(true) | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |         navigator.geolocation.watchPosition( | 
					
						
							|  |  |  |             function (position) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 self._currentGPSLocation.setData(position.coords) | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |             function () { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 console.warn("Could not get location with navigator.geolocation") | 
					
						
							| 
									
										
										
										
											2021-07-26 09:46:54 +02:00
										 |  |  |             }, | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 enableHighAccuracy: true, | 
					
						
							| 
									
										
										
										
											2021-07-24 02:32:33 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2020-06-28 02:42:22 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-19 16:23:13 +02:00
										 |  |  | } |