diff --git a/Logic/Actors/OverpassFeatureSource.ts b/Logic/Actors/OverpassFeatureSource.ts index 7560e6c03a..bd2e9c4b0e 100644 --- a/Logic/Actors/OverpassFeatureSource.ts +++ b/Logic/Actors/OverpassFeatureSource.ts @@ -13,15 +13,15 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import Constants from "../../Models/Constants" import TileFreshnessCalculator from "../FeatureSource/TileFreshnessCalculator" import { Tiles } from "../../Models/TileRange" +import { Feature } from "geojson" export default class OverpassFeatureSource implements FeatureSource { public readonly name = "OverpassFeatureSource" /** - * The last loaded features of the geojson + * The last loaded features, as geojson */ - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = - new UIEventSource(undefined) + public readonly features: UIEventSource = new UIEventSource(undefined) public readonly runningQuery: UIEventSource = new UIEventSource(false) public readonly timeout: UIEventSource = new UIEventSource(0) @@ -243,7 +243,6 @@ export default class OverpassFeatureSource implements FeatureSource { data.features.forEach((feature) => SimpleMetaTagger.objectMetaInfo.applyMetaTagsOnFeature( feature, - date, undefined, this.state ) diff --git a/Logic/FeatureSource/Actors/MetaTagRecalculator.ts b/Logic/FeatureSource/Actors/MetaTagRecalculator.ts index 982939d4a6..165279b92c 100644 --- a/Logic/FeatureSource/Actors/MetaTagRecalculator.ts +++ b/Logic/FeatureSource/Actors/MetaTagRecalculator.ts @@ -101,7 +101,7 @@ export default class MetaTagRecalculator { } } - public registerSource(source: FeatureSourceForLayer & Tiled, recalculateOnEveryChange = false) { + public registerSource(source: FeatureSourceForLayer & Tiled) { if (source === undefined) { return } diff --git a/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts b/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts index 01ad3917b5..756c11da3b 100644 --- a/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts +++ b/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts @@ -1,20 +1,19 @@ -import FeatureSource from "../FeatureSource" -import { Store } from "../../UIEventSource" -import { ElementStorage } from "../../ElementStorage" +import FeatureSource from "../FeatureSource"; +import { Store } from "../../UIEventSource"; +import { ElementStorage } from "../../ElementStorage"; +import { Feature } from "geojson"; /** * Makes sure that every feature is added to the ElementsStorage, so that the tags-eventsource can be retrieved */ export default class RegisteringAllFromFeatureSourceActor { - public readonly features: Store<{ feature: any; freshness: Date }[]> - public readonly name + public readonly features: Store constructor(source: FeatureSource, allElements: ElementStorage) { this.features = source.features - this.name = "RegisteringSource of " + source.name this.features.addCallbackAndRunD((features) => { for (const feature of features) { - allElements.addOrGetElement(feature.feature) + allElements.addOrGetElement( feature) } }) } diff --git a/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts b/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts index 12ef0e5742..9cf1b1de51 100644 --- a/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts +++ b/Logic/FeatureSource/Actors/SaveTileToLocalStorageActor.ts @@ -7,6 +7,7 @@ import { BBox } from "../../BBox" import SimpleFeatureSource from "../Sources/SimpleFeatureSource" import FilteredLayer from "../../../Models/FilteredLayer" import Loc from "../../../Models/Loc" +import { Feature } from "geojson" /*** * Saves all the features that are passed in to localstorage, so they can be retrieved on the next run @@ -82,7 +83,7 @@ export default class SaveTileToLocalStorageActor { continue } loadedTiles.add(key) - this.GetIdb(key).then((features: { feature: any; freshness: Date }[]) => { + this.GetIdb(key).then((features: Feature[]) => { if (features === undefined) { return } @@ -90,7 +91,7 @@ export default class SaveTileToLocalStorageActor { const src = new SimpleFeatureSource( self._flayer, key, - new UIEventSource<{ feature: any; freshness: Date }[]>(features) + new UIEventSource(features) ) registerTile(src) }) diff --git a/Logic/FeatureSource/FeaturePipeline.ts b/Logic/FeatureSource/FeaturePipeline.ts index e398294d65..edfac8fbdc 100644 --- a/Logic/FeatureSource/FeaturePipeline.ts +++ b/Logic/FeatureSource/FeaturePipeline.ts @@ -136,7 +136,7 @@ export default class FeaturePipeline { // Passthrough to passed function, except that it registers as well handleFeatureSource(src) src.features.addCallbackAndRunD((fs) => { - fs.forEach((ff) => state.allElements.addOrGetElement(ff.feature)) + fs.forEach((ff) => state.allElements.addOrGetElement(ff)) }) } @@ -422,7 +422,7 @@ export default class FeaturePipeline { } return TileHierarchyTools.getTiles(requestedHierarchy, bbox) .filter((featureSource) => featureSource.features?.data !== undefined) - .map((featureSource) => featureSource.features.data.map((fs) => fs.feature)) + .map((featureSource) => featureSource.features.data) } public GetTilesPerLayerWithin( @@ -639,10 +639,7 @@ export default class FeaturePipeline { * Inject a new point */ InjectNewPoint(geojson) { - this.newGeometryHandler.features.data.push({ - feature: geojson, - freshness: new Date(), - }) + this.newGeometryHandler.features.data.push(geojson) this.newGeometryHandler.features.ping() } } diff --git a/Logic/FeatureSource/FeatureSource.ts b/Logic/FeatureSource/FeatureSource.ts index c5460ff685..243b8efd96 100644 --- a/Logic/FeatureSource/FeatureSource.ts +++ b/Logic/FeatureSource/FeatureSource.ts @@ -1,15 +1,10 @@ -import { Store, UIEventSource } from "../UIEventSource" +import { Store } from "../UIEventSource" import FilteredLayer from "../../Models/FilteredLayer" import { BBox } from "../BBox" -import { Feature, Geometry } from "@turf/turf" -import { OsmFeature } from "../../Models/OsmFeature" +import { Feature } from "geojson" export default interface FeatureSource { - features: Store<{ feature: OsmFeature; freshness: Date }[]> - /** - * Mainly used for debuging - */ - name: string + features: Store } export interface Tiled { diff --git a/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts b/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts index 6b6bfd330b..ef92543a7f 100644 --- a/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts +++ b/Logic/FeatureSource/PerLayerFeatureSourceSplitter.ts @@ -2,6 +2,7 @@ import FeatureSource, { FeatureSourceForLayer, Tiled } from "./FeatureSource" import { Store } from "../UIEventSource" import FilteredLayer from "../../Models/FilteredLayer" import SimpleFeatureSource from "./Sources/SimpleFeatureSource" +import { Feature } from "geojson" /** * In some rare cases, some elements are shown on multiple layers (when 'passthrough' is enabled) @@ -32,7 +33,7 @@ export default class PerLayerFeatureSourceSplitter { // We try to figure out (for each feature) in which feature store it should be saved. // Note that this splitter is only run when it is invoked by the overpass feature source, so we can't be sure in which layer it should go - const featuresPerLayer = new Map() + const featuresPerLayer = new Map() const noLayerFound = [] for (const layer of layers.data) { @@ -42,7 +43,7 @@ export default class PerLayerFeatureSourceSplitter { for (const f of features) { let foundALayer = false for (const layer of layers.data) { - if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { + if (layer.layerDef.source.osmTags.matchesProperties(f.properties)) { // We have found our matching layer! featuresPerLayer.get(layer.layerDef.id).push(f) foundALayer = true diff --git a/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts b/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts index 0bac2ab6dc..fb92d69c67 100644 --- a/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts +++ b/Logic/FeatureSource/Sources/ChangeGeometryApplicator.ts @@ -6,11 +6,11 @@ import { UIEventSource } from "../../UIEventSource" import { FeatureSourceForLayer, IndexedFeatureSource } from "../FeatureSource" import FilteredLayer from "../../../Models/FilteredLayer" import { ChangeDescription, ChangeDescriptionTools } from "../../Osm/Actions/ChangeDescription" +import { Feature } from "geojson" export default class ChangeGeometryApplicator implements FeatureSourceForLayer { - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = - new UIEventSource<{ feature: any; freshness: Date }[]>([]) - public readonly name: string + public readonly features: UIEventSource = + new UIEventSource([]) public readonly layer: FilteredLayer private readonly source: IndexedFeatureSource private readonly changes: Changes @@ -20,8 +20,7 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { this.changes = changes this.layer = source.layer - this.name = "ChangesApplied(" + source.name + ")" - this.features = new UIEventSource<{ feature: any; freshness: Date }[]>(undefined) + this.features = new UIEventSource(undefined) const self = this source.features.addCallbackAndRunD((_) => self.update()) @@ -58,9 +57,9 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { changesPerId.set(key, [ch]) } } - const newFeatures: { feature: any; freshness: Date }[] = [] + const newFeatures: Feature[] = [] for (const feature of upstreamFeatures) { - const changesForFeature = changesPerId.get(feature.feature.properties.id) + const changesForFeature = changesPerId.get(feature.properties.id) if (changesForFeature === undefined) { // No changes for this element newFeatures.push(feature) @@ -73,7 +72,7 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { } // We only apply the last change as that one'll have the latest geometry const change = changesForFeature[changesForFeature.length - 1] - copy.feature.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) + copy.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) console.log( "Applying a geometry change onto:", feature, diff --git a/Logic/FeatureSource/Sources/FeatureSourceMerger.ts b/Logic/FeatureSource/Sources/FeatureSourceMerger.ts index 248a9d9d98..8034ab6975 100644 --- a/Logic/FeatureSource/Sources/FeatureSourceMerger.ts +++ b/Logic/FeatureSource/Sources/FeatureSourceMerger.ts @@ -1,16 +1,13 @@ import { UIEventSource } from "../../UIEventSource" import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "../FeatureSource" import FilteredLayer from "../../../Models/FilteredLayer" -import { Tiles } from "../../../Models/TileRange" import { BBox } from "../../BBox" +import { Feature } from "geojson" export default class FeatureSourceMerger implements FeatureSourceForLayer, Tiled, IndexedFeatureSource { - public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< - { feature: any; freshness: Date }[] - >([]) - public readonly name + public features: UIEventSource = new UIEventSource([]) public readonly layer: FilteredLayer public readonly tileIndex: number public readonly bbox: BBox @@ -32,12 +29,6 @@ export default class FeatureSourceMerger this.bbox = bbox this._sources = sources this.layer = layer - this.name = - "FeatureSourceMerger(" + - layer.layerDef.id + - ", " + - Tiles.tile_from_index(tileIndex).join(",") + - ")" const self = this const handledSources = new Set() @@ -63,14 +54,11 @@ export default class FeatureSourceMerger private Update() { let somethingChanged = false - const all: Map = new Map< - string, - { feature: any; freshness: Date } - >() + const all: Map = new Map() // We seed the dictionary with the previously loaded features const oldValues = this.features.data ?? [] for (const oldValue of oldValues) { - all.set(oldValue.feature.id, oldValue) + all.set(oldValue.properties.id, oldValue) } for (const source of this._sources.data) { @@ -78,7 +66,7 @@ export default class FeatureSourceMerger continue } for (const f of source.features.data) { - const id = f.feature.properties.id + const id = f.properties.id if (!all.has(id)) { // This is a new feature somethingChanged = true @@ -89,11 +77,11 @@ export default class FeatureSourceMerger // This value has been seen already, either in a previous run or by a previous datasource // Let's figure out if something changed const oldV = all.get(id) - if (oldV.freshness < f.freshness) { - // Jup, this feature is fresher - all.set(id, f) - somethingChanged = true + if (oldV === f) { + continue } + all.set(id, f) + somethingChanged = true } } diff --git a/Logic/FeatureSource/Sources/FilteringFeatureSource.ts b/Logic/FeatureSource/Sources/FilteringFeatureSource.ts index 9bb3546256..2a36553731 100644 --- a/Logic/FeatureSource/Sources/FilteringFeatureSource.ts +++ b/Logic/FeatureSource/Sources/FilteringFeatureSource.ts @@ -4,13 +4,10 @@ import { FeatureSourceForLayer, Tiled } from "../FeatureSource" import { BBox } from "../../BBox" import { ElementStorage } from "../../ElementStorage" import { TagsFilter } from "../../Tags/TagsFilter" -import { OsmFeature } from "../../../Models/OsmFeature" +import { Feature } from "geojson" export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled { - public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< - { feature: any; freshness: Date }[] - >([]) - public readonly name + public features: UIEventSource = new UIEventSource([]) public readonly layer: FilteredLayer public readonly tileIndex: number public readonly bbox: BBox @@ -36,7 +33,6 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti upstream: FeatureSourceForLayer, metataggingUpdated?: UIEventSource ) { - this.name = "FilteringFeatureSource(" + upstream.name + ")" this.tileIndex = tileIndex this.bbox = tileIndex === undefined ? undefined : BBox.fromTileIndex(tileIndex) this.upstream = upstream @@ -73,15 +69,14 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti private update() { const self = this const layer = this.upstream.layer - const features: { feature: OsmFeature; freshness: Date }[] = - this.upstream.features.data ?? [] + const features: Feature[] = this.upstream.features.data ?? [] const includedFeatureIds = new Set() const globalFilters = self.state.globalFilters?.data?.map((f) => f.filter) const newFeatures = (features ?? []).filter((f) => { - self.registerCallback(f.feature) + self.registerCallback(f) const isShown: TagsFilter = layer.layerDef.isShown - const tags = f.feature.properties + const tags = f.properties if (isShown !== undefined && !isShown.matchesProperties(tags)) { return false } @@ -92,10 +87,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti const tagsFilter = Array.from(layer.appliedFilters?.data?.values() ?? []) for (const filter of tagsFilter) { const neededTags: TagsFilter = filter?.currentFilter - if ( - neededTags !== undefined && - !neededTags.matchesProperties(f.feature.properties) - ) { + if (neededTags !== undefined && !neededTags.matchesProperties(f.properties)) { // Hidden by the filter on the layer itself - we want to hide it no matter what return false } @@ -103,16 +95,13 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti for (const filter of globalFilters ?? []) { const neededTags: TagsFilter = filter?.currentFilter - if ( - neededTags !== undefined && - !neededTags.matchesProperties(f.feature.properties) - ) { + if (neededTags !== undefined && !neededTags.matchesProperties(f.properties)) { // Hidden by the filter on the layer itself - we want to hide it no matter what return false } } - includedFeatureIds.add(f.feature.properties.id) + includedFeatureIds.add(f.properties.id) return true }) diff --git a/Logic/FeatureSource/Sources/GeoJsonSource.ts b/Logic/FeatureSource/Sources/GeoJsonSource.ts index 5c0ecb9e91..99525508bf 100644 --- a/Logic/FeatureSource/Sources/GeoJsonSource.ts +++ b/Logic/FeatureSource/Sources/GeoJsonSource.ts @@ -8,9 +8,10 @@ import { FeatureSourceForLayer, Tiled } from "../FeatureSource" import { Tiles } from "../../../Models/TileRange" import { BBox } from "../../BBox" import { GeoOperations } from "../../GeoOperations" +import { Feature } from "geojson" export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> + public readonly features: UIEventSource public readonly state = new UIEventSource(undefined) public readonly name public readonly isOsmCache: boolean @@ -69,7 +70,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { this.name = "GeoJsonSource of " + url this.isOsmCache = flayer.layerDef.source.isOsmCacheLayer - this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) + this.features = new UIEventSource([]) this.LoadJSONFrom(url) } @@ -110,7 +111,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { } const time = new Date() - const newFeatures: { feature: any; freshness: Date }[] = [] + const newFeatures: Feature[] = [] let i = 0 let skipped = 0 for (const feature of json.features) { @@ -146,7 +147,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { freshness = new Date(props["_last_edit:timestamp"]) } - newFeatures.push({ feature: feature, freshness: freshness }) + newFeatures.push(feature) } if (newFeatures.length == 0) { diff --git a/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts b/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts index 6829a25a4d..86e92ae8f6 100644 --- a/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts +++ b/Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource.ts @@ -5,6 +5,7 @@ import { UIEventSource } from "../../UIEventSource" import { ChangeDescription } from "../../Osm/Actions/ChangeDescription" import { ElementStorage } from "../../ElementStorage" import { OsmId, OsmTags } from "../../../Models/OsmFeature" +import { Feature } from "geojson" export class NewGeometryFromChangesFeatureSource implements FeatureSource { // This class name truly puts the 'Java' into 'Javascript' @@ -15,9 +16,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { * These elements are probably created by the 'SimpleAddUi' which generates a new point, but the import functionality might create a line or polygon too. * Other sources of new points are e.g. imports from nodes */ - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = - new UIEventSource<{ feature: any; freshness: Date }[]>([]) - public readonly name: string = "newFeatures" + public readonly features: UIEventSource = new UIEventSource([]) constructor(changes: Changes, allElementStorage: ElementStorage, backendUrl: string) { const seenChanges = new Set() @@ -29,15 +28,11 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { return } - const now = new Date() let somethingChanged = false function add(feature) { feature.id = feature.properties.id - features.push({ - feature: feature, - freshness: now, - }) + features.push(feature) somethingChanged = true } @@ -71,7 +66,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { } const geojson = feat.asGeoJson() allElementStorage.addOrGetElement(geojson) - self.features.data.push({ feature: geojson, freshness: new Date() }) + self.features.data.push(geojson) self.features.ping() }) continue diff --git a/Logic/FeatureSource/Sources/RememberingSource.ts b/Logic/FeatureSource/Sources/RememberingSource.ts index 5d71541c4c..fcc4b7f016 100644 --- a/Logic/FeatureSource/Sources/RememberingSource.ts +++ b/Logic/FeatureSource/Sources/RememberingSource.ts @@ -5,28 +5,25 @@ import FeatureSource, { Tiled } from "../FeatureSource" import { Store, UIEventSource } from "../../UIEventSource" import { BBox } from "../../BBox" +import { Feature } from "geojson" export default class RememberingSource implements FeatureSource, Tiled { - public readonly features: Store<{ feature: any; freshness: Date }[]> - public readonly name + public readonly features: Store public readonly tileIndex: number public readonly bbox: BBox constructor(source: FeatureSource & Tiled) { const self = this - this.name = "RememberingSource of " + source.name this.tileIndex = source.tileIndex this.bbox = source.bbox const empty = [] - const featureSource = new UIEventSource<{ feature: any; freshness: Date }[]>(empty) + const featureSource = new UIEventSource(empty) this.features = featureSource source.features.addCallbackAndRunD((features) => { const oldFeatures = self.features?.data ?? empty // Then new ids - const ids = new Set( - features.map((f) => f.feature.properties.id + f.feature.geometry.type) - ) + const ids = new Set(features.map((f) => f.properties.id + f.geometry.type)) // the old data const oldData = oldFeatures.filter( (old) => !ids.has(old.feature.properties.id + old.feature.geometry.type) diff --git a/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts b/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts index 6a07fb7aaa..0b929713e2 100644 --- a/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts +++ b/Logic/FeatureSource/Sources/RenderingMultiPlexerFeatureSource.ts @@ -1,13 +1,12 @@ -/** - * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. - */ import { Store } from "../../UIEventSource" import { GeoOperations } from "../../GeoOperations" import FeatureSource from "../FeatureSource" import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig" import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" import LineRenderingConfig from "../../../Models/ThemeConfig/LineRenderingConfig" - +/** + * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. + */ export default class RenderingMultiPlexerFeatureSource { public readonly features: Store< (any & { @@ -64,8 +63,7 @@ export default class RenderingMultiPlexerFeatureSource { withIndex.push(patched) } - for (const f of features) { - const feat = f.feature + for (const feat of features) { if (feat === undefined) { continue } diff --git a/Logic/FeatureSource/Sources/SimpleFeatureSource.ts b/Logic/FeatureSource/Sources/SimpleFeatureSource.ts index f2dfec6788..ca08543374 100644 --- a/Logic/FeatureSource/Sources/SimpleFeatureSource.ts +++ b/Logic/FeatureSource/Sources/SimpleFeatureSource.ts @@ -2,23 +2,18 @@ import { UIEventSource } from "../../UIEventSource" import FilteredLayer from "../../../Models/FilteredLayer" import { FeatureSourceForLayer, Tiled } from "../FeatureSource" import { BBox } from "../../BBox" +import { Feature } from "geojson" export default class SimpleFeatureSource implements FeatureSourceForLayer, Tiled { - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> - public readonly name: string = "SimpleFeatureSource" + public readonly features: UIEventSource public readonly layer: FilteredLayer public readonly bbox: BBox = BBox.global public readonly tileIndex: number - constructor( - layer: FilteredLayer, - tileIndex: number, - featureSource?: UIEventSource<{ feature: any; freshness: Date }[]> - ) { - this.name = "SimpleFeatureSource(" + layer.layerDef.id + ")" + constructor(layer: FilteredLayer, tileIndex: number, featureSource?: UIEventSource) { this.layer = layer this.tileIndex = tileIndex ?? 0 this.bbox = BBox.fromTileIndex(this.tileIndex) - this.features = featureSource ?? new UIEventSource<{ feature: any; freshness: Date }[]>([]) + this.features = featureSource ?? new UIEventSource([]) } } diff --git a/Logic/FeatureSource/Sources/StaticFeatureSource.ts b/Logic/FeatureSource/Sources/StaticFeatureSource.ts index d99304a47f..97d6600cc8 100644 --- a/Logic/FeatureSource/Sources/StaticFeatureSource.ts +++ b/Logic/FeatureSource/Sources/StaticFeatureSource.ts @@ -8,63 +8,34 @@ import { Feature } from "geojson" * A simple, read only feature store. */ export default class StaticFeatureSource implements FeatureSource { - public readonly features: Store<{ feature: any; freshness: Date }[]> - public readonly name: string + public readonly features: Store constructor( - features: Store<{ feature: Feature; freshness: Date }[]>, - name = "StaticFeatureSource" + features: + | Store + | Feature[] + | { features: Feature[] } + | { features: Store } ) { if (features === undefined) { throw "Static feature source received undefined as source" } - this.name = name - this.features = features + let feats: Feature[] | Store + if (features["features"]) { + feats = features["features"] + } else { + feats = >features + } + + if (Array.isArray(feats)) { + this.features = new ImmutableStore(feats) + } else { + this.features = feats + } } - public static fromGeojsonAndDate( - features: { feature: Feature; freshness: Date }[], - name = "StaticFeatureSourceFromGeojsonAndDate" - ): StaticFeatureSource { - return new StaticFeatureSource(new ImmutableStore(features), name) - } - - public static fromGeojson( - geojson: Feature[], - name = "StaticFeatureSourceFromGeojson" - ): StaticFeatureSource { - const now = new Date() - return StaticFeatureSource.fromGeojsonAndDate( - geojson.map((feature) => ({ feature, freshness: now })), - name - ) - } - - public static fromGeojsonStore( - geojson: Store, - name = "StaticFeatureSourceFromGeojson" - ): StaticFeatureSource { - const now = new Date() - const mapped: Store<{ feature: Feature; freshness: Date }[]> = geojson.map((features) => - features.map((feature) => ({ feature, freshness: now })) - ) - return new StaticFeatureSource(mapped, name) - } - - static fromDateless( - featureSource: Store<{ feature: Feature }[]>, - name = "StaticFeatureSourceFromDateless" - ) { - const now = new Date() - return new StaticFeatureSource( - featureSource.map((features) => - features.map((feature) => ({ - feature: feature.feature, - freshness: now, - })) - ), - name - ) + public static fromGeojson(geojson: Feature[]): StaticFeatureSource { + return new StaticFeatureSource(geojson) } } @@ -76,11 +47,7 @@ export class TiledStaticFeatureSource public readonly tileIndex: number public readonly layer: FilteredLayer - constructor( - features: Store<{ feature: any; freshness: Date }[]>, - layer: FilteredLayer, - tileIndex: number = 0 - ) { + constructor(features: Store, layer: FilteredLayer, tileIndex: number = 0) { super(features) this.tileIndex = tileIndex this.layer = layer diff --git a/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts b/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts index f312d0a355..13225ed152 100644 --- a/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts @@ -53,11 +53,9 @@ export default class FullNodeDatabaseSource implements TileHierarchy ({ - feature: osmNode.asGeoJson(), - freshness: now, - })) + const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => + osmNode.asGeoJson() + ) const featureSource = new SimpleFeatureSource(this.layer, tileId) featureSource.features.setData(asGeojsonFeatures) diff --git a/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts b/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts index 849ea4c7d2..d2ada64268 100644 --- a/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts @@ -175,7 +175,7 @@ export default class OsmFeatureSource { new PerLayerFeatureSourceSplitter( this.filteredLayers, this.handleTile, - StaticFeatureSource.fromGeojson(geojson.features), + new StaticFeatureSource(geojson.features), { tileIndex: index, } diff --git a/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts b/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts index 9327ec7066..d49bf16d3e 100644 --- a/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource.ts @@ -4,6 +4,7 @@ import FilteredLayer from "../../../Models/FilteredLayer" import TileHierarchy from "./TileHierarchy" import { Tiles } from "../../../Models/TileRange" import { BBox } from "../../BBox" +import { Feature } from "geojson"; /** * Contains all features in a tiled fashion. @@ -29,7 +30,7 @@ export default class TiledFeatureSource public readonly maxFeatureCount: number public readonly name - public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> + public readonly features: UIEventSource public readonly containedIds: Store> public readonly bbox: BBox @@ -80,7 +81,7 @@ export default class TiledFeatureSource if (features === undefined) { return undefined } - return new Set(features.map((f) => f.feature.properties.id)) + return new Set(features.map((f) => f.properties.id)) }) // We register this tile, but only when there is some data in it @@ -132,7 +133,7 @@ export default class TiledFeatureSource * @param features * @private */ - private addFeatures(features: { feature: any; freshness: Date }[]) { + private addFeatures(features: Feature[]) { if (features === undefined || features.length === 0) { return } @@ -180,7 +181,7 @@ export default class TiledFeatureSource const overlapsboundary = [] for (const feature of features) { - const bbox = BBox.get(feature.feature) + const bbox = BBox.get(feature) // There are a few strategies to deal with features that cross tile boundaries diff --git a/Logic/MetaTagging.ts b/Logic/MetaTagging.ts index 47d698ac02..68fb03a3de 100644 --- a/Logic/MetaTagging.ts +++ b/Logic/MetaTagging.ts @@ -2,6 +2,7 @@ import SimpleMetaTaggers, { SimpleMetaTagger } from "./SimpleMetaTagger" import { ExtraFuncParams, ExtraFunctions } from "./ExtraFunctions" import LayerConfig from "../Models/ThemeConfig/LayerConfig" import { ElementStorage } from "./ElementStorage" +import { Feature } from "geojson" /** * Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ... @@ -20,7 +21,7 @@ export default class MetaTagging { * Returns true if at least one feature has changed properties */ public static addMetatags( - features: { feature: any; freshness: Date }[], + features: Feature[], params: ExtraFuncParams, layer: LayerConfig, state?: { allElements?: ElementStorage }, @@ -55,8 +56,7 @@ export default class MetaTagging { for (let i = 0; i < features.length; i++) { const ff = features[i] - const feature = ff.feature - const freshness = ff.freshness + const feature = ff let somethingChanged = false let definedTags = new Set(Object.getOwnPropertyNames(feature.properties)) for (const metatag of metatagsToApply) { @@ -72,19 +72,14 @@ export default class MetaTagging { continue } somethingChanged = true - metatag.applyMetaTagsOnFeature(feature, freshness, layer, state) + metatag.applyMetaTagsOnFeature(feature, layer, state) if (options?.evaluateStrict) { for (const key of metatag.keys) { feature.properties[key] } } } else { - const newValueAdded = metatag.applyMetaTagsOnFeature( - feature, - freshness, - layer, - state - ) + const newValueAdded = metatag.applyMetaTagsOnFeature(feature, layer, state) /* Note that the expression: * `somethingChanged = newValueAdded || metatag.applyMetaTagsOnFeature(feature, freshness)` * Is WRONG diff --git a/Logic/SimpleMetaTagger.ts b/Logic/SimpleMetaTagger.ts index eb8479e7fe..1a0fbb8fde 100644 --- a/Logic/SimpleMetaTagger.ts +++ b/Logic/SimpleMetaTagger.ts @@ -17,12 +17,7 @@ export class SimpleMetaTagger { public readonly doc: string public readonly isLazy: boolean public readonly includesDates: boolean - public readonly applyMetaTagsOnFeature: ( - feature: any, - freshness: Date, - layer: LayerConfig, - state - ) => boolean + public readonly applyMetaTagsOnFeature: (feature: any, layer: LayerConfig, state) => boolean /*** * A function that adds some extra data to a feature @@ -41,7 +36,7 @@ export class SimpleMetaTagger { isLazy?: boolean cleanupRetagger?: boolean }, - f: (feature: any, freshness: Date, layer: LayerConfig, state) => boolean + f: (feature: any, layer: LayerConfig, state) => boolean ) { this.keys = docs.keys this.doc = docs.doc @@ -71,7 +66,7 @@ export class ReferencingWaysMetaTagger extends SimpleMetaTagger { isLazy: true, doc: "_referencing_ways contains - for a node - which ways use this this node as point in their geometry. ", }, - (feature, _, __, state) => { + (feature, _, state) => { if (!ReferencingWaysMetaTagger.enabled) { return false } @@ -116,7 +111,7 @@ export class CountryTagger extends SimpleMetaTagger { doc: "The country code of the property (with latlon2country)", includesDates: false, }, - (feature, _, __, state) => { + (feature, _, state) => { let centerPoint: any = GeoOperations.centerpoint(feature) const lat = centerPoint.geometry.coordinates[1] const lon = centerPoint.geometry.coordinates[0] @@ -236,7 +231,7 @@ export default class SimpleMetaTaggers { keys: ["_layer"], includesDates: false, }, - (feature, freshness, layer) => { + (feature, _, layer) => { if (feature.properties._layer === layer.id) { return false } @@ -322,7 +317,7 @@ export default class SimpleMetaTaggers { doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`; `1` will be rewritten to `1m` as well)", keys: ["Theme-defined keys"], }, - (feature, _, __, state) => { + (feature, _, state) => { const units = Utils.NoNull( [].concat(...(state?.layoutToUse?.layers?.map((layer) => layer.units) ?? [])) ) @@ -395,7 +390,7 @@ export default class SimpleMetaTaggers { includesDates: true, isLazy: true, }, - (feature, _, __, state) => { + (feature, _, state) => { if (Utils.runningFromConsole) { // We are running from console, thus probably creating a cache // isOpen is irrelevant @@ -508,17 +503,13 @@ export default class SimpleMetaTaggers { private static currentTime = new SimpleMetaTagger( { - keys: ["_now:date", "_now:datetime", "_loaded:date", "_loaded:_datetime"], + keys: ["_now:date", "_now:datetime"], doc: "Adds the time that the data got loaded - pretty much the time of downloading from overpass. The format is YYYY-MM-DD hh:mm, aka 'sortable' aka ISO-8601-but-not-entirely", includesDates: true, }, - (feature, freshness) => { + (feature) => { const now = new Date() - if (typeof freshness === "string") { - freshness = new Date(freshness) - } - function date(d: Date) { return d.toISOString().slice(0, 10) } @@ -529,8 +520,6 @@ export default class SimpleMetaTaggers { feature.properties["_now:date"] = date(now) feature.properties["_now:datetime"] = datetime(now) - feature.properties["_loaded:date"] = date(freshness) - feature.properties["_loaded:datetime"] = datetime(freshness) return true } ) diff --git a/Logic/State/FeaturePipelineState.ts b/Logic/State/FeaturePipelineState.ts index 8c56a0aacf..60e9fa7881 100644 --- a/Logic/State/FeaturePipelineState.ts +++ b/Logic/State/FeaturePipelineState.ts @@ -57,7 +57,7 @@ export default class FeaturePipelineState extends MapState { function registerSource(source: FeatureSourceForLayer & Tiled) { clusterCounter.addTile(source) const sourceBBox = source.features.map((allFeatures) => - BBox.bboxAroundAll(allFeatures.map((f) => BBox.get(f.feature))) + BBox.bboxAroundAll(allFeatures.map(BBox.get)) ) // Do show features indicates if the respective 'showDataLayer' should be shown. It can be hidden by e.g. clustering @@ -131,7 +131,7 @@ export default class FeaturePipelineState extends MapState { handleRawFeatureSource: registerRaw, }) this.metatagRecalculator = new MetaTagRecalculator(this, this.featurePipeline) - this.metatagRecalculator.registerSource(this.currentView, true) + this.metatagRecalculator.registerSource(this.currentView) sourcesToRegister.forEach((source) => self.metatagRecalculator.registerSource(source)) diff --git a/Logic/State/MapState.ts b/Logic/State/MapState.ts index 59b1770442..724797585a 100644 --- a/Logic/State/MapState.ts +++ b/Logic/State/MapState.ts @@ -213,38 +213,33 @@ export default class MapState extends UserRelatedState { let i = 0 const self = this - const features: Store<{ feature: any; freshness: Date }[]> = this.currentBounds.map( - (bounds) => { - if (bounds === undefined) { - return [] - } - i++ - const feature = { - freshness: new Date(), - feature: { - type: "Feature", - properties: { - id: "current_view-" + i, - current_view: "yes", - zoom: "" + self.locationControl.data.zoom, - }, - geometry: { - type: "Polygon", - coordinates: [ - [ - [bounds.maxLon, bounds.maxLat], - [bounds.minLon, bounds.maxLat], - [bounds.minLon, bounds.minLat], - [bounds.maxLon, bounds.minLat], - [bounds.maxLon, bounds.maxLat], - ], - ], - }, - }, - } - return [feature] + const features: Store = this.currentBounds.map((bounds) => { + if (bounds === undefined) { + return [] } - ) + i++ + const feature = { + type: "Feature", + properties: { + id: "current_view-" + i, + current_view: "yes", + zoom: "" + self.locationControl.data.zoom, + }, + geometry: { + type: "Polygon", + coordinates: [ + [ + [bounds.maxLon, bounds.maxLat], + [bounds.minLon, bounds.maxLat], + [bounds.minLon, bounds.minLat], + [bounds.maxLon, bounds.minLat], + [bounds.maxLon, bounds.maxLat], + ], + ], + }, + } + return [feature] + }) this.currentView = new TiledStaticFeatureSource(features, currentViewLayer) } diff --git a/Models/OsmFeature.ts b/Models/OsmFeature.ts index aee5f08fb3..d8ff8928ee 100644 --- a/Models/OsmFeature.ts +++ b/Models/OsmFeature.ts @@ -1,4 +1,4 @@ -import { Feature, Geometry } from "@turf/turf" +import { Feature, Geometry } from "geojson" export type RelationId = `relation/${number}` export type WayId = `way/${number}` diff --git a/UI/ImportFlow/CompareToAlreadyExistingNotes.ts b/UI/ImportFlow/CompareToAlreadyExistingNotes.ts index c936c7921f..56cc4932d3 100644 --- a/UI/ImportFlow/CompareToAlreadyExistingNotes.ts +++ b/UI/ImportFlow/CompareToAlreadyExistingNotes.ts @@ -106,7 +106,7 @@ export class CompareToAlreadyExistingNotes state, zoomToFeatures: true, leafletMap: comparisonMap.leafletMap, - features: StaticFeatureSource.fromGeojsonStore( + features: new StaticFeatureSource( partitionedImportPoints.map((p) => p.hasNearby) ), popup: (tags, layer) => new FeatureInfoBox(tags, layer, state), diff --git a/UI/ImportFlow/ConflationChecker.ts b/UI/ImportFlow/ConflationChecker.ts index 1b18e67220..5ec1de4434 100644 --- a/UI/ImportFlow/ConflationChecker.ts +++ b/UI/ImportFlow/ConflationChecker.ts @@ -166,7 +166,7 @@ export default class ConflationChecker [osmLiveData.bounds, zoomLevel.GetValue()] ) - const preview = StaticFeatureSource.fromGeojsonStore(geojsonFeatures) + const preview = new StaticFeatureSource(geojsonFeatures) new ShowDataLayer({ layerToShow: new LayerConfig(currentview), @@ -225,7 +225,7 @@ export default class ConflationChecker }, [nearbyCutoff.GetValue().stabilized(500)] ) - const nearbyFeatures = StaticFeatureSource.fromGeojsonStore(geojsonMapped) + const nearbyFeatures = new StaticFeatureSource(geojsonMapped) const paritionedImport = ImportUtils.partitionFeaturesIfNearby( toImport, geojson, @@ -233,7 +233,7 @@ export default class ConflationChecker ) // Featuresource showing OSM-features which are nearby a toImport-feature - const toImportWithNearby = StaticFeatureSource.fromGeojsonStore( + const toImportWithNearby = new StaticFeatureSource( paritionedImport.map((els) => els?.hasNearby ?? []) ) toImportWithNearby.features.addCallback((nearby) => diff --git a/UI/ImportFlow/MapPreview.ts b/UI/ImportFlow/MapPreview.ts index 9348db65b1..9fb71489de 100644 --- a/UI/ImportFlow/MapPreview.ts +++ b/UI/ImportFlow/MapPreview.ts @@ -8,8 +8,6 @@ import Constants from "../../Models/Constants" import { DropDown } from "../Input/DropDown" import { Utils } from "../../Utils" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" -import BaseLayer from "../../Models/BaseLayer" -import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" import Loc from "../../Models/Loc" import Minimap from "../Base/Minimap" import Attribution from "../BigComponents/Attribution" @@ -140,9 +138,7 @@ export class MapPreview new ShowDataLayer({ layerToShow, zoomToFeatures: true, - features: StaticFeatureSource.fromDateless( - matching.map((features) => features.map((feature) => ({ feature }))) - ), + features: new StaticFeatureSource(matching), leafletMap: map.leafletMap, popup: (tag) => new PreviewPanel(tag), }) diff --git a/UI/Input/LocationInput.ts b/UI/Input/LocationInput.ts index 56f20f4451..38518392cd 100644 --- a/UI/Input/LocationInput.ts +++ b/UI/Input/LocationInput.ts @@ -53,7 +53,7 @@ export default class LocationInput * Used for rendering * @private */ - private readonly _snapToRaw: Store<{ feature: Feature }[]> + private readonly _snapToRaw: Store private readonly _value: Store private readonly _snappedPoint: Store private readonly _maxSnapDistance: number @@ -112,7 +112,7 @@ export default class LocationInput constructor(options?: { minZoom?: number mapBackground?: UIEventSource - snapTo?: UIEventSource<{ feature: Feature }[]> + snapTo?: UIEventSource renderLayerForSnappedPoint?: LayerConfig maxSnapDistance?: number snappedPointTags?: any @@ -276,7 +276,7 @@ export default class LocationInput if (this._snapToRaw !== undefined) { // Show the lines to snap to new ShowDataMultiLayer({ - features: StaticFeatureSource.fromDateless(this._snapToRaw), + features: new StaticFeatureSource(this._snapToRaw), zoomToFeatures: false, leafletMap: this.map.leafletMap, layers: this._state.filteredLayers, @@ -286,12 +286,12 @@ export default class LocationInput if (loc === undefined) { return [] } - return [{ feature: loc }] + return [loc] }) // The 'matchlayer' is the layer which shows the target location new ShowDataLayer({ - features: StaticFeatureSource.fromDateless(matchPoint), + features: new StaticFeatureSource(matchPoint), zoomToFeatures: false, leafletMap: this.map.leafletMap, layerToShow: this._matching_layer, diff --git a/UI/NewPoint/ConfirmLocationOfPoint.ts b/UI/NewPoint/ConfirmLocationOfPoint.ts index df10191c56..8aed2d01d0 100644 --- a/UI/NewPoint/ConfirmLocationOfPoint.ts +++ b/UI/NewPoint/ConfirmLocationOfPoint.ts @@ -3,7 +3,6 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection" import FeaturePipeline from "../../Logic/FeatureSource/FeaturePipeline" import BaseUIElement from "../BaseUIElement" import LocationInput from "../Input/LocationInput" -import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" import { BBox } from "../../Logic/BBox" import { TagUtils } from "../../Logic/Tags/TagUtils" import { SubtleButton } from "../Base/SubtleButton" @@ -12,7 +11,6 @@ import Translations from "../i18n/Translations" import Svg from "../../Svg" import Toggle from "../Input/Toggle" import SimpleAddUI, { PresetInfo } from "../BigComponents/SimpleAddUI" -import BaseLayer from "../../Models/BaseLayer" import Img from "../Base/Img" import Title from "../Base/Title" import { GlobalFilter } from "../../Logic/State/MapState" @@ -20,6 +18,8 @@ import { VariableUiElement } from "../Base/VariableUIElement" import { Tag } from "../../Logic/Tags/Tag" import { WayId } from "../../Models/OsmFeature" import { Translation } from "../i18n/Translation" +import { Feature } from "geojson"; +import { AvailableRasterLayers, RasterLayerPolygon } from "../../Models/RasterLayers"; export default class ConfirmLocationOfPoint extends Combine { constructor( @@ -28,7 +28,7 @@ export default class ConfirmLocationOfPoint extends Combine { featureSwitchIsTesting: UIEventSource osmConnection: OsmConnection featurePipeline: FeaturePipeline - backgroundLayer?: UIEventSource + backgroundLayer?: UIEventSource }, filterViewIsOpened: UIEventSource, preset: PresetInfo, @@ -55,10 +55,10 @@ export default class ConfirmLocationOfPoint extends Combine { const locationSrc = new UIEventSource(zloc) let backgroundLayer = new UIEventSource( - state?.backgroundLayer?.data ?? AvailableBaseLayers.osmCarto + state?.backgroundLayer?.data ?? AvailableRasterLayers.osmCarto ) if (preset.preciseInput.preferredBackground) { - const defaultBackground = AvailableBaseLayers.SelectBestLayerAccordingTo( + const defaultBackground = AvailableRasterLayers.SelectBestLayerAccordingTo( locationSrc, new UIEventSource(preset.preciseInput.preferredBackground) ) @@ -66,10 +66,10 @@ export default class ConfirmLocationOfPoint extends Combine { backgroundLayer.setData(defaultBackground.data) } - let snapToFeatures: UIEventSource<{ feature: any }[]> = undefined + let snapToFeatures: UIEventSource = undefined let mapBounds: UIEventSource = undefined if (preset.preciseInput.snapToLayers && preset.preciseInput.snapToLayers.length > 0) { - snapToFeatures = new UIEventSource<{ feature: any }[]>([]) + snapToFeatures = new UIEventSource< Feature[]>([]) mapBounds = new UIEventSource(undefined) } @@ -105,13 +105,13 @@ export default class ConfirmLocationOfPoint extends Combine { Math.max(preset.boundsFactor ?? 0.25, 2) ) loadedBbox = bbox - const allFeatures: { feature: any }[] = [] + const allFeatures: Feature[] = [] preset.preciseInput.snapToLayers.forEach((layerId) => { console.log("Snapping to", layerId) state.featurePipeline .GetFeaturesWithin(layerId, bbox) ?.forEach((feats) => - allFeatures.push(...feats.map((f) => ({ feature: f }))) + allFeatures.push(...feats) ) }) console.log("Snapping to", allFeatures) diff --git a/test.ts b/test.ts index 23dde7df0b..167ce125a7 100644 --- a/test.ts +++ b/test.ts @@ -1,20 +1,17 @@ import SvelteUIElement from "./UI/Base/SvelteUIElement" import MaplibreMap from "./UI/Map/MaplibreMap.svelte" -import { ImmutableStore, UIEventSource } from "./Logic/UIEventSource" +import { UIEventSource } from "./Logic/UIEventSource" import { MapLibreAdaptor } from "./UI/Map/MapLibreAdaptor" import { AvailableRasterLayers, RasterLayerPolygon } from "./Models/RasterLayers" import type { Map as MlMap } from "maplibre-gl" -import RasterLayerPicker from "./UI/Map/RasterLayerPicker.svelte" -import BackgroundLayerResetter from "./Logic/Actors/BackgroundLayerResetter" import { ShowDataLayer } from "./UI/Map/ShowDataLayer" -import StaticFeatureSource from "./Logic/FeatureSource/Sources/StaticFeatureSource" -import { Layer } from "leaflet" import LayerConfig from "./Models/ThemeConfig/LayerConfig" import * as bench from "./assets/generated/layers/bench.json" import { Utils } from "./Utils" import SimpleFeatureSource from "./Logic/FeatureSource/Sources/SimpleFeatureSource" import { FilterState } from "./Models/FilteredLayer" import { FixedUiElement } from "./UI/Base/FixedUiElement" + async function main() { const mlmap = new UIEventSource(undefined) const location = new UIEventSource<{ lon: number; lat: number }>({