From 65b5be8eff48205ee843703fc6eb98b292a1a47f Mon Sep 17 00:00:00 2001 From: Diego Imbert Date: Fri, 15 May 2026 14:45:30 +0200 Subject: [PATCH] fix(frontend): wire ?nodraft=true to actually skip the local autosave on /edit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flows/apps/apps_raw `/edit` routes had a `?nodraft=true` handler that just stripped the param from the URL via `afterNavigate` — nothing behind it. The original pre-PR semantics (and what every caller assumes) was "skip the localStorage autosave on this load." Mirror the synchronous wipe pattern already in /add: when nodraft is present, call `UserDraft.remove(kind, path)` and strip the flag from the URL via `window.history.replaceState`, before the UserDraft handle is created. The handle then reads an empty entry and the editor opens on the backend version. A plain reload (no nodraft) restores the autosave normally. Removed the redundant `afterNavigate` blocks. Dropped the now-unused `afterNavigate` import in all three; apps/edit still imports `replaceState` (used downstream), so only that name stayed. --- .../(logged)/apps/edit/[...path]/+page.svelte | 21 +++++++++--------- .../apps_raw/edit/[...path]/+page.svelte | 22 +++++++++---------- .../flows/edit/[...path]/+page.svelte | 21 ++++++++++-------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte index 83a387a05c..5f4813c75f 100644 --- a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte @@ -8,7 +8,7 @@ } from '$lib/gen' import { workspaceStore } from '$lib/stores' import { cleanValueProperties, orderedJsonStringify, type Value } from '$lib/utils' - import { afterNavigate, replaceState } from '$app/navigation' + import { replaceState } from '$app/navigation' import { goto } from '$lib/navigation' import { sendUserToast } from '$lib/toast' import DiffDrawer from '$lib/components/DiffDrawer.svelte' @@ -67,15 +67,16 @@ staleModalOpen = false } - let nodraft = page.url.searchParams.get('nodraft') - - afterNavigate(() => { - if (nodraft) { - let url = new URL(page.url.href) - url.search = '' - replaceState(url.toString(), page.state) - } - }) + // `?nodraft=true` is the callers' way of saying "skip the local autosave + // on this load." Wipe the UserDraft entry and strip the flag from the + // URL synchronously, before any descendant reads it. A plain reload + // (no nodraft) restores normally. + if (page.url.searchParams.get('nodraft') && typeof window !== 'undefined') { + UserDraft.remove('app', path) + const url = new URL(window.location.href) + url.searchParams.delete('nodraft') + window.history.replaceState(window.history.state, '', url.toString()) + } /** Increments per `loadApp` call. Stale loads (e.g. when picker * navigation races a draft-discard reload) bail at the next checkpoint diff --git a/frontend/src/routes/(root)/(logged)/apps_raw/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/apps_raw/edit/[...path]/+page.svelte index 725856dc41..d8444f0197 100644 --- a/frontend/src/routes/(root)/(logged)/apps_raw/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/apps_raw/edit/[...path]/+page.svelte @@ -9,7 +9,6 @@ readFieldsRecursively, type Value } from '$lib/utils' - import { afterNavigate, replaceState } from '$app/navigation' import { goto } from '$lib/navigation' import { sendUserToast } from '$lib/toast' import DiffDrawer from '$lib/components/DiffDrawer.svelte' @@ -55,6 +54,17 @@ let redraw = $state(0) let path = page.params.path ?? '' + // `?nodraft=true` is the callers' way of saying "skip the local autosave + // on this load." Wipe the UserDraft entry and strip the flag from the + // URL synchronously, before the handle is created. A plain reload (no + // nodraft) restores normally. + if (page.url.searchParams.get('nodraft') && typeof window !== 'undefined') { + UserDraft.remove('raw_app', path) + const url = new URL(window.location.href) + url.searchParams.delete('nodraft') + window.history.replaceState(window.history.state, '', url.toString()) + } + const draftHandle = UserDraft.use('raw_app', path) // Local-draft staleness modal: opened when the remote has moved on since @@ -97,16 +107,6 @@ draftHandle.draft = { files, runnables, data, summary } }) - let nodraft = page.url.searchParams.get('nodraft') - - afterNavigate(() => { - if (nodraft) { - let url = new URL(page.url.href) - url.search = '' - replaceState(url.toString(), page.state) - } - }) - function extractRawApp(app: any) { runnables = app.value.runnables // Support old formats and new format diff --git a/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte index e369fbb895..bc1419b66d 100644 --- a/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte @@ -13,7 +13,6 @@ } from '$lib/utils' import { initFlow } from '$lib/components/flows/flowStore.svelte' import { goto } from '$lib/navigation' - import { afterNavigate, replaceState } from '$app/navigation' import { sendUserToast } from '$lib/toast' import DiffDrawer from '$lib/components/DiffDrawer.svelte' @@ -49,15 +48,19 @@ }) | undefined = $state(undefined) - afterNavigate(() => { - if (page.url.searchParams.get('nodraft')) { - let url = new URL(page.url.href) - url.search = '' - replaceState(url.toString(), page.state) - } - }) - const flowDraftPath = page.params.path ?? '' + + // `?nodraft=true` is the callers' way of saying "skip the local autosave + // on this load." Wipe the UserDraft entry and strip the flag from the + // URL synchronously, before the handle is created — same pattern as + // /flows/add. A plain reload (no nodraft) restores normally. + if (page.url.searchParams.get('nodraft') && typeof window !== 'undefined') { + UserDraft.remove('flow', flowDraftPath) + const url = new URL(window.location.href) + url.searchParams.delete('nodraft') + window.history.replaceState(window.history.state, '', url.toString()) + } + const flowHandle = UserDraft.use('flow', flowDraftPath) function emptyFlow(): Flow {