Performance: lazily download ELI when needed instead of bundling this in the download

This commit is contained in:
Pieter Vander Vennet 2024-08-11 16:27:00 +02:00
parent b91b1378d1
commit 62070a64e2
14 changed files with 257 additions and 183 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "mapcomplete", "name": "mapcomplete",
"version": "0.45.0", "version": "0.45.1",
"repository": "https://github.com/pietervdvn/MapComplete", "repository": "https://github.com/pietervdvn/MapComplete",
"description": "A small website to edit OSM easily", "description": "A small website to edit OSM easily",
"bugs": "https://github.com/pietervdvn/MapComplete/issues", "bugs": "https://github.com/pietervdvn/MapComplete/issues",

View file

@ -99,8 +99,17 @@ class DownloadEli extends Script {
const contents = const contents =
'{"type":"FeatureCollection",\n "features": [\n' + '{"type":"FeatureCollection",\n "features": [\n' +
keptLayers.map((l) => JSON.stringify(l)).join(",\n") + keptLayers.filter(l => l.properties.id !== "Bing").map((l) => JSON.stringify(l)).join(",\n") +
"\n]}" "\n]}"
const bing = keptLayers.find(l => l.properties.id === "Bing")
if(bing){
const pth = target.replace(/.json$/, ".bing.json")
fs.writeFileSync(pth, JSON.stringify(bing), { encoding: "utf8" })
console.log("Written", pth)
}else{
console.log("No bing entry found")
}
fs.writeFileSync(target, contents, { encoding: "utf8" }) fs.writeFileSync(target, contents, { encoding: "utf8" })
console.log("Written", keptLayers.length + ", entries to the ELI") console.log("Written", keptLayers.length + ", entries to the ELI")
} }

View file

