diff --git a/frontend/src/lib/components/apps/editor/AppEditor.svelte b/frontend/src/lib/components/apps/editor/AppEditor.svelte
index 0cffdc2400..f6e3245c2c 100644
--- a/frontend/src/lib/components/apps/editor/AppEditor.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditor.svelte
@@ -83,7 +83,8 @@
onResetToDeployed,
loadedFromDraft = false,
othersDraftsCount = 0,
- onOpenOthersDrafts
+ onOpenOthersDrafts,
+ onRestore
}: AppEditorProps = $props()
migrateApp(untrack(() => app))
@@ -890,7 +891,7 @@
{loadedFromDraft}
{othersDraftsCount}
{onOpenOthersDrafts}
- on:restore
+ {onRestore}
{policy}
{fromHub}
bind:this={appEditorHeader}
diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
index 1de186c301..0ed389f52c 100644
--- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
+++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte
@@ -112,6 +112,10 @@
loadedFromDraft?: boolean
othersDraftsCount?: number
onOpenOthersDrafts?: () => void
+ // Restoring an older deployment from the history drawer. A callback prop
+ // (not `on:restore` forwarding): forwarding a `createEventDispatcher`
+ // event up through these runes-mode components silently drops it.
+ onRestore?: (restoredApp: any) => void
}
let {
@@ -137,7 +141,8 @@
onResetToDeployed,
loadedFromDraft = false,
othersDraftsCount = 0,
- onOpenOthersDrafts
+ onOpenOthersDrafts,
+ onRestore
}: Props = $props()
/** Mirror of the path the user is editing in the pen popover. Initialized
@@ -862,7 +867,7 @@
(historyBrowserDrawerOpen = false)}>
-
+ onRestore?.(e.detail)} appPath={$appPath} />
diff --git a/frontend/src/lib/components/apps/types.ts b/frontend/src/lib/components/apps/types.ts
index de34f4676d..d8ac000ba5 100644
--- a/frontend/src/lib/components/apps/types.ts
+++ b/frontend/src/lib/components/apps/types.ts
@@ -176,6 +176,10 @@ export interface AppEditorProps {
loadedFromDraft?: boolean
othersDraftsCount?: number
onOpenOthersDrafts?: () => void
+ // Restoring an older deployment from the history drawer. Threaded through
+ // AppEditorHeader as a callback prop rather than `on:restore` forwarding,
+ // which does not propagate through these runes-mode components.
+ onRestore?: (restoredApp: any) => void
}
export type App = {
diff --git a/frontend/src/lib/components/raw_apps/RawAppEditor.svelte b/frontend/src/lib/components/raw_apps/RawAppEditor.svelte
index c8d15e6e7e..18f9c1af0c 100644
--- a/frontend/src/lib/components/raw_apps/RawAppEditor.svelte
+++ b/frontend/src/lib/components/raw_apps/RawAppEditor.svelte
@@ -121,6 +121,14 @@
onOpenOthersDrafts?: () => void
onRuntimeLogRequester?: (requester: RawAppRuntimeLogRequester | undefined) => void
onRunsProvider?: (provider: RawAppRunsProvider | undefined) => void
+ // Restoring an older deployment from the history drawer. A callback prop
+ // (not `on:restore` forwarding): forwarding a `createEventDispatcher`
+ // event up through these runes-mode components silently drops it.
+ onRestore?: (restoredApp: any) => void
+ // Deploy created the app at a new path; the page navigates to it. Callback
+ // prop for the same reason as `onRestore` — `on:savedNewAppPath` forwarding
+ // through these runes-mode components is dropped.
+ onSavedNewAppPath?: (path: string) => void
}
let {
@@ -148,7 +156,9 @@
othersDraftsCount = 0,
onOpenOthersDrafts,
onRuntimeLogRequester = undefined,
- onRunsProvider = undefined
+ onRunsProvider = undefined,
+ onRestore,
+ onSavedNewAppPath
}: Props = $props()
export const version: number | undefined = undefined
@@ -1596,8 +1606,8 @@
bind:savedApp
bind:summary
bind:pendingDraftPath
- on:restore
- on:savedNewAppPath
+ {onRestore}
+ {onSavedNewAppPath}
{policy}
{diffDrawer}
{newApp}
diff --git a/frontend/src/lib/components/raw_apps/RawAppEditorHeader.svelte b/frontend/src/lib/components/raw_apps/RawAppEditorHeader.svelte
index 3963e1b16d..9853fb69bd 100644
--- a/frontend/src/lib/components/raw_apps/RawAppEditorHeader.svelte
+++ b/frontend/src/lib/components/raw_apps/RawAppEditorHeader.svelte
@@ -26,7 +26,7 @@
Undo,
WandSparkles
} from 'lucide-svelte'
- import { createEventDispatcher, untrack } from 'svelte'
+ import { untrack } from 'svelte'
import { orderedJsonStringify, type Value, replaceFalseWithUndefined } from '../../utils'
import { random_adj } from '$lib/components/random_positive_adjetive'
@@ -151,6 +151,14 @@
loadedFromDraft?: boolean
othersDraftsCount?: number
onOpenOthersDrafts?: () => void
+ // Restoring an older deployment from the history drawer. A callback prop
+ // (not `on:restore` forwarding): forwarding a `createEventDispatcher`
+ // event up through these runes-mode components silently drops it.
+ onRestore?: (restoredApp: any) => void
+ // Deploy created the app at a new path; the page navigates to it. Callback
+ // prop for the same reason as `onRestore` — `on:savedNewAppPath` forwarding
+ // through these runes-mode components is dropped.
+ onSavedNewAppPath?: (path: string) => void
}
let {
@@ -184,7 +192,9 @@
onResetToDeployed,
loadedFromDraft = false,
othersDraftsCount = 0,
- onOpenOthersDrafts
+ onOpenOthersDrafts,
+ onRestore,
+ onSavedNewAppPath
}: Props = $props()
// Set by the on-behalf-of selector when the publisher picks a user other than
@@ -352,7 +362,7 @@
path: appPath
})
}
- dispatch('savedNewAppPath', path)
+ onSavedNewAppPath?.(path)
onDeploy?.({ path })
} catch (e) {
sendUserToast(`Error creating app: ${e.body ?? e.message}`, true)
@@ -475,7 +485,7 @@
})
}
if (appPath !== npath) {
- dispatch('savedNewAppPath', npath)
+ onSavedNewAppPath?.(npath)
}
onDeploy?.({ path: npath })
}
@@ -575,8 +585,6 @@
}
])
- const dispatch = createEventDispatcher()
-
let customPath = $state(savedApp?.custom_path)
let customPathError = $state('')
@@ -688,7 +696,7 @@
(historyBrowserDrawerOpen = false)}>
-
+ onRestore?.(e.detail)} {appPath} />
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 8c0efa0af4..ea87409171 100644
--- a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte
+++ b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte
@@ -388,9 +388,14 @@
let diffDrawer: DiffDrawer | undefined = $state()
- function onRestore(ev: any) {
+ function onRestore(restoredApp: any) {
sendUserToast('App restored from previous deployment')
- app = ev.detail
+ // Drop the stale pre-restore autosave. The remounted AppEditor seeds its
+ // state from `appDraftHandle.draft ?? app`, so without this it keeps showing
+ // the old draft instead of the restored version. Same reason `reloadDeployed`
+ // removes the draft before remounting.
+ UserDraft.remove('app', path)
+ app = restoredApp
// Re-pin the stale-draft fork base to the current head. A restored value
// carries the `parent_version` baked in when that older version was deployed,
// which would make the deploy guard (`compareVersions`) falsely report "not on
@@ -470,7 +475,7 @@
app.path = url
}
}}
- on:restore={onRestore}
+ {onRestore}
summary={app.summary}
app={app.value}
{deployedBaseline}
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 94c6d72e71..0cf374f0b1 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
@@ -449,9 +449,9 @@
let diffDrawer: DiffDrawer | undefined = $state(undefined)
- function onRestore(ev: any) {
+ function onRestore(restoredApp: any) {
sendUserToast('App restored from previous deployment')
- let prev = ev.detail
+ let prev = restoredApp
extractRawApp(prev)
savedApp = {
summary: prev.summary,
@@ -536,12 +536,12 @@
{#key redraw}
{
+ onSavedNewAppPath={(savedPath) => {
draftSync.remove()
- goto(`/apps_raw/edit/${event.detail}`)
- newPath = event.detail
+ goto(`/apps_raw/edit/${savedPath}`)
+ newPath = savedPath
}}
- on:restore={onRestore}
+ {onRestore}
bind:files
bind:runnables
bind:data