From 292bad5df74941e86e3e2dbed3af9e80622ed67b Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Fri, 7 May 2021 01:43:32 +0200 Subject: [PATCH] Stabilize popup --- Logic/FeatureSource/FeatureSourceMerger.ts | 43 +++++++++--- Logic/FeatureSource/FilteringFeatureSource.ts | 2 +- Logic/FeatureSource/OsmApiFeatureSource.ts | 2 - Logic/Osm/OsmObject.ts | 67 +++++++++++-------- Models/Constants.ts | 2 +- UI/ShowDataLayer.ts | 3 +- 6 files changed, 74 insertions(+), 45 deletions(-) diff --git a/Logic/FeatureSource/FeatureSourceMerger.ts b/Logic/FeatureSource/FeatureSourceMerger.ts index 76c4c5211..9ceef4429 100644 --- a/Logic/FeatureSource/FeatureSourceMerger.ts +++ b/Logic/FeatureSource/FeatureSourceMerger.ts @@ -21,27 +21,48 @@ export default class FeatureSourceMerger implements FeatureSource { } private Update() { - let all = {}; // Mapping 'id' -> {feature, freshness} + + let somethingChanged = false; + 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) + } + for (const source of this._sources) { if (source?.features?.data === undefined) { continue; } for (const f of source.features.data) { const id = f.feature.properties.id; - const oldV = all[id]; - if (oldV === undefined) { - all[id] = f; - } else { - if (oldV.freshness < f.freshness) { - all[id] = f; - } + if (!all.has(id)) { + // This is a new feature + somethingChanged = true; + all.set(id, f); + continue; + } + + // 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; } } } - const newList = []; - for (const id in all) { - newList.push(all[id]); + + if(!somethingChanged){ + // We don't bother triggering an update + return; } + + const newList = []; + all.forEach((value, key) => { + newList.push(value) + }) this.features.setData(newList); } diff --git a/Logic/FeatureSource/FilteringFeatureSource.ts b/Logic/FeatureSource/FilteringFeatureSource.ts index b883f271b..e4c8b0f34 100644 --- a/Logic/FeatureSource/FilteringFeatureSource.ts +++ b/Logic/FeatureSource/FilteringFeatureSource.ts @@ -34,7 +34,7 @@ export default class FilteringFeatureSource implements FeatureSource { const newFeatures = features.filter(f => { const layerId = f.feature._matching_layer_id; - if(selectedElement.data === f.feature){ + if(selectedElement.data !== undefined && selectedElement.data?.id === f.feature.id){ // This is the selected object - it gets a free pass even if zoom is not sufficient return true; } diff --git a/Logic/FeatureSource/OsmApiFeatureSource.ts b/Logic/FeatureSource/OsmApiFeatureSource.ts index 4805511d6..13d2e4d82 100644 --- a/Logic/FeatureSource/OsmApiFeatureSource.ts +++ b/Logic/FeatureSource/OsmApiFeatureSource.ts @@ -22,10 +22,8 @@ export default class OsmApiFeatureSource implements FeatureSource { public load(id: string) { - console.log("Updating from OSM API: ", id) OsmObject.DownloadObject(id, (element, meta) => { const geojson = element.asGeoJson(); - console.warn(geojson) geojson.id = geojson.properties.id; this.features.setData([{feature: geojson, freshness: meta["_last_edit:timestamp"]}]) }) diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index ed74876be..5de7fd591 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -67,6 +67,36 @@ export abstract class OsmObject { }) } + private static ParseObjects(elements: any[]) : OsmObject[]{ + const objects: OsmObject[] = []; + const allNodes: Map = new Map() + for (const element of elements) { + const type = element.type; + const idN = element.id; + let osmObject: OsmObject = null + switch (type) { + case("node"): + const node = new OsmNode(idN); + allNodes.set(idN, node); + osmObject = node + node.SaveExtraData(element); + break; + case("way"): + osmObject = new OsmWay(idN); + const nodes = element.nodes.map(i => allNodes.get(i)); + osmObject.SaveExtraData(element, nodes) + break; + case("relation"): + osmObject = new OsmRelation(idN); + osmObject.SaveExtraData(element, []) + break; + } + osmObject.LoadData(element) + objects.push(osmObject) + } + return objects; + } + //Loads an area from the OSM-api. // bounds should be: [[maxlat, minlon], [minlat, maxlon]] (same as Utils.tile_bounds) public static LoadArea(bounds: [[number, number], [number, number]], callback: (objects: OsmObject[]) => void) { @@ -77,32 +107,7 @@ export abstract class OsmObject { const url = `https://www.openstreetmap.org/api/0.6/map.json?bbox=${minlon},${minlat},${maxlon},${maxlat}` $.getJSON(url, data => { const elements: any[] = data.elements; - const objects: OsmObject[] = []; - const allNodes: Map = new Map() - for (const element of elements) { - const type = element.type; - const idN = element.id; - let osmObject: OsmObject = null - switch (type) { - case("node"): - const node = new OsmNode(idN); - allNodes.set(idN, node); - osmObject = node - node.SaveExtraData(element); - break; - case("way"): - osmObject = new OsmWay(idN); - const nodes = element.nodes.map(i => allNodes.get(i)); - osmObject.SaveExtraData(element, nodes) - break; - case("relation"): - osmObject = new OsmRelation(idN); - osmObject.SaveExtraData(element, []) - break; - } - osmObject.LoadData(element) - objects.push(osmObject) - } + const objects = OsmObject.ParseObjects(elements) callback(objects); }) @@ -157,10 +162,16 @@ export abstract class OsmObject { const full = this.type !== "way" ? "" : "/full"; const url = "https://www.openstreetmap.org/api/0.6/" + this.type + "/" + this.id + full; $.getJSON(url, function (data) { - const element = data.elements[data.elements.length - 1]; + + const element = data.elements.pop(); + let nodes = [] + if(data.elements.length > 2){ + nodes = OsmObject.ParseObjects(data.elements) + } + self.LoadData(element) - self.SaveExtraData(element, data.elements); + self.SaveExtraData(element, nodes); continuation(self, { "_last_edit:contributor": element.user, diff --git a/Models/Constants.ts b/Models/Constants.ts index 85a3f16cf..f1e8195c1 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import { Utils } from "../Utils"; export default class Constants { - public static vNumber = "0.7.1"; + public static vNumber = "0.7.1b"; // The user journey states thresholds when a new feature gets unlocked public static userJourney = { diff --git a/UI/ShowDataLayer.ts b/UI/ShowDataLayer.ts index 4ebe82e45..2eb7437f4 100644 --- a/UI/ShowDataLayer.ts +++ b/UI/ShowDataLayer.ts @@ -162,9 +162,8 @@ export default class ShowDataLayer { leafletLayer.on("popupopen", () => { State.state.selectedElement.setData(feature) }); - + this._popups.set(feature, leafletLayer); - } private CreateGeojsonLayer(): L.Layer {