fix(sessions): keep the tab put when a resource save fails

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
This commit is contained in:
Diego Imbert
2026-09-05 19:49:33 +02:00
co-authored by Claude Opus 5
parent f79160e598
commit f154863061
2 changed files with 10 additions and 10 deletions
@@ -57,7 +57,8 @@
let resourceEditor:
| {
save: () => void
/** False when the write failed; it toasts its own error. */
save: () => Promise<boolean>
localDraftDeployed: () => unknown
localDraftCurrent: () => unknown
discardLocalDraft: () => void
@@ -205,9 +206,12 @@
// Closed before the write is awaited, the way it always was: `save()` toasts its
// own failures and never rejects, so waiting would only add visible lag to every
// caller of this drawer. `onSaved` still fires after the write lands.
const saved = resourceEditor?.save()
const saving = resourceEditor?.save()
drawer?.closeDrawer()
await saved
// Everything below moves this host onto the path that was written, so it
// must not run for a write that failed — a rejected rename (a name
// collision, say) would point the tab at a path this save never created.
if (!(await saving)) return
// Rendered inline there is no drawer to close, so the mounted editor would
// otherwise keep the pre-save baseline. Follow a rename before remounting,
// or it comes back up on a path the save just moved the item off.
@@ -86,13 +86,9 @@
let frame: HTMLIFrameElement | undefined = $state()
// Bumped to remount a hosted entity editor, which is how it re-reads the item
// from the server: its own state is built at mount from the draft cell, so
// there is nothing to refresh in place once that cell has been dropped. The
// acting workspace joins it in the key for the same reason — these editors
// load and save against the workspace they were mounted with, so a session
// that rescopes (a staged fork materialising on first send) must not leave
// them bound to the previous one.
// A hosted entity editor builds its state at mount, from the draft cell and the
// workspace it was given, and can refresh neither in place — so both the bump
// below and a change of `workspaceId` key it, and remounting is how it re-reads.
let entityNonce = $state(0)
// Pages whose theme we mirror on live toggles. Regular apps are the only item