mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-15 08:02:53 +00:00
* fix(frontend): keep session-exit URL clean by syncing new_draft strip with the router Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(frontend): correct replaceState comment and test-mock wording per review Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(frontend): correct replaceState comment and drop drafting-history phrasing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
78 lines
3.4 KiB
TypeScript
78 lines
3.4 KiB
TypeScript
import { page } from '$app/state'
|
|
import { replaceState } from '$app/navigation'
|
|
import { rememberNavRoute } from '$lib/components/sessions/sessionSwitch.svelte'
|
|
import { UserDraftDbSyncer, type UserDraftLastSyncQuery } from '$lib/userDraftDbSyncer.svelte'
|
|
import { getLocalDraftHint } from '$lib/localDraftHints.svelte'
|
|
import type { UserDraftItemKind } from '$lib/gen'
|
|
|
|
/** Drop `?new_draft=true` from the current URL (preserving every other param),
|
|
* mutating the address bar without a navigation. No-op when the flag is absent
|
|
* or `window` is unavailable (SSR).
|
|
*
|
|
* Uses SvelteKit's `replaceState` (not raw `history.replaceState`, which the
|
|
* router warns conflicts with it) so the history entry keeps the router's
|
|
* bookkeeping and `page.state`. Also refreshes the remembered nav route:
|
|
* `afterNavigate` never observes this in-place rewrite, so without it
|
|
* `exitSessionMode` would restore the pre-strip URL — still carrying
|
|
* `?new_draft=true` — and re-enter the seed-empty branch. */
|
|
export function stripNewDraftFlag(): void {
|
|
if (typeof window === 'undefined') return
|
|
const url = new URL(window.location.href)
|
|
if (url.searchParams.get('new_draft') !== 'true') return
|
|
url.searchParams.delete('new_draft')
|
|
replaceState(url, page.state)
|
|
rememberNavRoute(url.pathname + url.search)
|
|
}
|
|
|
|
/**
|
|
* Whether an editor load should take the `?new_draft` seed-empty branch.
|
|
*
|
|
* The `/{scripts,flows,apps,apps_raw}/add` redirect lands the editor on
|
|
* `u/<user>/draft_<uuid>?new_draft=true`; the seed branch bootstraps an empty
|
|
* (or template/hub/fork-seeded) editor instead of fetching a row that doesn't
|
|
* exist yet. But the flag can outlive the seed: exiting an AI session restores
|
|
* the remembered nav route (still `?new_draft=true`) even though the draft was
|
|
* already materialized — by the first autosave, or by "Open in AI session"'s
|
|
* `forcePersist`. Re-running the seed branch then blanks the saved draft.
|
|
*
|
|
* So gate the seed branch on `new_draft=true` AND no persisted draft this
|
|
* session (`getLocalDraftHint`): a never-saved draft still seeds empty (and a
|
|
* pre-edit refresh re-seeds instead of 404-ing), while a re-entry after the
|
|
* draft exists falls through to the normal load that reflects it.
|
|
*/
|
|
export function shouldSeedNewDraft(
|
|
searchParams: URLSearchParams,
|
|
workspace: string | undefined,
|
|
itemKind: UserDraftItemKind,
|
|
path: string
|
|
): boolean {
|
|
if (searchParams.get('new_draft') !== 'true') return false
|
|
return getLocalDraftHint(workspace, itemKind, path) !== true
|
|
}
|
|
|
|
/**
|
|
* Defer stripping `?new_draft=true` from the URL until the draft's first save
|
|
* is CONFIRMED by the backend. The `/{scripts,flows,apps,apps_raw}/add`
|
|
* redirect lands the editor on an unsaved `u/<user>/draft_<uuid>` path;
|
|
* stripping the flag on load (the old behavior) meant a refresh before any
|
|
* edit fell through to the `getByPath` fetch for a row that doesn't exist yet
|
|
* → 404 "not found". Keeping the flag until `onSaved` fires lets a pre-edit
|
|
* refresh re-enter the new-draft seeding branch, while a post-save refresh
|
|
* loads the now-persisted draft.
|
|
*
|
|
* Returns a cleanup to drop the listener on navigation / unmount; the listener
|
|
* also self-unsubscribes after the first save.
|
|
*/
|
|
export function stripNewDraftFlagOnSave(query: UserDraftLastSyncQuery): () => void {
|
|
let unsub: (() => void) | undefined
|
|
unsub = UserDraftDbSyncer.onSaved(query, () => {
|
|
unsub?.()
|
|
unsub = undefined
|
|
stripNewDraftFlag()
|
|
})
|
|
return () => {
|
|
unsub?.()
|
|
unsub = undefined
|
|
}
|
|
}
|