| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  | import { VariableUiElement } from "../Base/VariableUIElement" | 
					
						
							|  |  |  | import Svg from "../../Svg" | 
					
						
							|  |  |  | import { UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | import GeoLocationHandler from "../../Logic/Actors/GeoLocationHandler" | 
					
						
							| 
									
										
										
										
											2022-12-24 02:12:22 +01:00
										 |  |  | import { BBox } from "../../Logic/BBox" | 
					
						
							|  |  |  | import Loc from "../../Models/Loc" | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  | import Hotkeys from "../Base/Hotkeys" | 
					
						
							| 
									
										
										
										
											2022-12-28 00:37:48 +01:00
										 |  |  | import Translations from "../i18n/Translations" | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  | import Constants from "../../Models/Constants" | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Displays an icon depending on the state of the geolocation. | 
					
						
							|  |  |  |  * Will set the 'lock' if clicked twice | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export class GeolocationControl extends VariableUiElement { | 
					
						
							| 
									
										
										
										
											2022-12-24 02:12:22 +01:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         geolocationHandler: GeoLocationHandler, | 
					
						
							|  |  |  |         state: { | 
					
						
							|  |  |  |             locationControl: UIEventSource<Loc> | 
					
						
							|  |  |  |             currentBounds: UIEventSource<BBox> | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |         const lastClick = new UIEventSource<Date>(undefined) | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |         lastClick.addCallbackD((date) => { | 
					
						
							|  |  |  |             geolocationHandler.geolocationState.requestMoment.setData(date) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |         const lastClickWithinThreeSecs = lastClick.map((lastClick) => { | 
					
						
							|  |  |  |             if (lastClick === undefined) { | 
					
						
							|  |  |  |                 return false | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const timeDiff = (new Date().getTime() - lastClick.getTime()) / 1000 | 
					
						
							|  |  |  |             return timeDiff <= 3 | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |         const lastRequestWithinTimeout = geolocationHandler.geolocationState.requestMoment.map( | 
					
						
							|  |  |  |             (date) => { | 
					
						
							|  |  |  |                 if (date === undefined) { | 
					
						
							|  |  |  |                     return false | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const timeDiff = (new Date().getTime() - date.getTime()) / 1000 | 
					
						
							|  |  |  |                 console.log("Timediff", timeDiff) | 
					
						
							|  |  |  |                 return timeDiff <= Constants.zoomToLocationTimeout | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-02-07 02:11:17 +01:00
										 |  |  |         const geolocationState = geolocationHandler?.geolocationState | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |         super( | 
					
						
							| 
									
										
										
										
											2023-02-07 02:11:17 +01:00
										 |  |  |             geolocationState?.permission?.map( | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                 (permission) => { | 
					
						
							|  |  |  |                     if (permission === "denied") { | 
					
						
							|  |  |  |                         return Svg.location_refused_svg() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (geolocationState.isLocked.data) { | 
					
						
							|  |  |  |                         return Svg.location_locked_svg() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 15:52:22 +01:00
										 |  |  |                     if (geolocationState.currentGPSLocation.data === undefined) { | 
					
						
							|  |  |  |                         if (permission === "prompt") { | 
					
						
							|  |  |  |                             return Svg.location_empty_svg() | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                         // Position not yet found, but permission is either requested or granted: we spin to indicate activity
 | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |                         const icon = | 
					
						
							|  |  |  |                             !geolocationHandler.mapHasMoved.data || lastRequestWithinTimeout.data | 
					
						
							|  |  |  |                                 ? Svg.location_svg() | 
					
						
							|  |  |  |                                 : Svg.location_empty_svg() | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                         return icon | 
					
						
							|  |  |  |                             .SetClass("cursor-wait") | 
					
						
							|  |  |  |                             .SetStyle("animation: spin 4s linear infinite;") | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-23 15:52:22 +01:00
										 |  |  |                     // We have a location, so we show a dot in the center
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-28 00:37:48 +01:00
										 |  |  |                     if (lastClickWithinThreeSecs.data) { | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                         return Svg.location_unlocked_svg() | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     // We have a location, so we show a dot in the center
 | 
					
						
							|  |  |  |                     return Svg.location_svg() | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                     geolocationState.currentGPSLocation, | 
					
						
							|  |  |  |                     geolocationState.isLocked, | 
					
						
							|  |  |  |                     geolocationHandler.mapHasMoved, | 
					
						
							|  |  |  |                     lastClickWithinThreeSecs, | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |                     lastRequestWithinTimeout, | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                 ] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  |         async function handleClick() { | 
					
						
							| 
									
										
										
										
											2022-12-28 00:37:48 +01:00
										 |  |  |             if ( | 
					
						
							|  |  |  |                 geolocationState.permission.data !== "granted" && | 
					
						
							|  |  |  |                 geolocationState.currentGPSLocation.data === undefined | 
					
						
							|  |  |  |             ) { | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |                 lastClick.setData(new Date()) | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                 await geolocationState.requestPermission() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (geolocationState.isLocked.data === true) { | 
					
						
							|  |  |  |                 // Unlock
 | 
					
						
							|  |  |  |                 geolocationState.isLocked.setData(false) | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (geolocationState.currentGPSLocation.data === undefined) { | 
					
						
							|  |  |  |                 // No location is known yet, not much we can do
 | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |                 lastClick.setData(new Date()) | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 02:12:22 +01:00
										 |  |  |             // A location _is_ known! Let's move to this location
 | 
					
						
							|  |  |  |             const currentLocation = geolocationState.currentGPSLocation.data | 
					
						
							|  |  |  |             const inBounds = state.currentBounds.data.contains([ | 
					
						
							|  |  |  |                 currentLocation.longitude, | 
					
						
							|  |  |  |                 currentLocation.latitude, | 
					
						
							|  |  |  |             ]) | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |             geolocationHandler.MoveMapToCurrentLocation() | 
					
						
							| 
									
										
										
										
											2022-12-24 02:12:22 +01:00
										 |  |  |             if (inBounds) { | 
					
						
							|  |  |  |                 const lc = state.locationControl.data | 
					
						
							|  |  |  |                 state.locationControl.setData({ | 
					
						
							|  |  |  |                     ...lc, | 
					
						
							|  |  |  |                     zoom: lc.zoom + 3, | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-28 00:37:48 +01:00
										 |  |  |             if (lastClickWithinThreeSecs.data) { | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |                 geolocationState.isLocked.setData(true) | 
					
						
							|  |  |  |                 lastClick.setData(undefined) | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             lastClick.setData(new Date()) | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.onClick(handleClick) | 
					
						
							|  |  |  |         Hotkeys.RegisterHotkey( | 
					
						
							|  |  |  |             { nomod: "L" }, | 
					
						
							| 
									
										
										
										
											2022-12-28 00:37:48 +01:00
										 |  |  |             Translations.t.hotkeyDocumentation.geolocate, | 
					
						
							| 
									
										
										
										
											2022-12-24 03:44:21 +01:00
										 |  |  |             handleClick | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         lastClick.addCallbackAndRunD((_) => { | 
					
						
							|  |  |  |             window.setTimeout(() => { | 
					
						
							|  |  |  |                 if (lastClickWithinThreeSecs.data) { | 
					
						
							|  |  |  |                     lastClick.ping() | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, 500) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2023-02-09 03:12:21 +01:00
										 |  |  |         geolocationHandler.geolocationState.requestMoment.addCallbackAndRunD((_) => { | 
					
						
							|  |  |  |             window.setTimeout(() => { | 
					
						
							|  |  |  |                 if (lastRequestWithinTimeout.data) { | 
					
						
							|  |  |  |                     geolocationHandler.geolocationState.requestMoment.ping() | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }, 500) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2022-12-22 04:13:52 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } |