forked from MapComplete/MapComplete
		
	More refactoring!
This commit is contained in:
		
							parent
							
								
									b2c234b51d
								
							
						
					
					
						commit
						6ac8ec84e4
					
				
					 22 changed files with 170 additions and 158 deletions
				
			
		|  | @ -6,7 +6,7 @@ import {FromJSON} from "./FromJSON"; | |||
| import SharedTagRenderings from "../SharedTagRenderings"; | ||||
| import {TagRenderingConfigJson} from "./TagRenderingConfigJson"; | ||||
| import {Translation} from "../../UI/i18n/Translation"; | ||||
| import {Img} from "../../UI/Img"; | ||||
| import Img from "../../UI/Base/Img"; | ||||
| import Svg from "../../Svg"; | ||||
| import {SubstitutedTranslation} from "../../UI/SpecialVisualizations"; | ||||
| import {Utils} from "../../Utils"; | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ import State from "./State"; | |||
| import {WelcomeMessage} from "./UI/WelcomeMessage"; | ||||
| import {LayerSelection} from "./UI/LayerSelection"; | ||||
| import {VariableUiElement} from "./UI/Base/VariableUIElement"; | ||||
| import {UpdateFromOverpass} from "./Logic/UpdateFromOverpass"; | ||||
| import UpdateFromOverpass from "./Logic/UpdateFromOverpass"; | ||||
| import {UIEventSource} from "./Logic/UIEventSource"; | ||||
| import {QueryParameters} from "./Logic/Web/QueryParameters"; | ||||
| import {PersonalLayersPanel} from "./UI/PersonalLayersPanel"; | ||||
|  | @ -35,10 +35,11 @@ import Link from "./UI/Base/Link"; | |||
| import * as personal from "./assets/themes/personalLayout/personalLayout.json" | ||||
| import LayoutConfig from "./Customizations/JSON/LayoutConfig"; | ||||
| import * as L from "leaflet"; | ||||
| import {Img} from "./UI/Img"; | ||||
| import Img from "./UI/Base/Img"; | ||||
| import {UserDetails} from "./Logic/Osm/OsmConnection"; | ||||
| import Attribution from "./UI/Misc/Attribution"; | ||||
| import Constants from "./Models/Constants"; | ||||
| import MetaTagging from "./Logic/MetaTagging"; | ||||
| 
 | ||||
| export class InitUiElements { | ||||
| 
 | ||||
|  | @ -354,17 +355,11 @@ export class InitUiElements { | |||
|             State.state.selectedElement.setData(undefined) | ||||
|         }) | ||||
| 
 | ||||
