fix(desktop): deleting the active profile reliably falls back to default

Centralize the fallback in DeleteProfileDialog (the single delete choke
point) so both the rail and the Profiles view inherit it. Reset *after*
the host's onDeleted refresh so a refreshActiveProfile racing the dying
backend can't clobber the pill back to the deleted profile, and set
$activeProfile too (selectProfile only moved the gateway, leaving the
statusbar pill stranded on the dead profile).
This commit is contained in:
Brooklyn Nicholson
2026-06-04 19:49:11 -05:00
parent 9dbd3c57d7
commit f764b0400a
2 changed files with 16 additions and 11 deletions

View File

@ -264,16 +264,7 @@ export function ProfileRail() {
<DeleteProfileDialog
onClose={() => setPendingDelete(null)}
onDeleted={async () => {
// Deleting the profile you're currently in would strand the gateway on
// a dead profile — fall back to default.
const wasActive = pendingDelete != null && normalizeProfileKey(pendingDelete.name) === activeKey
await refreshActiveProfile()
if (wasActive) {
selectProfile('default')
}
}}
onDeleted={refreshActiveProfile}
open={pendingDelete !== null}
profile={pendingDelete}
/>

View File

@ -1,8 +1,10 @@
import { ConfirmDialog } from '@/components/ui/confirm-dialog'
import { deleteProfile } from '@/hermes'
import { $activeGatewayProfile, normalizeProfileKey, selectProfile, setActiveProfile } from '@/store/profile'
// Thin wrapper over ConfirmDialog: owns the deleteProfile call, inherits
// Enter-to-confirm + busy/done/error from the shared dialog.
// Enter-to-confirm + busy/done/error from the shared dialog. The single choke
// point for every delete entry point (rail + Profiles view).
export function DeleteProfileDialog({
profile,
onClose,
@ -34,8 +36,20 @@ export function DeleteProfileDialog({
return
}
// Deleting the profile the live gateway is on strands it on a dead
// backend. Capture that before the delete; reset *after* the host's
// onDeleted refresh so our reset is the last write — a refreshActiveProfile
// racing the (still-dying) backend can't clobber the pill back to it.
const wasActive = normalizeProfileKey(profile.name) === normalizeProfileKey($activeGatewayProfile.get())
await deleteProfile(profile.name)
await onDeleted?.()
if (wasActive) {
// Swap gateway/sidebar to default and set the pill now — the primary
// backend is always default, so this is correct, not just optimistic.
selectProfile('default')
setActiveProfile('default')
}
}}
open={open}
title="Delete profile?"