@ -1,6 +1,6 @@
import { Store, UIEventSource } from "../UIEventSource" import { Store, UIEventSource } from "../UIEventSource"
import { Utils } from "../../Utils" import { Utils } from "../../Utils"
import { RasterLayerPolygon, RasterLayerUtils } from "../../Models/RasterLayers" import { AvailableRasterLayers, RasterLayerPolygon, RasterLayerUtils } from "../../Models/RasterLayers"
/** /**
* When a user pans around on the map, they might pan out of the range of the current background raster layer. * When a user pans around on the map, they might pan out of the range of the current background raster layer.
@ -9,12 +9,24 @@ import { RasterLayerPolygon, RasterLayerUtils } from "../../Models/RasterLayers"
export default class BackgroundLayerResetter { export default class BackgroundLayerResetter {
constructor( constructor(
currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>, currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>,
availableLayers: Store<RasterLayerPolygon[]> availableLayers: {store: Store<RasterLayerPolygon[]>}
) { ) {
if (Utils.runningFromConsole) { if (Utils.runningFromConsole) {
return return
} }
currentBackgroundLayer.addCallbackAndRunD(l => {
if(l.geometry !== undefined && AvailableRasterLayers.globalLayers.find(global => global.properties.id !== l.properties.id)){
BackgroundLayerResetter.installHandler(currentBackgroundLayer, availableLayers.store)
return true // unregister
}
})
}
private static installHandler( currentBackgroundLayer: UIEventSource<RasterLayerPolygon | undefined>,
availableLayers: Store<RasterLayerPolygon[]>
){
// Change the baseLayer back to OSM if we go out of the current range of the layer // Change the baseLayer back to OSM if we go out of the current range of the layer
availableLayers.addCallbackAndRunD((availableLayers) => { availableLayers.addCallbackAndRunD((availableLayers) => {
// We only check on move/on change of the availableLayers // We only check on move/on change of the availableLayers

View file

@ -1,5 +1,5 @@
import { Store, UIEventSource } from "../UIEventSource" import { Store, UIEventSource } from "../UIEventSource"
import { RasterLayerPolygon } from "../../Models/RasterLayers" import { AvailableRasterLayers, RasterLayerPolygon } from "../../Models/RasterLayers"
/** /**
* Selects the appropriate raster layer as background for the given query parameter, theme setting, user preference or default value. * Selects the appropriate raster layer as background for the given query parameter, theme setting, user preference or default value.
@ -8,7 +8,7 @@ import { RasterLayerPolygon } from "../../Models/RasterLayers"
*/ */
export class PreferredRasterLayerSelector { export class PreferredRasterLayerSelector {
private readonly _rasterLayerSetting: UIEventSource<RasterLayerPolygon> private readonly _rasterLayerSetting: UIEventSource<RasterLayerPolygon>
private readonly _availableLayers: Store<RasterLayerPolygon[]> private readonly _availableLayers: { store: Store<RasterLayerPolygon[]> }
private readonly _preferredBackgroundLayer: UIEventSource< private readonly _preferredBackgroundLayer: UIEventSource<
string | "photo" | "map" | "osmbasedmap" | undefined string | "photo" | "map" | "osmbasedmap" | undefined
> >
@ -16,11 +16,11 @@ export class PreferredRasterLayerSelector {
constructor( constructor(
rasterLayerSetting: UIEventSource<RasterLayerPolygon>, rasterLayerSetting: UIEventSource<RasterLayerPolygon>,
availableLayers: Store<RasterLayerPolygon[]>, availableLayers: { store: Store<RasterLayerPolygon[]> },
queryParameter: UIEventSource<string>, queryParameter: UIEventSource<string>,
preferredBackgroundLayer: UIEventSource< preferredBackgroundLayer: UIEventSource<
string | "photo" | "map" | "osmbasedmap" | undefined string | "photo" | "map" | "osmbasedmap" | undefined
> >,
) { ) {
this._rasterLayerSetting = rasterLayerSetting this._rasterLayerSetting = rasterLayerSetting
this._availableLayers = availableLayers this._availableLayers = availableLayers
@ -47,7 +47,13 @@ export class PreferredRasterLayerSelector {
this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer()) this._preferredBackgroundLayer.addCallbackD((_) => self.updateLayer())
this._availableLayers.addCallbackD((_) => self.updateLayer()) rasterLayerSetting.addCallbackAndRunD(layer => {
if (AvailableRasterLayers.globalLayers.find(l => l.id === layer.properties.id)) {
return
}
this._availableLayers.store.addCallbackD((_) => self.updateLayer())
return true // unregister
})
self.updateLayer() self.updateLayer()
} }
@ -58,9 +64,17 @@ export class PreferredRasterLayerSelector {
private updateLayer() { private updateLayer() {
// What is the ID of the layer we have to (try to) load? // What is the ID of the layer we have to (try to) load?
const targetLayerId = this._queryParameter.data ?? this._preferredBackgroundLayer.data const targetLayerId = this._queryParameter.data ?? this._preferredBackgroundLayer.data
const available = this._availableLayers.data if (targetLayerId === undefined || targetLayerId === "default") {
return
}
const global = AvailableRasterLayers.globalLayers.find(l => l.properties.id === targetLayerId)
if (global) {
this._rasterLayerSetting.setData(global)
return
}
const isCategory = const isCategory =
targetLayerId === "photo" || targetLayerId === "osmbasedmap" || targetLayerId === "map" targetLayerId === "photo" || targetLayerId === "osmbasedmap" || targetLayerId === "map"
const available = this._availableLayers.store.data
const foundLayer = isCategory const foundLayer = isCategory
? available.find((l) => l.properties.category === targetLayerId) ? available.find((l) => l.properties.category === targetLayerId)
: available.find((l) => l.properties.id === targetLayerId) : available.find((l) => l.properties.id === targetLayerId)

View file

@ -1,17 +1,33 @@
import { Feature, Polygon } from "geojson" import { Feature, Polygon } from "geojson"
import * as editorlayerindex from "../assets/editor-layer-index.json"
import * as globallayers from "../assets/global-raster-layers.json" import * as globallayers from "../assets/global-raster-layers.json"
import * as bingJson from "../assets/editor-layer-index.bing.json"
import { BBox } from "../Logic/BBox" import { BBox } from "../Logic/BBox"
import { Store, Stores } from "../Logic/UIEventSource" import { Store, Stores, UIEventSource } from "../Logic/UIEventSource"
import { GeoOperations } from "../Logic/GeoOperations" import { GeoOperations } from "../Logic/GeoOperations"
import { RasterLayerProperties } from "./RasterLayerProperties" import { RasterLayerProperties } from "./RasterLayerProperties"
import Constants from "./Constants" import { Utils } from "../Utils"
export type EditorLayerIndex = (Feature<Polygon, EditorLayerIndexProperties> &
RasterLayerPolygon)[]
export class AvailableRasterLayers { export class AvailableRasterLayers {
public static EditorLayerIndex: (Feature<Polygon, EditorLayerIndexProperties> & private static _editorLayerIndex: EditorLayerIndex = undefined
RasterLayerPolygon)[] = (<any>editorlayerindex.features).filter( private static _editorLayerIndexStore: UIEventSource<EditorLayerIndex> = new UIEventSource<EditorLayerIndex>(undefined)
(l) => l.properties.id !== "Bing"
) public static async editorLayerIndex(): Promise<EditorLayerIndex> {
if(AvailableRasterLayers._editorLayerIndex !== undefined){
return AvailableRasterLayers._editorLayerIndex
}
console.debug("Downloading ELI")
const eli = await Utils.downloadJson<{ features: EditorLayerIndex }>("./src/assets/editor-layer-index.json")
this._editorLayerIndex = eli.features.filter(l => l.properties.id !== "Bing")
this._editorLayerIndexStore.set(this._editorLayerIndex)
return this._editorLayerIndex
}
public static globalLayers: RasterLayerPolygon[] = globallayers.layers public static globalLayers: RasterLayerPolygon[] = globallayers.layers
.filter( .filter(
(properties) => (properties) =>
@ -25,9 +41,7 @@ export class AvailableRasterLayers {
geometry: BBox.global.asGeometry(), geometry: BBox.global.asGeometry(),
} }
) )
public static bing: RasterLayerPolygon = (<any>editorlayerindex.features).find( public static bing = <RasterLayerPolygon> bingJson
(l) => l.properties.id === "Bing"
)
public static readonly osmCartoProperties: RasterLayerProperties = { public static readonly osmCartoProperties: RasterLayerProperties = {
id: "osm", id: "osm",
name: "OpenStreetMap", name: "OpenStreetMap",
@ -56,17 +70,30 @@ export class AvailableRasterLayers {
return l.properties.id === "protomaps.sunny" return l.properties.id === "protomaps.sunny"
}) })
public static layersAvailableAt( public static layersAvailableAt( location: Store<{ lon: number; lat: number }>,
enableBing?: Store<boolean>): {store: Store<RasterLayerPolygon[]> } {
const store = {store: undefined}
Utils.AddLazyProperty(store, "store", () => AvailableRasterLayers._layersAvailableAt(location, enableBing))
return store
}
private static _layersAvailableAt(
location: Store<{ lon: number; lat: number }>, location: Store<{ lon: number; lat: number }>,
enableBing?: Store<boolean> enableBing?: Store<boolean>
): Store<RasterLayerPolygon[]> { ): Store<RasterLayerPolygon[]> {
this.editorLayerIndex() // start the download
const availableLayersBboxes = Stores.ListStabilized( const availableLayersBboxes = Stores.ListStabilized(
location.mapD((loc) => { location.mapD((loc) => {
const eli = AvailableRasterLayers._editorLayerIndexStore.data
if(!eli){
return []
}
const lonlat: [number, number] = [loc.lon, loc.lat] const lonlat: [number, number] = [loc.lon, loc.lat]
return AvailableRasterLayers.EditorLayerIndex.filter((eliPolygon) => return eli.filter((eliPolygon) =>
BBox.get(eliPolygon).contains(lonlat) BBox.get(eliPolygon).contains(lonlat)
) )
}) }, [AvailableRasterLayers._editorLayerIndexStore])
) )
return Stores.ListStabilized( return Stores.ListStabilized(
availableLayersBboxes.map( availableLayersBboxes.map(
@ -100,14 +127,6 @@ export class AvailableRasterLayers {
) )
} }
public static allIds(): Set<string> {
const all: string[] = []
all.push(...AvailableRasterLayers.globalLayers.map((l) => l.properties.id))
all.push(...AvailableRasterLayers.EditorLayerIndex.map((l) => l.properties.id))
all.push(this.osmCarto.properties.id)
all.push(this.defaultBackgroundLayer.properties.id)
return new Set<string>(all)
}
} }
export class RasterLayerUtils { export class RasterLayerUtils {

View file

@ -8,7 +8,6 @@ import { Utils } from "../../../Utils"
import { DetectDuplicatePresets, DoesImageExist, ValidateLanguageCompleteness } from "./Validation" import { DetectDuplicatePresets, DoesImageExist, ValidateLanguageCompleteness } from "./Validation"
export class ValidateTheme extends DesugaringStep<LayoutConfigJson> { export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
private static readonly _availableLayers = AvailableRasterLayers.allIds()
/** /**
* The paths where this layer is originally saved. Triggers some extra checks * The paths where this layer is originally saved. Triggers some extra checks
* @private * @private
@ -150,6 +149,8 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
} }
if (json.defaultBackgroundId) { if (json.defaultBackgroundId) {
/*
TODO re-enable this check
const backgroundId = json.defaultBackgroundId const backgroundId = json.defaultBackgroundId
const isCategory = const isCategory =
@ -165,7 +166,7 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
.slice(0, 5) .slice(0, 5)
.join(", ")}`, .join(", ")}`,
) )
} }*/
} }
for (let i = 0; i < theme.layers.length; i++) { for (let i = 0; i < theme.layers.length; i++) {

View file

@ -19,8 +19,6 @@ import { Utils } from "../../Utils"
import { TagsFilter } from "../../Logic/Tags/TagsFilter" import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import FilterConfigJson from "./Json/FilterConfigJson" import FilterConfigJson from "./Json/FilterConfigJson"
import { Overpass } from "../../Logic/Osm/Overpass" import { Overpass } from "../../Logic/Osm/Overpass"
import { ImmutableStore } from "../../Logic/UIEventSource"
import { OsmTags } from "../OsmFeature"
import Constants from "../Constants" import Constants from "../Constants"
import { QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson" import { QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson"
import MarkdownUtils from "../../Utils/MarkdownUtils" import MarkdownUtils from "../../Utils/MarkdownUtils"

View file

@ -2,11 +2,7 @@ import LayoutConfig from "./ThemeConfig/LayoutConfig"
import { SpecialVisualizationState } from "../UI/SpecialVisualization" import { SpecialVisualizationState } from "../UI/SpecialVisualization"
import { Changes } from "../Logic/Osm/Changes" import { Changes } from "../Logic/Osm/Changes"
import { Store, UIEventSource } from "../Logic/UIEventSource" import { Store, UIEventSource } from "../Logic/UIEventSource"
import { import { FeatureSource, IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource"
FeatureSource,
IndexedFeatureSource,
WritableFeatureSource,
} from "../Logic/FeatureSource/FeatureSource"
import { OsmConnection } from "../Logic/Osm/OsmConnection" import { OsmConnection } from "../Logic/Osm/OsmConnection"
import { ExportableMap, MapProperties } from "./MapProperties" import { ExportableMap, MapProperties } from "./MapProperties"
import LayerState from "../Logic/State/LayerState" import LayerState from "../Logic/State/LayerState"
@ -50,9 +46,7 @@ import BackgroundLayerResetter from "../Logic/Actors/BackgroundLayerResetter"
import SaveFeatureSourceToLocalStorage from "../Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage" import SaveFeatureSourceToLocalStorage from "../Logic/FeatureSource/Actors/SaveFeatureSourceToLocalStorage"
import BBoxFeatureSource from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource" import BBoxFeatureSource from "../Logic/FeatureSource/Sources/TouchesBboxFeatureSource"
import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor" import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor"
import NoElementsInViewDetector, { import NoElementsInViewDetector, { FeatureViewState } from "../Logic/Actors/NoElementsInViewDetector"
FeatureViewState,
} from "../Logic/Actors/NoElementsInViewDetector"
import FilteredLayer from "./FilteredLayer" import FilteredLayer from "./FilteredLayer"
import { PreferredRasterLayerSelector } from "../Logic/Actors/PreferredRasterLayerSelector" import { PreferredRasterLayerSelector } from "../Logic/Actors/PreferredRasterLayerSelector"
import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager" import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager"
@ -122,7 +116,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
readonly perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer> readonly perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>
readonly perLayerFiltered: ReadonlyMap<string, FilteringFeatureSource> readonly perLayerFiltered: ReadonlyMap<string, FilteringFeatureSource>
readonly availableLayers: Store<RasterLayerPolygon[]> readonly availableLayers: {store: Store<RasterLayerPolygon[]>}
readonly userRelatedState: UserRelatedState readonly userRelatedState: UserRelatedState
readonly geolocation: GeoLocationHandler readonly geolocation: GeoLocationHandler
readonly geolocationControl: GeolocationControlState readonly geolocationControl: GeolocationControlState
@ -153,7 +147,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false) public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false)
public readonly toCacheSavers: ReadonlyMap<string, SaveFeatureSourceToLocalStorage> public readonly toCacheSavers: ReadonlyMap<string, SaveFeatureSourceToLocalStorage>
public readonly nearbyImageSearcher public readonly nearbyImageSearcher: CombinedFetcher
constructor(layout: LayoutConfig, mvtAvailableLayers: Set<string>) { constructor(layout: LayoutConfig, mvtAvailableLayers: Set<string>) {
Utils.initDomPurify() Utils.initDomPurify()
@ -375,9 +369,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
longAgo.setTime(new Date().getTime() - 5 * 365 * 24 * 60 * 60 * 1000) longAgo.setTime(new Date().getTime() - 5 * 365 * 24 * 60 * 60 * 1000)
this.nearbyImageSearcher = new CombinedFetcher(50, longAgo, this.indexedFeatures) this.nearbyImageSearcher = new CombinedFetcher(50, longAgo, this.indexedFeatures)
this.featureSummary = this.setupSummaryLayer( this.featureSummary = this.setupSummaryLayer()
new LayerConfig(<LayerConfigJson>summaryLayer, "summaryLayer", true)
)
this.toCacheSavers = layout.enableCache ? this.initSaveToLocalStorage() : undefined this.toCacheSavers = layout.enableCache ? this.initSaveToLocalStorage() : undefined
this.initActors() this.initActors()
this.drawSpecialLayers() this.drawSpecialLayers()
@ -647,7 +639,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
} }
) )
const setLayerCategory = (category: EliCategory) => { const setLayerCategory = (category: EliCategory) => {
const available = this.availableLayers.data const available = this.availableLayers.store.data
const current = this.mapProperties.rasterLayer const current = this.mapProperties.rasterLayer
const best = RasterLayerUtils.SelectBestLayerAccordingTo( const best = RasterLayerUtils.SelectBestLayerAccordingTo(
available, available,
@ -696,7 +688,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
) )
} }
private setupSummaryLayer(summaryLayerConfig: LayerConfig): SummaryTileSourceRewriter { private setupSummaryLayer(): SummaryTileSourceRewriter {
/** /**
* MaxZoom for the summary layer * MaxZoom for the summary layer
*/ */
@ -723,8 +715,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
} }
) )
const src = new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers) return new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers)
return src
} }
/** /**

View file

@ -22,7 +22,7 @@ class SingleBackgroundHandler {
constructor( constructor(
map: Store<MLMap>, map: Store<MLMap>,
targetLayer: RasterLayerPolygon, targetLayer: RasterLayerPolygon,
background: UIEventSource<RasterLayerPolygon | undefined> background: UIEventSource<RasterLayerPolygon | undefined>,
) { ) {
this._targetLayer = targetLayer this._targetLayer = targetLayer
this._map = map this._map = map
@ -57,10 +57,15 @@ class SingleBackgroundHandler {
"Removing raster layer", "Removing raster layer",
this._targetLayer.properties.id, this._targetLayer.properties.id,
"map moved and not been used for", "map moved and not been used for",
SingleBackgroundHandler.DEACTIVATE_AFTER SingleBackgroundHandler.DEACTIVATE_AFTER,
) )
if (map.getLayer(<string>this._targetLayer.properties.id)) { try {
map.removeLayer(<string>this._targetLayer.properties.id)
if (map.getLayer(<string>this._targetLayer.properties.id)) {
map.removeLayer(<string>this._targetLayer.properties.id)
}
} catch (e) {
console.warn("Could not (try to) remove the raster layer", e)
} }
} }
@ -152,7 +157,7 @@ class SingleBackgroundHandler {
"raster-opacity": 0, "raster-opacity": 0,
}, },
}, },
addLayerBeforeId addLayerBeforeId,
) )
this.opacity.addCallbackAndRun((o) => { this.opacity.addCallbackAndRun((o) => {
try { try {
@ -170,14 +175,14 @@ class SingleBackgroundHandler {
private fadeOut() { private fadeOut() {
Stores.Chronic( Stores.Chronic(
8, 8,
() => this.opacity.data > 0 && this._deactivationTime !== undefined () => this.opacity.data > 0 && this._deactivationTime !== undefined,
).addCallback((_) => this.opacity.setData(Math.max(0, this.opacity.data - this.fadeStep))) ).addCallback((_) => this.opacity.setData(Math.max(0, this.opacity.data - this.fadeStep)))
} }
private fadeIn() { private fadeIn() {
Stores.Chronic( Stores.Chronic(
8, 8,
() => this.opacity.data < 1.0 && this._deactivationTime === undefined () => this.opacity.data < 1.0 && this._deactivationTime === undefined,
).addCallback((_) => this.opacity.setData(Math.min(1.0, this.opacity.data + this.fadeStep))) ).addCallback((_) => this.opacity.setData(Math.min(1.0, this.opacity.data + this.fadeStep)))
} }
} }
@ -195,7 +200,7 @@ export default class RasterLayerHandler {
} }
public static prepareSource( public static prepareSource(
layer: RasterLayerProperties layer: RasterLayerProperties,
): RasterSourceSpecification | VectorSourceSpecification { ): RasterSourceSpecification | VectorSourceSpecification {
if (layer.type === "vector") { if (layer.type === "vector") {
const vs: VectorSourceSpecification = { const vs: VectorSourceSpecification = {

View file

@ -12,11 +12,13 @@
import Translations from "../i18n/Translations" import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte" import Tr from "../Base/Tr.svelte"
import TitledPanel from "../Base/TitledPanel.svelte" import TitledPanel from "../Base/TitledPanel.svelte"
import Loading from "../Base/Loading.svelte"
export let availableLayers: Store<RasterLayerPolygon[]> export let availableLayers: {store: Store<RasterLayerPolygon[]>}
export let mapproperties: MapProperties export let mapproperties: MapProperties
export let userstate: UserRelatedState export let userstate: UserRelatedState
export let map: Store<MlMap> export let map: Store<MlMap>
let _availableLayers = availableLayers.store
/** /**
* Used to toggle the background layers on/off * Used to toggle the background layers on/off
*/ */
@ -32,8 +34,8 @@
function availableForCategory(type: CategoryType): Store<RasterLayerPolygon[]> { function availableForCategory(type: CategoryType): Store<RasterLayerPolygon[]> {
const keywords = categories[type] const keywords = categories[type]
return availableLayers.mapD((available) => return _availableLayers.mapD((available) =>
available.filter((layer) => keywords.indexOf(<EliCategory>layer.properties.category) >= 0) available.filter((layer) => keywords.indexOf(<EliCategory>layer.properties.category) >= 0),
) )
} }
@ -53,39 +55,42 @@
<TitledPanel> <TitledPanel>
<Tr slot="title" t={Translations.t.general.backgroundMap} /> <Tr slot="title" t={Translations.t.general.backgroundMap} />
{#if $_availableLayers?.length < 1}
<div class="grid h-full w-full grid-cols-1 gap-2 md:grid-cols-2"> <Loading />
<RasterLayerPicker {:else }
availableLayers={photoLayers} <div class="grid h-full w-full grid-cols-1 gap-2 md:grid-cols-2">
favourite={getPref("photo")} <RasterLayerPicker
{map} availableLayers={$photoLayers}
{mapproperties} favourite={getPref("photo")}
on:appliedLayer={onApply} {map}
{visible} {mapproperties}
/> on:appliedLayer={onApply}
<RasterLayerPicker {visible}
availableLayers={mapLayers} />
favourite={getPref("map")} <RasterLayerPicker
{map} availableLayers={$mapLayers}
{mapproperties} favourite={getPref("map")}
on:appliedLayer={onApply} {map}
{visible} {mapproperties}
/> on:appliedLayer={onApply}
<RasterLayerPicker {visible}
availableLayers={osmbasedmapLayers} />
favourite={getPref("osmbasedmap")} <RasterLayerPicker
{map} availableLayers={$osmbasedmapLayers}
{mapproperties} favourite={getPref("osmbasedmap")}
on:appliedLayer={onApply} {map}
{visible} {mapproperties}
/> on:appliedLayer={onApply}
<RasterLayerPicker {visible}
availableLayers={otherLayers} />
favourite={getPref("other")} <RasterLayerPicker
{map} availableLayers={$otherLayers}
{mapproperties} favourite={getPref("other")}
on:appliedLayer={onApply} {map}
{visible} {mapproperties}
/> on:appliedLayer={onApply}
</div> {visible}
/>
</div>
{/if}
</TitledPanel> </TitledPanel>

View file

@ -9,7 +9,7 @@
/*** /***
* Chooses a background-layer out of available options * Chooses a background-layer out of available options
*/ */
export let availableLayers: Store<RasterLayerPolygon[]> export let availableLayers: RasterLayerPolygon[]
export let mapproperties: MapProperties export let mapproperties: MapProperties
export let map: Store<MlMap> export let map: Store<MlMap>
@ -19,34 +19,26 @@
export let favourite: UIEventSource<string> | undefined = undefined export let favourite: UIEventSource<string> | undefined = undefined
let rasterLayer = new UIEventSource<RasterLayerPolygon>(availableLayers.data?.[0]) let rasterLayer = new UIEventSource<RasterLayerPolygon>(availableLayers[0])
let hasLayers = true let rasterLayerId = rasterLayer.sync(l => l?.properties?.id, [], id => availableLayers.find(l => l.properties.id === id))
onDestroy( rasterLayer.setData(availableLayers[0])
availableLayers.addCallbackAndRun((layers) => { $: rasterLayer.setData(availableLayers[0])
if (layers === undefined || layers.length === 0) {
hasLayers = false
return
}
hasLayers = true
rasterLayer.setData(layers[0])
})
)
if (favourite) { if (favourite) {
onDestroy( onDestroy(
favourite.addCallbackAndRunD((favourite) => { favourite.addCallbackAndRunD((favourite) => {
const fav = availableLayers.data?.find((l) => l.properties.id === favourite) const fav = availableLayers?.find((l) => l.properties.id === favourite)
if (!fav) { if (!fav) {
return return
} }
rasterLayer.setData(fav) rasterLayer.setData(fav)
}) }),
) )
onDestroy( onDestroy(
rasterLayer.addCallbackAndRunD((selected) => { rasterLayer.addCallbackAndRunD((selected) => {
favourite?.setData(selected.properties.id) favourite?.setData(selected.properties.id)
}) }),
) )
} }
@ -56,13 +48,14 @@
onDestroy( onDestroy(
visible?.addCallbackAndRunD((visible) => { visible?.addCallbackAndRunD((visible) => {
if (visible) { if (visible) {
rasterLayerOnMap.setData(rasterLayer.data ?? availableLayers.data[0]) rasterLayerOnMap.setData(rasterLayer.data ?? availableLayers[0])
} else { } else {
rasterLayerOnMap.setData(undefined) rasterLayerOnMap.setData(undefined)
} }
}) }),
) )
} }
function apply() { function apply() {
mapproperties.rasterLayer.setData(rasterLayer.data) mapproperties.rasterLayer.setData(rasterLayer.data)
dispatch("appliedLayer") dispatch("appliedLayer")
@ -75,7 +68,7 @@
} }
</script> </script>
{#if hasLayers} {#if availableLayers?.length > 0}
<form class="flex h-full w-full flex-col" on:submit|preventDefault={() => {}}> <form class="flex h-full w-full flex-col" on:submit|preventDefault={() => {}}>
<button <button
tabindex="-1" tabindex="-1"
@ -92,9 +85,9 @@
/> />
</span> </span>
</button> </button>
<select bind:value={$rasterLayer} class="w-full" on:keydown={handleKeyPress}> <select bind:value={$rasterLayerId} class="w-full" on:keydown={handleKeyPress}>
{#each $availableLayers as availableLayer} {#each availableLayers as availableLayer}
<option value={availableLayer}> <option value={availableLayer.properties.id}>
{availableLayer.properties.name} {availableLayer.properties.name}
</option> </option>
{/each} {/each}

View file

@ -88,8 +88,6 @@ export interface SpecialVisualizationState {
readonly language: UIEventSource<string> readonly language: UIEventSource<string>
} }
readonly availableLayers: Store<RasterLayerPolygon[]>
readonly imageUploadManager: ImageUploadManager readonly imageUploadManager: ImageUploadManager
readonly previewedImage: UIEventSource<ProvidedImage> readonly previewedImage: UIEventSource<ProvidedImage>

View file

@ -0,0 +1 @@
{"properties":{"name":"Bing Maps Aerial","id":"Bing","url":"https://ecn.t0.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=14634&pr=odbl&n=f","type":"bing","category":"photo","min_zoom":1,"max_zoom":22},"type":"Feature","geometry":null}

File diff suppressed because one or more lines are too long