diff --git a/frontend/src/lib/components/DiffDrawer.svelte b/frontend/src/lib/components/DiffDrawer.svelte index 40df701b4d..edb8b1e9dd 100644 --- a/frontend/src/lib/components/DiffDrawer.svelte +++ b/frontend/src/lib/components/DiffDrawer.svelte @@ -94,10 +94,11 @@ let selectedVersion: string | undefined = $state(undefined) let versionLoader: ((id: string) => Promise) | undefined = $state(undefined) let headLabel: string | undefined = $state(undefined) - /** The deployed head as it was handed to `setDiff`. `data.deployed` follows the - * picker, and Restore always restores the head, so its enabled state compares - * against this rather than whichever version is on display. */ - let headDeployed: Value | undefined = $state(undefined) + /** The deployed head, prepared for diffing as `data.deployed` is: `data.deployed` + * follows the picker while Restore always restores the head, so its enabled state + * compares against this. Must hold `prepareDiff`'s output, not the raw value, or the + * comparison never matches and Restore is always enabled. */ + let headDeployed: ReturnType | undefined = $state(undefined) let loadingVersion = $state(false) /** Which version load the spinner belongs to, counted rather than keyed on the id so * re-picking the same version is still generation-safe. A response from any other 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 a60fbf9d69..203773d30b 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 @@ -629,7 +629,15 @@ deployedHeadVersion && draftBaseVersion !== deployedHeadVersion ? async () => { - const head = Number(deployedHeadVersion) + // Re-read rather than trusting the head this page loaded with; see + // /scripts/edit. + const head = + ( + await AppService.getAppLatestVersion({ + workspace: $workspaceStore!, + path: page.params.path ?? '' + }).catch(() => undefined) + )?.version ?? Number(deployedHeadVersion) parentVersion = head if (deployedBaseline) deployedBaseline = { ...deployedBaseline, parent_version: head } draftBaseVersion = String(head) 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 97b636e4b0..a97113fd12 100644 --- a/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte @@ -546,7 +546,15 @@ { - const head = version + // Re-read rather than trusting the head this page loaded with; see + // /scripts/edit. + const head = + ( + await FlowService.getFlowLatestVersion({ + workspace: $workspaceStore!, + path: flowDraftPath + }).catch(() => undefined) + )?.id ?? version if (!draftSync.draft || head == null || !$workspaceStore) return draftSync.draft = { ...draftSync.draft, version_id: head } draftBaseVersion = String(head) diff --git a/frontend/src/routes/(root)/(logged)/scripts/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/scripts/edit/[...path]/+page.svelte index f0f9546160..4757c11a21 100644 --- a/frontend/src/routes/(root)/(logged)/scripts/edit/[...path]/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/scripts/edit/[...path]/+page.svelte @@ -527,7 +527,16 @@ userDraftPath={draftPath} onTakeLatest={draftBaseHash && deployedHeadHash && draftBaseHash !== deployedHeadHash ? async () => { - const head = deployedHeadHash + // Re-read rather than trusting the head this page loaded with: taking a + // stale one would say the draft is up to date with a version that is not + // the latest any more. + const head = + ( + await ScriptService.getScriptLatestVersion({ + workspace: $workspaceStore!, + path: draftPath + }).catch(() => undefined) + )?.script_hash ?? deployedHeadHash if (!draftSync.draft || !head || !$workspaceStore) return draftSync.draft = { ...draftSync.draft, parent_hash: head } // The baseline mirrors the draft's base so an unedited draft still