Manage the built-in daemon from one place in settings (#1938)

* feat(settings): consolidate daemon management into the host page

The app-level Daemon section and the localhost host page rendered the
same daemon card in two places. The host page is now the single home:
the Host sidebar group leads with Overview, and a desktop-only "Enable
built-in daemon" option in the host switcher recovers a removed
localhost connection. Old settings/daemon deep links redirect
(COMPAT-tagged).

* fix(settings): hide daemon recovery option when the server id probe fails

Review feedback: !query.isLoading treated an errored IPC probe as
resolved, so the recovery affordance could show without knowing the
local server id. Replace the resolved-boolean hook with a single
discriminated state hook (loading | error | resolved) — errors hide the
affordance and fall back to the settings root in the redirect. Also
collapses the two query subscriptions per caller into one.

* fix(settings): keep daemon recovery reachable when no hosts remain

Review feedback: removing localhost as the only host takes the settings
sidebar down its no-host branch, which never mounts the host picker —
so the "Enable built-in daemon" option was unreachable in the most
common recovery case. The sidebar now owns the single hook call, passes
it to the picker, and renders the same action as a sidebar row next to
"Add host" when no hosts exist.

* test(e2e): update settings host header to Overview

Test drift: the host section's sidebar/header label was intentionally
renamed to "Overview"; the spec still asserted the old "Host" title.
Also assert the retired app-level Daemon row stays absent.
This commit is contained in:
Mohamed Boudra
2026-07-08 10:20:30 +02:00
committed by GitHub
parent 06c3161008
commit 4fb70668f2
19 changed files with 232 additions and 41 deletions
+28 -2
View File
@@ -15,10 +15,10 @@ async function loadDesktopDaemonServerId(): Promise<DesktopDaemonServerIdResult>
};
}
export function useLocalDaemonServerId(): string | null {
function useLocalDaemonServerIdQuery() {
const isDesktopApp = shouldUseDesktopDaemon();
const query = useQuery({
return useQuery({
queryKey: DESKTOP_DAEMON_SERVER_ID_QUERY_KEY,
queryFn: loadDesktopDaemonServerId,
enabled: isDesktopApp,
@@ -30,6 +30,11 @@ export function useLocalDaemonServerId(): string | null {
refetchOnWindowFocus: false,
retry: false,
});
}
export function useLocalDaemonServerId(): string | null {
const isDesktopApp = shouldUseDesktopDaemon();
const query = useLocalDaemonServerIdQuery();
if (!isDesktopApp) {
return null;
@@ -38,6 +43,27 @@ export function useLocalDaemonServerId(): string | null {
return query.data?.serverId ?? null;
}
export type LocalDaemonServerIdState =
| { status: "loading" }
| { status: "error" }
| { status: "resolved"; serverId: string | null };
export function useLocalDaemonServerIdState(): LocalDaemonServerIdState {
const isDesktopApp = shouldUseDesktopDaemon();
const query = useLocalDaemonServerIdQuery();
if (!isDesktopApp) {
return { status: "resolved", serverId: null };
}
if (query.isError) {
return { status: "error" };
}
if (query.isSuccess) {
return { status: "resolved", serverId: query.data.serverId };
}
return { status: "loading" };
}
export function useIsLocalDaemon(serverId: string): boolean {
const normalizedServerId = serverId.trim();
const localServerId = useLocalDaemonServerId();