| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Handles all changes made to OSM. | 
					
						
							|  |  |  |  * Needs an authenticator via OsmConnection | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | import {UIEventSource} from "../../UI/UIEventSource"; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | import {OsmConnection} from "./OsmConnection"; | 
					
						
							|  |  |  | import {OsmNode, OsmObject} from "./OsmObject"; | 
					
						
							| 
									
										
										
										
											2020-07-30 00:59:08 +02:00
										 |  |  | import {And, Tag, TagsFilter} from "../TagsFilter"; | 
					
						
							|  |  |  | import {ElementStorage} from "../ElementStorage"; | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  | import {State} from "../../State"; | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  | import {Utils} from "../../Utils"; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class Changes { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static _nextId = -1; // New assined ID's are negative
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |     private _pendingChanges: { elementId: string, key: string, value: string }[] = []; // Gets reset on uploadAll
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     private newElements: OsmObject[] = []; // Gets reset on uploadAll
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |     public readonly pendingChangesES = new UIEventSource<number>(this._pendingChanges.length); | 
					
						
							|  |  |  |     public readonly isSaving = new UIEventSource(false); | 
					
						
							|  |  |  |     private readonly _changesetComment: string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     constructor( | 
					
						
							|  |  |  |         changesetComment: string, | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |         state: State) { | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         this._changesetComment = changesetComment; | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.SetupAutoSave(state); | 
					
						
							|  |  |  |         this.LastEffortSave(); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     addTag(elementId: string, tagsFilter : TagsFilter){ | 
					
						
							|  |  |  |         if(tagsFilter instanceof  Tag){ | 
					
						
							|  |  |  |             const tag = tagsFilter as Tag; | 
					
						
							|  |  |  |             this.addChange(elementId, tag.key, tag.value); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         if(tagsFilter instanceof And){ | 
					
						
							|  |  |  |             const and = tagsFilter as And; | 
					
						
							|  |  |  |             for (const tag of and.and) { | 
					
						
							|  |  |  |                 this.addTag(elementId, tag); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.log("Unsupported tagsfilter element to addTag", tagsFilter); | 
					
						
							|  |  |  |         throw "Unsupported tagsFilter element"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Adds a change to the pending changes | 
					
						
							|  |  |  |      * @param elementId | 
					
						
							|  |  |  |      * @param key | 
					
						
							|  |  |  |      * @param value | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     addChange(elementId: string, key: string, value: string) { | 
					
						
							|  |  |  |         if (key === undefined || key === null) { | 
					
						
							|  |  |  |             console.log("Invalid key"); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (value === undefined || value === null) { | 
					
						
							|  |  |  |             console.log("Invalid value for ",key); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-06 19:42:10 +02:00
										 |  |  |          | 
					
						
							|  |  |  |         if(key.startsWith(" ") || value.startsWith(" ") || value.endsWith(" ") || key.endsWith(" ")){ | 
					
						
							|  |  |  |             console.warn("Tag starts with or ends with a space - trimming anyway") | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         key = key.trim(); | 
					
						
							|  |  |  |         value = value.trim(); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const eventSource = State.state.allElements.getElement(elementId); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         eventSource.data[key] = value; | 
					
						
							|  |  |  |         eventSource.ping(); | 
					
						
							|  |  |  |         // We get the id from the event source, as that ID might be rewritten
 | 
					
						
							|  |  |  |         this._pendingChanges.push({elementId: eventSource.data.id, key: key, value: value}); | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         this.pendingChangesES.setData(this._pendingChanges.length); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a new node element at the given lat/long. | 
					
						
							|  |  |  |      * An internal OsmObject is created to upload later on, a geojson represention is returned. | 
					
						
							|  |  |  |      * Note that the geojson version shares the tags (properties) by pointer, but has _no_ id in properties | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     createElement(basicTags:Tag[], lat: number, lon: number) { | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |         console.log("Creating a new element with ", basicTags) | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         const osmNode = new OsmNode(Changes._nextId); | 
					
						
							|  |  |  |         this.newElements.push(osmNode); | 
					
						
							|  |  |  |         Changes._nextId--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const id = "node/" + osmNode.id; | 
					
						
							|  |  |  |         osmNode.lat = lat; | 
					
						
							|  |  |  |         osmNode.lon = lon; | 
					
						
							|  |  |  |         const properties = {id: id}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const geojson = { | 
					
						
							|  |  |  |             "type": "Feature", | 
					
						
							|  |  |  |             "properties": properties, | 
					
						
							|  |  |  |             "id": id, | 
					
						
							|  |  |  |             "geometry": { | 
					
						
							|  |  |  |                 "type": "Point", | 
					
						
							|  |  |  |                 "coordinates": [ | 
					
						
							|  |  |  |                     lon, | 
					
						
							|  |  |  |                     lat | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // The basictags are COPIED, the id is included in the properties
 | 
					
						
							|  |  |  |         // The tags are not yet written into the OsmObject, but this is applied onto a 
 | 
					
						
							|  |  |  |         for (const kv of basicTags) { | 
					
						
							|  |  |  |             properties[kv.key] = kv.value; | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |             this._pendingChanges.push({elementId: id, key: kv.key, value: kv.value}); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |         this.pendingChangesES.setData(this._pendingChanges.length); | 
					
						
							|  |  |  |         State.state.allElements.addOrGetElement(geojson).ping(); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return geojson; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-19 00:13:45 +02:00
										 |  |  |     public uploadAll(optionalContinuation: (() => void) = undefined) { | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         const self = this; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         this.isSaving.setData(true); | 
					
						
							|  |  |  |         const optionalContinuationWrapped = function () { | 
					
						
							|  |  |  |             self.isSaving.setData(false); | 
					
						
							|  |  |  |             if (optionalContinuation) { | 
					
						
							|  |  |  |                 optionalContinuation(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         const pending: { elementId: string; key: string; value: string }[] = this._pendingChanges; | 
					
						
							|  |  |  |         this._pendingChanges = []; | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |         this.pendingChangesES.setData(this._pendingChanges.length); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const newElements = this.newElements; | 
					
						
							|  |  |  |         this.newElements = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const knownElements = {}; // maps string --> OsmObject
 | 
					
						
							|  |  |  |         function DownloadAndContinue(neededIds, continuation: (() => void)) { | 
					
						
							|  |  |  |             // local function which downloads all the objects one by one
 | 
					
						
							|  |  |  |             // this is one big loop, running one download, then rerunning the entire function
 | 
					
						
							|  |  |  |             if (neededIds.length == 0) { | 
					
						
							|  |  |  |                 continuation(); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const neededId = neededIds.pop(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (neededId in knownElements) { | 
					
						
							|  |  |  |                 DownloadAndContinue(neededIds, continuation); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             console.log("Downloading ", neededId); | 
					
						
							|  |  |  |             OsmObject.DownloadObject(neededId, | 
					
						
							|  |  |  |                 function (element) { | 
					
						
							|  |  |  |                     knownElements[neededId] = element; // assign the element for later, continue downloading the next element
 | 
					
						
							|  |  |  |                     DownloadAndContinue(neededIds, continuation); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const neededIds = []; | 
					
						
							|  |  |  |         for (const change of pending) { | 
					
						
							|  |  |  |             const id = change.elementId; | 
					
						
							|  |  |  |             if (parseFloat(id.split("/")[1]) < 0) { | 
					
						
							|  |  |  |                 console.log("Detected a new element! Exciting!") | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 neededIds.push(id); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         DownloadAndContinue(neededIds, function () { | 
					
						
							|  |  |  |             // Here, inside the continuation, we know that all 'neededIds' are loaded in 'knownElements'
 | 
					
						
							|  |  |  |             // We apply the changes on them
 | 
					
						
							|  |  |  |             for (const change of pending) { | 
					
						
							|  |  |  |                 if (parseInt(change.elementId.split("/")[1]) < 0) { | 
					
						
							|  |  |  |                     // This is a new element - we should apply this on one of the new elements
 | 
					
						
							|  |  |  |                     for (const newElement of newElements) { | 
					
						
							|  |  |  |                         if (newElement.type + "/" + newElement.id === change.elementId) { | 
					
						
							|  |  |  |                             newElement.addTag(change.key, change.value); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     console.log(knownElements, change.elementId); | 
					
						
							|  |  |  |                     knownElements[change.elementId].addTag(change.key, change.value); | 
					
						
							|  |  |  |                     // note: addTag will flag changes with 'element.changed' internally
 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Small sanity check for duplicate information
 | 
					
						
							|  |  |  |             let changedElements = []; | 
					
						
							|  |  |  |             for (const elementId in knownElements) { | 
					
						
							|  |  |  |                 const element = knownElements[elementId]; | 
					
						
							|  |  |  |                 if (element.changed) { | 
					
						
							|  |  |  |                     changedElements.push(element); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (changedElements.length == 0 && newElements.length == 0) { | 
					
						
							|  |  |  |                 console.log("No changes in any object"); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const handleMapping = function (idMapping) { | 
					
						
							|  |  |  |                 for (const oldId in idMapping) { | 
					
						
							|  |  |  |                     const newId = idMapping[oldId]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |                     const element = State.state.allElements.getElement(oldId); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |                     element.data.id = newId; | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |                     State.state.allElements.addElementById(newId, element); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |                     element.ping(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             console.log("Beginning upload..."); | 
					
						
							|  |  |  |             // At last, we build the changeset and upload
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |             State.state.osmConnection.UploadChangeset(self._changesetComment, | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |                 function (csId) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let modifications = ""; | 
					
						
							|  |  |  |                     for (const element of changedElements) { | 
					
						
							|  |  |  |                         if (!element.changed) { | 
					
						
							|  |  |  |                             continue; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         modifications += element.ChangesetXML(csId) + "\n"; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let creations = ""; | 
					
						
							|  |  |  |                     for (const newElement of newElements) { | 
					
						
							|  |  |  |                         creations += newElement.ChangesetXML(csId); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 00:45:33 +02:00
										 |  |  |                     let changes = `<osmChange version='0.6' generator='Mapcomplete ${State.vNumber}'>`; | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (creations.length > 0) { | 
					
						
							|  |  |  |                         changes += | 
					
						
							|  |  |  |                             "<create>" + | 
					
						
							|  |  |  |                             creations + | 
					
						
							|  |  |  |                             "</create>"; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (modifications.length > 0) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         changes += | 
					
						
							|  |  |  |                             "<modify>" + | 
					
						
							|  |  |  |                             modifications + | 
					
						
							|  |  |  |                             "</modify>"; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     changes += "</osmChange>"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     return changes; | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 handleMapping, | 
					
						
							| 
									
										
										
										
											2020-06-27 03:06:51 +02:00
										 |  |  |                 optionalContinuationWrapped); | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |         * Registers an action that: | 
					
						
							|  |  |  |         * -> Upload everything to OSM | 
					
						
							|  |  |  |         * -> Asks the user not to close. The 'not to close' dialog should profide enough time to upload | 
					
						
							|  |  |  |         * -> WHen uploading is done, the window is closed anyway | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |     private LastEffortSave() { | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         window.addEventListener("beforeunload", function (e) { | 
					
						
							|  |  |  |             // Quickly save everyting!
 | 
					
						
							|  |  |  |             if (self.pendingChangesES.data == 0) { | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.uploadAll(function () { | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |                 console.log("Uploaded changes during a last-effort save") | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |                 window.close() | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |             var confirmationMessage = "Nog even geduld - je laatset wijzigingen worden opgeslaan!"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             (e || window.event).returnValue = confirmationMessage; //Gecko + IE
 | 
					
						
							|  |  |  |             return confirmationMessage;                            //Webkit, Safari, Chrome
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         document.addEventListener('visibilitychange', () => { | 
					
						
							|  |  |  |             if (document.visibilityState === "visible") { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (this.pendingChangesES.data == 0) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |             console.log("Uploading: loss of focus") | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |             this.uploadAll(function () { | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |                 console.log("Uploaded changes during a last-effort save (loss of focus)") | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |                 window.close() | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private SetupAutoSave(state: State) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const millisTillChangesAreSaved = state.secondsTillChangesAreSaved; | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |         const saveAfterXMillis = state.saveTimeout.data; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |         this.pendingChangesES.addCallback(function () { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |             var c = self.pendingChangesES.data; | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |             if (c > 10) { | 
					
						
							|  |  |  |                 millisTillChangesAreSaved.setData(0); | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |                 self.uploadAll(() => { | 
					
						
							| 
									
										
										
										
											2020-08-06 23:49:35 +02:00
										 |  |  |                     console.log("Uploaded changes: more then 10 pending changes") | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |                 }); | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (c > 0) { | 
					
						
							|  |  |  |                 millisTillChangesAreSaved.setData(saveAfterXMillis); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         millisTillChangesAreSaved.addCallback((time) => { | 
					
						
							| 
									
										
										
										
											2020-07-31 16:17:16 +02:00
										 |  |  |                 if (time <= 0 && self.pendingChangesES.data > 0) { | 
					
						
							| 
									
										
										
										
											2020-08-06 21:06:50 +02:00
										 |  |  |                     self.uploadAll(() => { | 
					
						
							|  |  |  |                         console.log("Saving changes: timer elapsed") | 
					
						
							|  |  |  |                     }); | 
					
						
							| 
									
										
										
										
											2020-07-31 04:58:58 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Utils.DoEvery( | 
					
						
							|  |  |  |             1000, | 
					
						
							|  |  |  |             () => { | 
					
						
							|  |  |  |                 millisTillChangesAreSaved | 
					
						
							|  |  |  |                     .setData(millisTillChangesAreSaved.data - 1000) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-24 00:35:19 +02:00
										 |  |  | } |