From 5f94207c02cb7d375f600e525d3c4907208cd518 Mon Sep 17 00:00:00 2001 From: Diego Imbert Date: Sun, 7 Jun 2026 23:49:50 +0200 Subject: [PATCH] fix(drafts): skip public-secret-URL fetch in the Deploy drawer for draft-only apps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Opening the Deploy drawer on a `/edit/u/{user}/draft_{uuid}` app fired `AppService.getPublicSecretOfApp` immediately because the gating effect only checked `appPath != ''` + `savedApp`. The `/secret_of/{path}` route plain-SELECTs `app.id`, so a draft-only path 404'd with "App not found at name …" and the public-URL ClipboardPanel spun forever waiting on `secretUrl`. Thread the existing `newApp` signal (already on `AppEditorHeader` / `RawAppEditorHeader`) into `AppEditorHeaderDeploy`, gate the fetch behind `!newApp`, and render the existing "Deploy this app once to get the public secret URL" placeholder instead of the spinner for draft-only items. --- .../apps/editor/AppEditorHeader.svelte | 1 + .../apps/editor/AppEditorHeaderDeploy.svelte | 22 +++++++++++++++---- .../raw_apps/RawAppEditorHeader.svelte | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte index e24a280d87..765d1ceffe 100644 --- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -757,6 +757,7 @@ {/snippet} void @@ -57,6 +58,11 @@ // document and break no-CORP cross-origin subresources (external images, // {@html} embeds, CDN imports). rawApp?: boolean + /** True while the editor is on a draft-only URL (`/edit/u/{user}/draft_{uuid}` + * with no deployed row yet). Suppresses the public-secret-URL fetch + * (`/secret_of/...` 404s with no `app` row) and renders a placeholder + * instead of the eternally-spinning link. */ + newApp?: boolean } = $props() let isDeployer = $derived($userStore?.groups?.includes(WM_DEPLOYERS_GROUP) ?? false) @@ -139,7 +145,15 @@ }) $effect(() => { - appPath && appPath != '' && savedApp && secretUrl == undefined && untrack(() => getSecretUrl()) + // Skip the secret URL fetch on draft-only items — `/secret_of/...` + // has no `app` row to look up and would 404, leaving the UI + // component spinning indefinitely. + !newApp && + appPath && + appPath != '' && + savedApp && + secretUrl == undefined && + untrack(() => getSecretUrl()) }) @@ -267,8 +281,8 @@ disabled={!savedApp} /> - {#if !savedApp} - + {#if !savedApp || newApp} + {:else if secretUrlHref}