From d7d6c3142c4830a50c982dcad48cbfcad78b0421 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Mon, 16 Oct 2023 13:38:11 +0200 Subject: [PATCH] UX: add pending changes indicator --- langs/en.json | 4 +++ src/Logic/Actors/PendingChangesUploader.ts | 16 ++-------- src/Logic/Osm/Changes.ts | 16 +++++++++- src/Models/Constants.ts | 2 +- .../PendingChangesIndicator.svelte | 32 +++++++++++++++++++ src/UI/ThemeViewGUI.svelte | 2 ++ 6 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 src/UI/BigComponents/PendingChangesIndicator.svelte diff --git a/langs/en.json b/langs/en.json index 7bd2338e5..4116b2af0 100644 --- a/langs/en.json +++ b/langs/en.json @@ -316,6 +316,7 @@ }, "skip": "Skip this question", "testing": "Testing - changes won't be saved", + "uploadError": "Error while uploading changes: {error}", "uploadGpx": { "choosePermission": "Choose below if your track should be shared:", "confirm": "Confirm upload", @@ -343,6 +344,9 @@ "uploadFinished": "Your track has been uploaded!", "uploading": "Uploading your trace…" }, + "uploadPending": "{count} changes pending", + "uploadPendingSingle": "One change pending", + "uploadingChanges": "Uploading changes…", "useSearch": "Use the search above to see presets", "useSearchForMore": "Use the search function to search within {total} more values…", "waitingForGeopermission": "Waiting for your permission to use the geolocation…", diff --git a/src/Logic/Actors/PendingChangesUploader.ts b/src/Logic/Actors/PendingChangesUploader.ts index e71d0bf82..a6035c8f9 100644 --- a/src/Logic/Actors/PendingChangesUploader.ts +++ b/src/Logic/Actors/PendingChangesUploader.ts @@ -5,23 +5,11 @@ import { Utils } from "../../Utils" import { Feature } from "geojson" export default class PendingChangesUploader { - private lastChange: Date constructor(changes: Changes, selectedFeature: UIEventSource) { - const self = this - this.lastChange = new Date() - changes.pendingChanges.addCallback(() => { - self.lastChange = new Date() + changes.pendingChanges.stabilized(Constants.updateTimeoutSec * 1000).addCallback(() => changes.flushChanges("Flushing changes due to timeout")) - window.setTimeout(() => { - const diff = (new Date().getTime() - self.lastChange.getTime()) / 1000 - if (Constants.updateTimeoutSec >= diff - 1) { - changes.flushChanges("Flushing changes due to timeout") - } - }, Constants.updateTimeoutSec * 1000) - }) - - selectedFeature.stabilized(10000).addCallback((feature) => { + selectedFeature.stabilized(1000).addCallback((feature) => { if (feature === undefined) { // The popup got closed - we flush changes.flushChanges("Flushing changes due to popup closed") diff --git a/src/Logic/Osm/Changes.ts b/src/Logic/Osm/Changes.ts index 2c0f8df02..4c91c9e10 100644 --- a/src/Logic/Osm/Changes.ts +++ b/src/Logic/Osm/Changes.ts @@ -26,6 +26,7 @@ export class Changes { public readonly extraComment: UIEventSource = new UIEventSource(undefined) public readonly backend: string public readonly isUploading = new UIEventSource(false) + public readonly errors = new UIEventSource([], "upload-errors") private readonly historicalUserLocations?: FeatureSource private _nextId: number = -1 // Newly assigned ID's are negative private readonly previouslyCreated: OsmObject[] = [] @@ -128,8 +129,11 @@ export class Changes { const csNumber = await this.flushChangesAsync() this.isUploading.setData(false) console.log("Changes flushed. Your changeset is " + csNumber) + this.errors.setData([]) } catch (e) { this.isUploading.setData(false) + this.errors.data.push(e) + this.errors.ping() console.error("Flushing changes failed due to", e) } } @@ -415,6 +419,8 @@ export class Changes { id, " dropping it from the changes (" + e + ")" ) + this.errors.data.push(e) + this.errors.ping() return undefined } }) @@ -572,9 +578,15 @@ export class Changes { openChangeset.data ) - return await self.flushSelectChanges(pendingChanges, openChangeset) + const result = await self.flushSelectChanges(pendingChanges, openChangeset) + if(result){ + this.errors.setData([]) + } + return result } catch (e) { console.error("Could not upload some changes:", e) + this.errors.data.push(e) + this.errors.ping() return false } }) @@ -589,6 +601,8 @@ export class Changes { "Could not handle changes - probably an old, pending changeset in localstorage with an invalid format; erasing those", e ) + this.errors.data.push(e) + this.errors.ping() self.pendingChanges.setData([]) } finally { self.isUploading.setData(false) diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index 27c3a26fe..514053299 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -63,7 +63,7 @@ export default class Constants { * Used by 'PendingChangesUploader', which waits this amount of seconds to upload changes. * (Note that pendingChanges might upload sooner if the popup is closed or similar) */ - static updateTimeoutSec: number = 30 + static updateTimeoutSec: number = 15 /** * If the contributor has their GPS location enabled and makes a change, * the points visited less then `nearbyVisitTime`-seconds ago will be inspected. diff --git a/src/UI/BigComponents/PendingChangesIndicator.svelte b/src/UI/BigComponents/PendingChangesIndicator.svelte new file mode 100644 index 000000000..0392d3bf5 --- /dev/null +++ b/src/UI/BigComponents/PendingChangesIndicator.svelte @@ -0,0 +1,32 @@ + + + +
changes.flushChanges("Pending changes indicator clicked")}> + {#if $isUploading} + + + + {:else if $pendingChangesCount === 1} + + {:else if $pendingChangesCount > 1} + + {/if} + + {#each $errors as error} + + {/each} +
diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index 5d3ffb24d..3d4bd80f2 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -53,6 +53,7 @@ import Locale from "./i18n/Locale"; import ShareScreen from "./BigComponents/ShareScreen.svelte"; import UploadingImageCounter from "./Image/UploadingImageCounter.svelte" + import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte" export let state: ThemeViewState; let layout = state.layout; @@ -156,6 +157,7 @@ construct={() => new ExtraLinkButton(state, layout.extraLink).SetClass("pointer-events-auto")} /> +
Testmode