forked from MapComplete/MapComplete
		
	When a logged-in user opens a popup, the latest data will be downloaded and tags are updated to prevent duplicate work, fix #505
This commit is contained in:
		
							parent
							
								
									adf02af5fe
								
							
						
					
					
						commit
						d4e63d90e4
					
				
					 4 changed files with 106 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -17,3 +17,4 @@ missing_translations.txt
 | 
				
			||||||
.DS_Store
 | 
					.DS_Store
 | 
				
			||||||
Svg.ts
 | 
					Svg.ts
 | 
				
			||||||
data/
 | 
					data/
 | 
				
			||||||
 | 
					Folder.DotSettings.user
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										100
									
								
								Logic/Actors/SelectedElementTagsUpdater.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Logic/Actors/SelectedElementTagsUpdater.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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<any>,
 | 
				
			||||||
 | 
					        allElements: ElementStorage,
 | 
				
			||||||
 | 
					        changes: Changes,
 | 
				
			||||||
 | 
					        osmConnection: OsmConnection
 | 
				
			||||||
 | 
					    }) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.osmConnection.isLoggedIn.addCallbackAndRun(isLoggedIn => {
 | 
				
			||||||
 | 
					            if(isLoggedIn){
 | 
				
			||||||
 | 
					                SelectedElementTagsUpdater.installCallback(state)
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private static installCallback(state: {
 | 
				
			||||||
 | 
					        selectedElement: UIEventSource<any>,
 | 
				
			||||||
 | 
					        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<any>,
 | 
				
			||||||
 | 
					                                   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()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,8 @@ export interface ChangeDescription {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * All changes to tags
 | 
					     * All changes to tags
 | 
				
			||||||
     * v = "" or v = undefined to erase this tag
 | 
					     * 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 }[],
 | 
					    tags?: { k: string, v: string }[],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								State.ts
									
										
									
									
									
								
							| 
						 | 
					@ -18,6 +18,7 @@ import FilteredLayer from "./Models/FilteredLayer";
 | 
				
			||||||
import ChangeToElementsActor from "./Logic/Actors/ChangeToElementsActor";
 | 
					import ChangeToElementsActor from "./Logic/Actors/ChangeToElementsActor";
 | 
				
			||||||
import LayoutConfig from "./Models/ThemeConfig/LayoutConfig";
 | 
					import LayoutConfig from "./Models/ThemeConfig/LayoutConfig";
 | 
				
			||||||
import {BBox} from "./Logic/BBox";
 | 
					import {BBox} from "./Logic/BBox";
 | 
				
			||||||
 | 
					import SelectedElementTagsUpdater from "./Logic/Actors/SelectedElementTagsUpdater";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Contains the global state: a bunch of UI-event sources
 | 
					 * Contains the global state: a bunch of UI-event sources
 | 
				
			||||||
| 
						 | 
					@ -377,6 +378,8 @@ export default class State {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        new PendingChangesUploader(this.changes, this.selectedElement);
 | 
					        new PendingChangesUploader(this.changes, this.selectedElement);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        new SelectedElementTagsUpdater(this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.mangroveIdentity = new MangroveIdentity(
 | 
					        this.mangroveIdentity = new MangroveIdentity(
 | 
				
			||||||
            this.osmConnection.GetLongPreference("identity", "mangrove")
 | 
					            this.osmConnection.GetLongPreference("identity", "mangrove")
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue