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