outdated state

This commit is contained in:
vcoppe committed 2026-10-11 10:48:43 +02:00
1 parent a2b4d89150
commit 9adb8e7221
14 files changed
+211 -118

No files matched your search

+11 -3
View File
@@ -19,7 +19,6 @@ import {
type Clipboard,
type ExportOptions,
type FileState,
type FilesUpdate,
type MergeType,
type MoveTarget,
type NewWaypoint,
@@ -34,6 +33,9 @@ import {
type WaypointDetails,
} from './types';
/** The error of the outcomes while the stored files come from a newer version of the app. */
const OUTDATED = 'saved by a newer version';
/**
* Thin wrapper around the WASM engine.
*
@@ -57,6 +59,7 @@ class Engine {
private _files = writable<Map<string, Writable<FileState>>>(new Map());
private _selection = writable<Selection>({ type: 'empty' });
private _lastError = writable<string | undefined>(undefined);
private _outdated = writable(false);
private _canUndo = writable(false);
private _canRedo = writable(false);
private _canPaste = writable(false);
@@ -67,6 +70,8 @@ class Engine {
readonly order: Readable<string[]> = { subscribe: this._order.subscribe };
/** Statistics of what is currently selected. */
readonly statistics: Readable<SelectionStatistics> = this._statistics.store;
/** Whether the stored files are from a newer version of the app: they cannot be changed. */
readonly outdated: Readable<boolean> = { subscribe: this._outdated.subscribe };
readonly canUndo: Readable<boolean> = { subscribe: this._canUndo.subscribe };
readonly canRedo: Readable<boolean> = { subscribe: this._canRedo.subscribe };
/** Why the last call to the engine did nothing, `undefined` if it did something. */
@@ -674,7 +679,7 @@ class Engine {
this._lastError.set(outcome.error);
if (outcome.error === 'nothing to do') {
console.debug('engine:', outcome.error);
} else if (outcome.error !== undefined) {
} else if (outcome.error !== undefined && outcome.error !== OUTDATED) {
console.warn('engine:', outcome.error);
}
}
@@ -691,7 +696,10 @@ class Engine {
}
/** Updates what is kept of the engine with what a call changed. */
private sync(wasm: Wasm, update: FilesUpdate) {
private sync(wasm: Wasm, update: Outcome) {
if (update.error === OUTDATED) {
this._outdated.set(true);
}
this._canUndo.set(wasm.can_undo());
this._canRedo.set(wasm.can_redo());
this._canPaste.set(wasm.can_paste());
+2 -10
View File
@@ -1,6 +1,6 @@
import { LEGACY_IMPORTED_KEY, readLegacyData } from '$lib/legacy-import';
import { parseVisibility, VISIBILITY_KEY, type Visibility } from '$lib/file-visibility';
import type { FilesUpdate, StorageOpened } from 'gpx-rs';
import type { Outcome, StorageOpened } from 'gpx-rs';
import type { Wasm } from './convert';
/** Name of the IndexedDB database that keeps the files and the settings. */
@@ -15,7 +15,7 @@ export type StorageHost = {
/** The explicit visibility per file, to fill with the one that was saved. */
visibility: Map<string, Visibility>;
/** Applies what a call changed to what the facade keeps of the files. */
sync(update: FilesUpdate): void;
sync(update: Outcome): void;
hasFiles(): boolean;
loadFiles(files: { data: Uint8Array; name: string }[]): Promise<boolean>;
deselect(): Promise<boolean>;
@@ -66,14 +66,6 @@ export async function openStoredFiles(host: StorageHost): Promise<Record<string,
console.error('The files cannot be kept in this browser', error);
return {};
}
if (opened.readOnly) {
console.warn(
'The files were saved by a newer version of the app: they are not saved again by this one'
);
}
if (opened.unreadable > 0) {
console.warn(`${opened.unreadable} stored file(s) could not be read`);
}
let settings = opened.settings;
// what was hidden, which the files that were restored need when they are read
parseVisibility(settings[VISIBILITY_KEY]).forEach((visibility, fileId) =>
+6 -1
View File
@@ -557,5 +557,10 @@
},
"webgl2_required": "WebGL 2 is required to display the map.",
"enable_webgl2": "Learn how to enable WebGL 2 in your browser",
"page_not_found": "page not found"
"page_not_found": "page not found",
"outdated": {
"title": "This page is out of date",
"description": "Your files were saved by a newer version of gpx.studio, which this page cannot read. Reload the page to get the latest version.",
"reload": "Reload"
}
}
@@ -11,6 +11,7 @@
import CoordinatesPopup from '$lib/components/map/CoordinatesPopup.svelte';
import Resizer from '$lib/components/Resizer.svelte';
import { Toaster } from '$lib/components/ui/sonner';
import * as AlertDialog from '$lib/components/ui/alert-dialog';
import { i18n } from '$lib/i18n.svelte';
import { settings } from '$lib/logic/settings';
import { loadFiles } from '$lib/logic/file-actions';
@@ -20,6 +21,8 @@
import { engine } from '$lib/engine';
import { getURLForGoogleDriveFile } from '$lib/components/embedding/embedding';
const outdated = engine.outdated;
const {
treeFileView,
elevationProfile,
@@ -153,6 +156,20 @@
{/if}
</div>
<AlertDialog.Root open={$outdated}>
<AlertDialog.Content escapeKeydownBehavior="ignore" interactOutsideBehavior="ignore">
<AlertDialog.Header>
<AlertDialog.Title>{i18n._('outdated.title')}</AlertDialog.Title>
<AlertDialog.Description>{i18n._('outdated.description')}</AlertDialog.Description>
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Action onclick={() => location.reload()}>
{i18n._('outdated.reload')}
</AlertDialog.Action>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog.Root>
<style lang="postcss">
@reference "tailwindcss";