diff --git a/InitUiElements.ts b/InitUiElements.ts index 0f1143eba..0dbc7eaac 100644 --- a/InitUiElements.ts +++ b/InitUiElements.ts @@ -341,7 +341,7 @@ export class InitUiElements { private static InitBaseMap() { - State.state.availableBackgroundLayers = new AvailableBaseLayers(State.state.locationControl).availableEditorLayers; + State.state.availableBackgroundLayers = AvailableBaseLayers.AvailableLayersAt(State.state.locationControl); State.state.backgroundLayer = State.state.backgroundLayerId .map((selectedId: string) => { diff --git a/Logic/Actors/AvailableBaseLayers.ts b/Logic/Actors/AvailableBaseLayers.ts index 52b1c12de..eceadde89 100644 --- a/Logic/Actors/AvailableBaseLayers.ts +++ b/Logic/Actors/AvailableBaseLayers.ts @@ -7,7 +7,6 @@ import {UIEventSource} from "../UIEventSource"; import {GeoOperations} from "../GeoOperations"; import {Utils} from "../../Utils"; import Loc from "../../Models/Loc"; -import {isBoolean} from "util"; /** * Calculates which layers are available at the current location @@ -31,42 +30,82 @@ export default class AvailableBaseLayers { category: "osmbasedmap" } - public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex()); - public availableEditorLayers: UIEventSource; - constructor(location: UIEventSource) { - const self = this; - this.availableEditorLayers = - location.map( - (currentLocation) => { + public static AvailableLayersAt(location: UIEventSource): UIEventSource { + const source = location.map( + (currentLocation) => { - if (currentLocation === undefined) { - return AvailableBaseLayers.layerOverview; - } + if (currentLocation === undefined) { + return AvailableBaseLayers.layerOverview; + } - const currentLayers = self.availableEditorLayers?.data; - const newLayers = AvailableBaseLayers.AvailableLayersAt(currentLocation?.lon, currentLocation?.lat); + const currentLayers = source?.data; // A bit unorthodox - I know + const newLayers = AvailableBaseLayers.CalculateAvailableLayersAt(currentLocation?.lon, currentLocation?.lat); - if (currentLayers === undefined) { + if (currentLayers === undefined) { + return newLayers; + } + if (newLayers.length !== currentLayers.length) { + return newLayers; + } + for (let i = 0; i < newLayers.length; i++) { + if (newLayers[i].name !== currentLayers[i].name) { return newLayers; } - if (newLayers.length !== currentLayers.length) { - return newLayers; - } - for (let i = 0; i < newLayers.length; i++) { - if (newLayers[i].name !== currentLayers[i].name) { - return newLayers; - } - } - - return currentLayers; - }); - + } + return currentLayers; + }); + return source; } - private static AvailableLayersAt(lon: number, lat: number): BaseLayer[] { + public static SelectBestLayerAccordingTo(location: UIEventSource, preferedCategory: UIEventSource): UIEventSource { + return AvailableBaseLayers.AvailableLayersAt(location).map(available => { + // First float all 'best layers' to the top + available.sort((a, b) => { + if (a.isBest && b.isBest) { + return 0; + } + if (!a.isBest) { + return 1 + } + + return -1; + } + ) + + if (preferedCategory.data === undefined) { + return available[0] + } + + let prefered: string [] + if (typeof preferedCategory.data === "string") { + prefered = [preferedCategory.data] + } else { + prefered = preferedCategory.data; + } + + prefered.reverse(); + for (const category of prefered) { + //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top + available.sort((a, b) => { + if (a.category === preferedCategory && b.category === preferedCategory) { + return 0; + } + if (a.category !== preferedCategory) { + return 1 + } + + return -1; + } + ) + } + return available[0] + }) + } + + private static CalculateAvailableLayersAt(lon: number, lat: number): BaseLayer[] { const availableLayers = [AvailableBaseLayers.osmCarto] const globalLayers = []; for (const layerOverviewItem of AvailableBaseLayers.layerOverview) { @@ -146,7 +185,7 @@ export default class AvailableBaseLayers { layer: leafletLayer, feature: layer, isBest: props.best ?? false, - category: props.category + category: props.category }); } return layers; diff --git a/UI/Base/Minimap.ts b/UI/Base/Minimap.ts index 73bf2354a..2c38e8b74 100644 --- a/UI/Base/Minimap.ts +++ b/UI/Base/Minimap.ts @@ -52,7 +52,7 @@ export default class Minimap extends BaseUIElement { return wrapper; } - + private InitMap() { if (this._constructedHtmlElement === undefined) { // This element isn't initialized yet diff --git a/UI/BigComponents/SimpleAddUI.ts b/UI/BigComponents/SimpleAddUI.ts index 05fb52c64..9d1fd1475 100644 --- a/UI/BigComponents/SimpleAddUI.ts +++ b/UI/BigComponents/SimpleAddUI.ts @@ -19,6 +19,7 @@ import {Translation} from "../i18n/Translation"; import LocationInput from "../Input/LocationInput"; import {InputElement} from "../Input/InputElement"; import Loc from "../../Models/Loc"; +import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; /* * The SimpleAddUI is a single panel, which can have multiple states: @@ -115,14 +116,21 @@ export default class SimpleAddUI extends Toggle { let location = State.state.LastClickLocation; let preciseInput: InputElement = undefined if (preset.preciseInput !== undefined) { + const locationSrc = new UIEventSource({ + lat: location.data.lat, + lon: location.data.lon, + zoom: 19 + }); + + let backgroundLayer = undefined; + if(preset.preciseInput.preferredBackground){ + backgroundLayer= AvailableBaseLayers.SelectBestLayerAccordingTo(locationSrc, new UIEventSource(preset.preciseInput.preferredBackground)) + } + preciseInput = new LocationInput({ - preferCategory: preset.preciseInput.preferredBackground ?? State.state.backgroundLayer, - centerLocation: - new UIEventSource({ - lat: location.data.lat, - lon: location.data.lon, - zoom: 19 - }) + mapBackground: backgroundLayer, + centerLocation:locationSrc + }) preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;") } diff --git a/UI/Input/LocationInput.ts b/UI/Input/LocationInput.ts index cee2f5cbf..c306153e3 100644 --- a/UI/Input/LocationInput.ts +++ b/UI/Input/LocationInput.ts @@ -2,30 +2,27 @@ import {InputElement} from "./InputElement"; import Loc from "../../Models/Loc"; import {UIEventSource} from "../../Logic/UIEventSource"; import Minimap from "../Base/Minimap"; -import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers"; import BaseLayer from "../../Models/BaseLayer"; import Combine from "../Base/Combine"; import Svg from "../../Svg"; +import State from "../../State"; export default class LocationInput extends InputElement { IsSelected: UIEventSource = new UIEventSource(false); private _centerLocation: UIEventSource; - private readonly preferCategory; + private readonly mapBackground : UIEventSource; constructor(options?: { + mapBackground?: UIEventSource, centerLocation?: UIEventSource, - preferCategory?: string | UIEventSource, }) { super(); options = options ?? {} options.centerLocation = options.centerLocation ?? new UIEventSource({lat: 0, lon: 0, zoom: 1}) this._centerLocation = options.centerLocation; - if(typeof options.preferCategory === "string"){ - options.preferCategory = new UIEventSource(options.preferCategory); - } - this.preferCategory = options.preferCategory ?? new UIEventSource(undefined) + this.mapBackground = options.mapBackground ?? State.state.backgroundLayer this.SetClass("block h-full") } @@ -38,43 +35,10 @@ export default class LocationInput extends InputElement { } protected InnerConstructElement(): HTMLElement { - const layer: UIEventSource = new AvailableBaseLayers(this._centerLocation).availableEditorLayers.map(allLayers => { - // First float all 'best layers' to the top - allLayers.sort((a, b) => { - if (a.isBest && b.isBest) { - return 0; - } - if (!a.isBest) { - return 1 - } - - return -1; - } - ) - if (this.preferCategory) { - const self = this; - //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top - allLayers.sort((a, b) => { - const preferred = self.preferCategory.data - if (a.category === preferred && b.category === preferred) { - return 0; - } - if (a.category !== preferred) { - return 1 - } - - return -1; - } - ) - } - return allLayers[0] - }, [this.preferCategory] - ) - layer.addCallbackAndRunD(layer => console.log(layer)) const map = new Minimap( { location: this._centerLocation, - background: layer + background: this.mapBackground } ) map.leafletMap.addCallbackAndRunD(leaflet => {