From d4e63d90e4afb9a446bca2f352533f1a505006d6 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Sun, 10 Oct 2021 00:53:14 +0200 Subject: [PATCH] When a logged-in user opens a popup, the latest data will be downloaded and tags are updated to prevent duplicate work, fix #505 --- .gitignore | 1 + Logic/Actors/SelectedElementTagsUpdater.ts | 100 +++++++++++++++++++++ Logic/Osm/Actions/ChangeDescription.ts | 2 + State.ts | 3 + 4 files changed, 106 insertions(+) create mode 100644 Logic/Actors/SelectedElementTagsUpdater.ts diff --git a/.gitignore b/.gitignore index f2ff425f8..b2ad34580 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ missing_translations.txt .DS_Store Svg.ts data/ +Folder.DotSettings.user diff --git a/Logic/Actors/SelectedElementTagsUpdater.ts b/Logic/Actors/SelectedElementTagsUpdater.ts new file mode 100644 index 000000000..bb46734d2 --- /dev/null +++ b/Logic/Actors/SelectedElementTagsUpdater.ts @@ -0,0 +1,100 @@ +/** + * This actor will download the latest version of the selected element from OSM and update the tags if necessary. + */ +import {UIEventSource} from "../UIEventSource"; +import {ElementStorage} from "../ElementStorage"; +import {Changes} from "../Osm/Changes"; +import {OsmObject} from "../Osm/OsmObject"; +import {OsmConnection} from "../Osm/OsmConnection"; + +export default class SelectedElementTagsUpdater { + + constructor(state: { + selectedElement: UIEventSource, + allElements: ElementStorage, + changes: Changes, + osmConnection: OsmConnection + }) { + + + state.osmConnection.isLoggedIn.addCallbackAndRun(isLoggedIn => { + if(isLoggedIn){ + SelectedElementTagsUpdater.installCallback(state) + return true; + } + }) + + } + + private static installCallback(state: { + selectedElement: UIEventSource, + allElements: ElementStorage, + changes: Changes, + osmConnection: OsmConnection + }) { + + + state.selectedElement.addCallbackAndRunD(s => { + const id = s.properties?.id + OsmObject.DownloadObjectAsync(id).then(obj => { + SelectedElementTagsUpdater.applyUpdate(state, obj, id) + }).catch(e => { + console.error("Could not update tags of ", id, "due to", e) + }) + }); + + } + + private static applyUpdate(state: { + selectedElement: UIEventSource, + allElements: ElementStorage, + changes: Changes, + osmConnection: OsmConnection + }, obj: OsmObject, id: string + ) { + const pendingChanges = state.changes.pendingChanges.data + .filter(change => change.type === obj.type && change.id === obj.id) + .filter(change => change.tags !== undefined); + const latestTags = obj.tags + console.log("Applying updates of ", id, " got tags", latestTags, "and still have to apply changes: ", pendingChanges) + + for (const pendingChange of pendingChanges) { + const tagChanges = pendingChange.tags; + for (const tagChange of tagChanges) { + const key = tagChange.k + const v = tagChange.v + if (v === undefined || v === "") { + delete latestTags[key] + } else { + latestTags[key] = v + } + } + } + + // With the changes applied, we merge them onto the upstream object + let somethingChanged = false; + const currentTagsSource = state.allElements.getEventSourceById(id); + const currentTags = currentTagsSource.data + for (const key in latestTags) { + let osmValue = latestTags[key] + + if(typeof osmValue === "number"){ + osmValue = ""+osmValue + } + + const localValue = currentTags[key] + if (localValue !== osmValue) { + console.log("Local value:", localValue, "upstream", osmValue) + somethingChanged = true; + currentTags[key] = osmValue + } + } + if (somethingChanged) { + console.log("Detected upstream changes to the object when opening it, updating...") + currentTagsSource.ping() + } + + } + + +} \ No newline at end of file diff --git a/Logic/Osm/Actions/ChangeDescription.ts b/Logic/Osm/Actions/ChangeDescription.ts index 1787d1b1b..55ced2f2a 100644 --- a/Logic/Osm/Actions/ChangeDescription.ts +++ b/Logic/Osm/Actions/ChangeDescription.ts @@ -18,6 +18,8 @@ export interface ChangeDescription { /** * All changes to tags * v = "" or v = undefined to erase this tag + * + * Note that this list will only contain the _changes_ to the tags, not the full set of tags */ tags?: { k: string, v: string }[], diff --git a/State.ts b/State.ts index 7279136b3..cdc61c57e 100644 --- a/State.ts +++ b/State.ts @@ -18,6 +18,7 @@ import FilteredLayer from "./Models/FilteredLayer"; import ChangeToElementsActor from "./Logic/Actors/ChangeToElementsActor"; import LayoutConfig from "./Models/ThemeConfig/LayoutConfig"; import {BBox} from "./Logic/BBox"; +import SelectedElementTagsUpdater from "./Logic/Actors/SelectedElementTagsUpdater"; /** * Contains the global state: a bunch of UI-event sources @@ -376,6 +377,8 @@ export default class State { new ChangeToElementsActor(this.changes, this.allElements) new PendingChangesUploader(this.changes, this.selectedElement); + + new SelectedElementTagsUpdater(this) this.mangroveIdentity = new MangroveIdentity( this.osmConnection.GetLongPreference("identity", "mangrove")