|          | ||||
|         State.state.layerUpdater = new UpdateFromOverpass(State.state); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     static InitLayers() { | ||||
| 
 | ||||
|         const flayers: FilteredLayer[] = [] | ||||
| 
 | ||||
|         const state = State.state; | ||||
| 
 | ||||
|         const flayers: FilteredLayer[] = [] | ||||
|         for (const layer of state.layoutToUse.data.layers) { | ||||
| 
 | ||||
|             if (typeof (layer) === "string") { | ||||
|  | @ -387,6 +382,40 @@ export class InitUiElements { | |||
|         } | ||||
| 
 | ||||
|         State.state.filteredLayers.setData(flayers); | ||||
| 
 | ||||
|         const updater = new UpdateFromOverpass(state.locationControl, state.layoutToUse, state.leafletMap); | ||||
|         State.state.layerUpdater = updater; | ||||
| 
 | ||||
|         updater.features.addCallback(features => { | ||||
| 
 | ||||
|             features.forEach(feature => { | ||||
|                 State.state.allElements.addElement(feature); | ||||
|             }) | ||||
|             MetaTagging.addMetatags(features); | ||||
| 
 | ||||
|             function renderLayers(layers) { | ||||
| 
 | ||||
| 
 | ||||
|                 if (layers.length === 0) { | ||||
|                     if (features.length > 0) { | ||||
|                         console.warn("Got some leftovers: ", features.join("; ")) | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
|                 // We use window.setTimeout to give JS some time to update everything and make the interface not too laggy
 | ||||
|                 window.setTimeout(() => { | ||||
|                     const layer = layers[0]; | ||||
|                     const rest = layers.slice(1, layers.length); | ||||
|                     features = layer.SetApplicableData(features); | ||||
|                     renderLayers(rest); | ||||
|                 }, 50) | ||||
|             } | ||||
| 
 | ||||
|             renderLayers(flayers); | ||||
| 
 | ||||
|         }) | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private static setupAllLayerElements() { | ||||
|  |  | |||
							
								
								
									
										8
									
								
								Logic/Actors/FeatureSource.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Logic/Actors/FeatureSource.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| 
 | ||||
| export default interface FeatureSource { | ||||
|      | ||||
|     features : UIEventSource<any[]>; | ||||
|     freshness: UIEventSource<Date>; | ||||
|      | ||||
| } | ||||
|  | @ -3,7 +3,7 @@ import {UIEventSource} from "../UIEventSource"; | |||
| import {UIElement} from "../../UI/UIElement"; | ||||
| import {Utils} from "../../Utils"; | ||||
| import Svg from "../../Svg"; | ||||
| import {Img} from "../../UI/Img"; | ||||
| import Img from "../../UI/Base/Img"; | ||||
| 
 | ||||
| export class GeoLocationHandler extends UIElement { | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| import LayoutConfig from "../Customizations/JSON/LayoutConfig"; | ||||
| import {OsmPreferences} from "./Osm/OsmPreferences"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {OsmConnection} from "./Osm/OsmConnection"; | ||||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; | ||||
| import {OsmConnection} from "../Osm/OsmConnection"; | ||||
| 
 | ||||
| export default class InstalledThemes { | ||||
|     public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>; | ||||
|      | ||||
|     static InstalledThemes(osmConnection: OsmConnection): UIEventSource<{ layout: LayoutConfig; definition: string }[]> { | ||||
|         return osmConnection.preferencesHandler.preferences.map<{ layout: LayoutConfig, definition: string }[]>(allPreferences => { | ||||
|     constructor(osmConnection: OsmConnection) { | ||||
|         this.installedThemes = osmConnection.preferencesHandler.preferences.map<{ layout: LayoutConfig, definition: string }[]>(allPreferences => { | ||||
|             const installedThemes: { layout: LayoutConfig, definition: string }[] = []; | ||||
|             if (allPreferences === undefined) { | ||||
|                 console.log("All prefs is undefined"); | ||||
|  | @ -41,7 +41,6 @@ export default class InstalledThemes { | |||
|             return installedThemes; | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private static DeleteInvalid(osmConnection: OsmConnection, invalidThemes: any[]) { | ||||
|  | @ -1,9 +1,9 @@ | |||
| import * as L from "leaflet"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| import {Img} from "../../UI/Img"; | ||||
| import Svg from "../../Svg"; | ||||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import {FilteredLayer} from "../FilteredLayer"; | ||||
| import Img from "../../UI/Base/Img"; | ||||
| 
 | ||||
| /** | ||||
|  * The stray-click-hanlders adds a marker to the map if no feature was clicked. | ||||
|  |  | |||
|  | @ -23,8 +23,8 @@ export class FilteredLayer { | |||
|     public readonly name: string | UIElement; | ||||
|     public readonly filters: TagsFilter; | ||||
|     public readonly isDisplayed: UIEventSource<boolean> = new UIEventSource(true); | ||||
|     private readonly combinedIsDisplayed: UIEventSource<boolean>; | ||||
|     public readonly layerDef: LayerConfig; | ||||
|     private readonly combinedIsDisplayed: UIEventSource<boolean>; | ||||
|     private readonly _maxAllowedOverlap: number; | ||||
| 
 | ||||
|     /** The featurecollection from overpass | ||||
|  | @ -68,14 +68,15 @@ export class FilteredLayer { | |||
|             } | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The main function to load data into this layer. | ||||
|      * The data that is NOT used by this layer, is returned as a geojson object; the other data is rendered | ||||
|      */ | ||||
|     public SetApplicableData(geojson: any): any { | ||||
|     public SetApplicableData(features: any[]): any[] { | ||||
|         const leftoverFeatures = []; | ||||
|         const selfFeatures = []; | ||||
|         for (let feature of geojson.features) { | ||||
|         for (let feature of features) { | ||||
|             const tags = TagUtils.proprtiesToKV(feature.properties); | ||||
|             const matches = this.filters.matches(tags); | ||||
|             if (matches) { | ||||
|  | @ -100,16 +101,13 @@ export class FilteredLayer { | |||
|             notShadowed.push(feature); | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             type: "FeatureCollection", | ||||
|             features: notShadowed | ||||
|         }; | ||||
|         return notShadowed; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public AddNewElement(element) { | ||||
|         this._newElements.push(element); | ||||
|         this.RenderLayer( this._dataFromOverpass); // Update the layer
 | ||||
|         this.RenderLayer(this._dataFromOverpass); // Update the layer
 | ||||
|     } | ||||
| 
 | ||||
|     private RenderLayer(features) { | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import opening_hours from "opening_hours"; | |||
| import {And, Or, Tag} from "./Tags"; | ||||
| import {Utils} from "../Utils"; | ||||
| import CountryCoder from "latlon2country" | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| 
 | ||||
| class SimpleMetaTagger { | ||||
|     private _f: (feature: any, index: number) => void; | ||||
|  | @ -264,7 +265,7 @@ export default class MetaTagging { | |||
|         } | ||||
|     ); | ||||
| 
 | ||||
|     public static metatags = [ | ||||
|     private static metatags = [ | ||||
|         MetaTagging.latlon, | ||||
|         MetaTagging.surfaceArea, | ||||
|         MetaTagging.country, | ||||
|  | @ -274,6 +275,10 @@ export default class MetaTagging { | |||
| 
 | ||||
|     ]; | ||||
| 
 | ||||
|     /** | ||||
|      * An actor which adds metatags on every feature in the given object | ||||
|      * The features are a list of geojson-features, with a "properties"-field and geometry | ||||
|      */ | ||||
|     static addMetatags(features: any[]) { | ||||
| 
 | ||||
|         for (const metatag of MetaTagging.metatags) { | ||||
|  |  | |||
|  | @ -4,9 +4,9 @@ import {UIEventSource} from "../UIEventSource"; | |||
| import {OsmPreferences} from "./OsmPreferences"; | ||||
| import {ChangesetHandler} from "./ChangesetHandler"; | ||||
| import {ElementStorage} from "../ElementStorage"; | ||||
| import {Img} from "../../UI/Img"; | ||||
| import Svg from "../../Svg"; | ||||
| import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; | ||||
| import Img from "../../UI/Base/Img"; | ||||
| 
 | ||||
| export class UserDetails { | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import {Bounds} from "../Bounds"; | ||||
| import {TagsFilter} from "../Tags"; | ||||
| import * as $ from "jquery" | ||||
| import * as OsmToGeoJson from "osmtogeojson"; | ||||
| import Bounds from "../../Models/Bounds"; | ||||
| 
 | ||||
| /** | ||||
|  * Interfaces overpass to get all the latest data | ||||
|  | @ -26,7 +26,7 @@ export class Overpass { | |||
|         return "https://overpass-api.de/api/interpreter?data=" + encodeURIComponent(query) | ||||
|     } | ||||
|      | ||||
|     queryGeoJson(bounds: Bounds, continuation: ((any) => void), onFail: ((reason) => void)): void { | ||||
|     queryGeoJson(bounds: Bounds, continuation: ((any, date: Date) => void), onFail: ((reason) => void)): void { | ||||
| 
 | ||||
|         let query = this.buildQuery("[bbox:" + bounds.south + "," + bounds.west + "," + bounds.north + "," + bounds.east + "]") | ||||
| 
 | ||||
|  | @ -48,7 +48,8 @@ export class Overpass { | |||
|                 } | ||||
|                 // @ts-ignore
 | ||||
|                 const geojson = OsmToGeoJson.default(json); | ||||
|                 continuation(geojson); | ||||
|                 const osmTime = new Date(json.osm3s.timestamp_osm_base); | ||||
|                 continuation(geojson, osmTime); | ||||
|             }).fail(onFail) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,16 +1,27 @@ | |||
| import {Or, TagsFilter} from "./Tags"; | ||||
| import {UIEventSource} from "./UIEventSource"; | ||||
| import {FilteredLayer} from "./FilteredLayer"; | ||||
| import {Bounds} from "./Bounds"; | ||||
| import Bounds from "../Models/Bounds"; | ||||
| import {Overpass} from "./Osm/Overpass"; | ||||
| import State from "../State"; | ||||
| import MetaTagging from "./MetaTagging"; | ||||
| import Loc from "../Models/Loc"; | ||||
| import LayoutConfig from "../Customizations/JSON/LayoutConfig"; | ||||
| import FeatureSource from "./Actors/FeatureSource"; | ||||
| 
 | ||||
| export class UpdateFromOverpass { | ||||
| export default class UpdateFromOverpass implements FeatureSource{ | ||||
| 
 | ||||
|     /** | ||||
|      * The last loaded features of the geojson | ||||
|      */ | ||||
|     public readonly features: UIEventSource<any[]> = new UIEventSource<any[]>(undefined); | ||||
| 
 | ||||
|     /** | ||||
|      * The time of updating according to Overpass | ||||
|      */ | ||||
|     public readonly freshness:UIEventSource<Date> = new UIEventSource<Date>(undefined); | ||||
| 
 | ||||
|     public readonly sufficientlyZoomed: UIEventSource<boolean>; | ||||
|     public readonly runningQuery: UIEventSource<boolean> = new UIEventSource<boolean>(false); | ||||
|     public readonly retries: UIEventSource<number> = new UIEventSource<number>(0); | ||||
|      | ||||
|     /** | ||||
|      * The previous bounds for which the query has been run at the given zoom level | ||||
|      * | ||||
|  | @ -18,55 +29,58 @@ export class UpdateFromOverpass { | |||
|      * If the map location changes, we check for each layer if it is loaded: | ||||
|      * we start checking the bounds at the first zoom level the layer might operate. If in bounds - no reload needed, otherwise we continue walking down | ||||
|      */ | ||||
|     private readonly previousBounds: Map<number, Bounds[]> = new Map<number, Bounds[]>(); | ||||
| 
 | ||||
|     private readonly state: State; | ||||
|     private readonly _previousBounds: Map<number, Bounds[]> = new Map<number, Bounds[]>(); | ||||
|     private readonly _location: UIEventSource<Loc>; | ||||
|     private readonly _layoutToUse: UIEventSource<LayoutConfig>; | ||||
|     private readonly _leafletMap: UIEventSource<L.Map>; | ||||
| 
 | ||||
|     /** | ||||
|      * The most important layer should go first, as that one gets first pick for the questions | ||||
|      */ | ||||
|     constructor(state: State) { | ||||
|         this.state = state; | ||||
|     constructor( | ||||
|         location: UIEventSource<Loc>, | ||||
|         layoutToUse: UIEventSource<LayoutConfig>, | ||||
|         leafletMap: UIEventSource<L.Map>) { | ||||
|         this._location = location; | ||||
|         this._layoutToUse = layoutToUse; | ||||
|         this._leafletMap = leafletMap; | ||||
|         const self = this; | ||||
| 
 | ||||
|         this.sufficientlyZoomed = State.state.locationControl.map(location => { | ||||
|         this.sufficientlyZoomed = location.map(location => { | ||||
|                 if(location?.zoom === undefined){ | ||||
|                     return false; | ||||
|                 } | ||||
|                 let minzoom = Math.min(...state.layoutToUse.data.layers.map(layer => layer.minzoom ?? 18)); | ||||
|                 let minzoom = Math.min(...layoutToUse.data.layers.map(layer => layer.minzoom ?? 18)); | ||||
|                 return location.zoom >= minzoom; | ||||
|             }, [state.layoutToUse] | ||||
|             }, [layoutToUse] | ||||
|         ); | ||||
|         for (let i = 0; i < 25; i++) { | ||||
|             // This update removes all data on all layers -> erase the map on lower levels too
 | ||||
|             this.previousBounds.set(i, []); | ||||
|             this._previousBounds.set(i, []); | ||||
|         } | ||||
|         state.locationControl.addCallback(() => { | ||||
|             self.update(state) | ||||
|         }); | ||||
|         state.layoutToUse.addCallback(() => { | ||||
|             self.update(state) | ||||
|         }); | ||||
| 
 | ||||
|         self.update(state); | ||||
|         | ||||
|         layoutToUse.addCallback(() => { | ||||
|             self.update() | ||||
|         }); | ||||
|         location.addCallbackAndRun(() => { | ||||
|             self.update() | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public ForceRefresh() { | ||||
|         for (let i = 0; i < 25; i++) { | ||||
|             this.previousBounds.set(i, []); | ||||
|             this._previousBounds.set(i, []); | ||||
|         } | ||||
|         this.update(this.state); | ||||
|         this.update(); | ||||
|     } | ||||
| 
 | ||||
|     private GetFilter(state: State) { | ||||
|     private GetFilter() { | ||||
|         const filters: TagsFilter[] = []; | ||||
|         state = state ?? State.state; | ||||
|         for (const layer of state.layoutToUse.data.layers) { | ||||
|         for (const layer of this._layoutToUse.data.layers) { | ||||
|             if(typeof(layer) === "string"){ | ||||
|                 continue; | ||||
|             } | ||||
|             if (state.locationControl.data.zoom < layer.minzoom) { | ||||
|             if (this._location.data.zoom < layer.minzoom) { | ||||
|                 continue; | ||||
|             } | ||||
|             if(layer.doNotDownload){ | ||||
|  | @ -77,12 +91,12 @@ export class UpdateFromOverpass { | |||
|             // Check if data for this layer has already been loaded
 | ||||
|             let previouslyLoaded = false; | ||||
|             for (let z = layer.minzoom; z < 25 && !previouslyLoaded; z++) { | ||||
|                 const previousLoadedBounds = this.previousBounds.get(z); | ||||
|                 const previousLoadedBounds = this._previousBounds.get(z); | ||||
|                 if (previousLoadedBounds === undefined) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 for (const previousLoadedBound of previousLoadedBounds) { | ||||
|                     previouslyLoaded = previouslyLoaded || this.IsInBounds(state, previousLoadedBound); | ||||
|                     previouslyLoaded = previouslyLoaded || this.IsInBounds(previousLoadedBound); | ||||
|                     if(previouslyLoaded){ | ||||
|                         break; | ||||
|                     } | ||||
|  | @ -98,61 +112,8 @@ export class UpdateFromOverpass { | |||
|         } | ||||
|         return new Or(filters); | ||||
|     } | ||||
|     private handleData(geojson: any) { | ||||
|         const self = this; | ||||
| 
 | ||||
|         self.retries.setData(0); | ||||
| 
 | ||||
|         let newIds = 1; | ||||
|         for (const feature of geojson.features) { | ||||
|             if (feature.properties.id === undefined) { | ||||
|                 feature.properties.id = "ext/" + newIds; | ||||
|                 newIds++; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         geojson.features.forEach(feature => { | ||||
|             State.state.allElements.addElement(feature); | ||||
|         }) | ||||
|         MetaTagging.addMetatags(geojson.features); | ||||
| 
 | ||||
|         function renderLayers(layers: FilteredLayer[]) { | ||||
|             if (layers.length === 0) { | ||||
|                 self.runningQuery.setData(false); | ||||
| 
 | ||||
|                 if (geojson.features.length > 0) { | ||||
|                     console.warn("Got some leftovers: ", geojson) | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             // We use window.setTimeout to give JS some time to update everything and make the interface not too laggy
 | ||||
|             window.setTimeout(() => { | ||||
|                 const layer = layers[0]; | ||||
|                 const rest = layers.slice(1, layers.length); | ||||
|                 geojson = layer.SetApplicableData(geojson); | ||||
|                 renderLayers(rest); | ||||
|             }, 50) | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         renderLayers(State.state.filteredLayers.data); | ||||
|     } | ||||
|     private handleFail(state: State, reason: any) { | ||||
|         this.retries.data++; | ||||
|         this.ForceRefresh(); | ||||
|         console.log(`QUERY FAILED (retrying in ${5 * this.retries.data} sec)`, reason); | ||||
|         this.retries.ping(); | ||||
|         this.runningQuery.setData(false) | ||||
|         const self = this; | ||||
|         window?.setTimeout( | ||||
|             function () { | ||||
|                 self.update(state) | ||||
|             }, this.retries.data * 5000 | ||||
|         ) | ||||
| 
 | ||||
|     } | ||||
|     private update(state: State): void { | ||||
|         const filter = this.GetFilter(state); | ||||
|     private update(): void { | ||||
|         const filter = this.GetFilter(); | ||||
|         if (filter === undefined) { | ||||
|             return; | ||||
|         } | ||||
|  | @ -162,9 +123,9 @@ export class UpdateFromOverpass { | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const bounds = state.leafletMap.data.getBounds(); | ||||
|         const bounds = this._leafletMap.data.getBounds(); | ||||
| 
 | ||||
|         const diff = state.layoutToUse.data.widenFactor; | ||||
|         const diff = this._layoutToUse.data.widenFactor; | ||||
| 
 | ||||
|         const n = Math.min(90, bounds.getNorth() + diff); | ||||
|         const e = Math.min(180, bounds.getEast() + diff); | ||||
|  | @ -172,18 +133,30 @@ export class UpdateFromOverpass { | |||
|         const w = Math.max(-180, bounds.getWest() - diff); | ||||
|         const queryBounds = {north: n, east: e, south: s, west: w}; | ||||
| 
 | ||||
|         const z = Math.floor(state.locationControl.data.zoom); | ||||
|         const z = Math.floor(this._location.data.zoom); | ||||
| 
 | ||||
|         this.runningQuery.setData(true); | ||||
|         const self = this; | ||||
|         const overpass = new Overpass(filter); | ||||
|         overpass.queryGeoJson(queryBounds, | ||||
|             function (data) { | ||||
|                 self.previousBounds.get(z).push(queryBounds); | ||||
|                 self.handleData(data) | ||||
|             function (data, date) { | ||||
|                 self._previousBounds.get(z).push(queryBounds); | ||||
|                 self.retries.setData(0); | ||||
|                 self.freshness.setData(date); | ||||
|                 self.features.setData(data.features); | ||||
|                 self.runningQuery.setData(false); | ||||
|             }, | ||||
|             function (reason) { | ||||
|                 self.handleFail(state, reason) | ||||
|                 self.retries.data++; | ||||
|                 self.ForceRefresh(); | ||||
|                 console.log(`QUERY FAILED (retrying in ${5 * self.retries.data} sec)`, undefined); | ||||
|                 self.retries.ping(); | ||||
|                 self.runningQuery.setData(false) | ||||
|                 window?.setTimeout( | ||||
|                     function () { | ||||
|                         self.update() | ||||
|                     }, self.retries.data * 5000 | ||||
|                 ) | ||||
|             } | ||||
|         ); | ||||
|          | ||||
|  | @ -191,12 +164,12 @@ export class UpdateFromOverpass { | |||
|          | ||||
| 
 | ||||
|     } | ||||
|     private IsInBounds(state: State, bounds: Bounds): boolean { | ||||
|         if (this.previousBounds === undefined) { | ||||
|     private IsInBounds(bounds: Bounds): boolean { | ||||
|         if (this._previousBounds === undefined) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const b = state.leafletMap.data.getBounds(); | ||||
|         const b = this._leafletMap.data.getBounds(); | ||||
|         return b.getSouth() >= bounds.south && | ||||
|             b.getNorth() <= bounds.north && | ||||
|             b.getEast() <= bounds.east && | ||||
|  |  | |||
							
								
								
									
										6
									
								
								Models/Bounds.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Models/Bounds.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| export default interface Bounds { | ||||
|     north: number, | ||||
|     east: number, | ||||
|     south: number, | ||||
|     west: number | ||||
| } | ||||
							
								
								
									
										4
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -13,7 +13,7 @@ import {QueryParameters} from "./Logic/Web/QueryParameters"; | |||
| import LayoutConfig from "./Customizations/JSON/LayoutConfig"; | ||||
| import Hash from "./Logic/Web/Hash"; | ||||
| import {MangroveIdentity} from "./Logic/Web/MangroveReviews"; | ||||
| import InstalledThemes from "./Logic/InstalledThemes"; | ||||
| import InstalledThemes from "./Logic/Actors/InstalledThemes"; | ||||
| import {BaseLayer} from "./Models/BaseLayer"; | ||||
| import Loc from "./Models/Loc"; | ||||
| import Constants from "./Models/Constants"; | ||||
|  | @ -237,7 +237,7 @@ export default class State { | |||
|         }) | ||||
| 
 | ||||
| 
 | ||||
|         this.installedThemes = InstalledThemes.InstalledThemes(this.osmConnection ); | ||||
|         this.installedThemes = new InstalledThemes(this.osmConnection).installedThemes; | ||||
| 
 | ||||
|         // Important: the favourite layers are initialized _after_ the installed themes, as these might contain an installedTheme
 | ||||
|         this.favouriteLayers = this.osmConnection.GetLongPreference("favouriteLayers").map( | ||||
|  |  | |||
							
								
								
									
										2
									
								
								Svg.ts
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Svg.ts
									
										
									
									
									
								
							|  | @ -1,4 +1,4 @@ | |||
| import {Img} from "./UI/Img"; | ||||
| import Img from "./UI/Base/Img"; | ||||
| import {FixedUiElement} from "./UI/Base/FixedUiElement"; | ||||
| 
 | ||||
| export default class Svg { | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| export class Img { | ||||
| export default class Img { | ||||
| 
 | ||||
|     public static runningFromConsole = false; | ||||
|      | ||||
|  | @ -1,10 +1,7 @@ | |||
| import {UIElement} from "../UIElement"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import {LicenseInfo} from "../../Logic/Web/Wikimedia"; | ||||
| import {Imgur} from "../../Logic/Web/Imgur"; | ||||
| import {Mapillary} from "../../Logic/Web/Mapillary"; | ||||
| import {Img} from "../Img"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| import Svg from "../../Svg"; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -56,15 +56,13 @@ export class MoreScreen extends UIElement { | |||
|         if (description !== undefined) { | ||||
|             description = new Combine(["<br/>", description]); | ||||
|         } | ||||
|         const link = | ||||
|             new SubtleButton(layout.icon, | ||||
|         return new SubtleButton(layout.icon, | ||||
|             new Combine([ | ||||
|                 "<b>", | ||||
|                 Translations.W(layout.title), | ||||
|                 "</b>", | ||||
|                 description ?? "", | ||||
|                 ]), {url: linkText, newTab: false}) | ||||
|         return link; | ||||
|             ]), {url: linkText, newTab: false}); | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ export class SearchAndGo extends UIElement { | |||
|                 } | ||||
| 
 | ||||
|                 const bb = result[0].boundingbox; | ||||
|                 const bounds = [ | ||||
|                 const bounds : [[number, number], [number, number]] = [ | ||||
|                     [bb[0], bb[2]], | ||||
|                     [bb[1], bb[3]] | ||||
|                 ] | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ import {VariableUiElement} from "./Base/VariableUIElement"; | |||
| import CheckBox from "./Input/CheckBox"; | ||||
| import {VerticalCombine} from "./Base/VerticalCombine"; | ||||
| import State from "../State"; | ||||
| import {Basemap} from "../Logic/Leaflet/Basemap"; | ||||
| import {FilteredLayer} from "../Logic/FilteredLayer"; | ||||
| import {Utils} from "../Utils"; | ||||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import {Img} from "../UI/Img" | ||||
| import Img from "../UI/Base/Img" | ||||
| import {UIElement} from "../UI/UIElement"; | ||||
| Img.runningFromConsole = true; | ||||
| // We HAVE to mark this while importing
 | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| import * as fs from "fs"; | ||||
| import {Utils} from "../Utils"; | ||||
| 
 | ||||
| function genImages() { | ||||
| 
 | ||||
|     console.log("Generating images") | ||||
|     const dir = fs.readdirSync("./assets/svg") | ||||
| 
 | ||||
|     let module = "import {Img} from \"./UI/Img\";\nimport {FixedUiElement} from \"./UI/Base/FixedUiElement\";\n\nexport default class Svg {\n\n\n"; | ||||
|     let module = "import Img from \"./UI/Base/Img\";\nimport {FixedUiElement} from \"./UI/Base/FixedUiElement\";\n\nexport default class Svg {\n\n\n"; | ||||
|     const allNames: string[] = []; | ||||
|     for (const path of dir) { | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import {UIElement} from "../UI/UIElement"; | ||||
| UIElement.runningFromConsole = true; | ||||
| import {Img} from "../UI/Img"; | ||||
| import Img from "../UI/Base/Img"; | ||||
| Img.runningFromConsole = true; | ||||
| import {equal} from "assert"; | ||||
| import T from "./TestHelper"; | ||||
|  | @ -9,13 +9,13 @@ import {And, Tag} from "../Logic/Tags"; | |||
| import Locale from "../UI/i18n/Locale"; | ||||
| import Translations from "../UI/i18n/Translations"; | ||||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
| import {OH, OpeningHour} from "../Logic/OpeningHours"; | ||||
| import PublicHolidayInput from "../UI/Input/OpeningHours/PublicHolidayInput"; | ||||
| import TagRenderingConfig from "../Customizations/JSON/TagRenderingConfig"; | ||||
| import EditableTagRendering from "../UI/Popup/EditableTagRendering"; | ||||
| import {SubstitutedTranslation} from "../UI/SpecialVisualizations"; | ||||
| import {Utils} from "../Utils"; | ||||
| import {Translation} from "../UI/i18n/Translation"; | ||||
| import {OH, OpeningHour} from "../UI/OpeningHours/OpeningHours"; | ||||
| import PublicHolidayInput from "../UI/OpeningHours/PublicHolidayInput"; | ||||
| 
 | ||||
| 
 | ||||
| new T([ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue