Fix settings host sections showing "host not found" when the local daemon is stopped (#1749)

The local daemon's serverId persists while the daemon is stopped, so it isn't
among the connected hosts. The settings host-section resolver fell back to it
without checking it was connected, resolving the section to an unknown id and
rendering "host not found".

Extract the fallback into resolveActiveHostServerId, which only uses a serverId
when it names a currently connected host (covering both the picker selection and
the local daemon), and add regression tests.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
维她命@
2026-07-21 04:48:34 +08:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 345d8e5240
commit 8c92c7d423
3 changed files with 109 additions and 13 deletions
+13 -13
View File
@@ -56,7 +56,11 @@ import {
} from "@/hooks/use-settings";
import { useHostRuntimeIsConnected, useHosts } from "@/runtime/host-runtime";
import { useSessionStore } from "@/stores/session-store";
import { orderHostsLocalFirst, type HostProfile } from "@/types/host-connection";
import {
orderHostsLocalFirst,
resolveActiveHostServerId,
type HostProfile,
} from "@/types/host-connection";
import { TitlebarDragRegion } from "@/components/desktop/titlebar-drag-region";
import { WindowChromeRegion, WindowChromeSafeArea } from "@/utils/desktop-window";
import { confirmDialog } from "@/utils/confirm-dialog";
@@ -1144,15 +1148,6 @@ export default function SettingsScreen({ view, openAddHostIntent = null }: Setti
const [selectedSettingsHostServerId, setSelectedSettingsHostServerId] = useState<string | null>(
view.kind === "host" ? view.serverId : null,
);
const knownSelectedSettingsHostServerId = useMemo(() => {
if (!selectedSettingsHostServerId) {
return null;
}
return hosts.some((host) => host.serverId === selectedSettingsHostServerId)
? selectedSettingsHostServerId
: null;
}, [hosts, selectedSettingsHostServerId]);
useEffect(() => {
if (view.kind === "host") {
setSelectedSettingsHostServerId(view.serverId);
@@ -1160,11 +1155,16 @@ export default function SettingsScreen({ view, openAddHostIntent = null }: Setti
}, [view]);
// The host the four sections scope to: the host on the active view, otherwise
// the picker choice, otherwise the local daemon, otherwise the first host.
// the picker choice, otherwise the connected local daemon, otherwise the first host.
const activeHostServerId = useMemo(() => {
if (view.kind === "host") return view.serverId;
return knownSelectedSettingsHostServerId ?? localServerId ?? sortedHosts[0]?.serverId ?? null;
}, [view, knownSelectedSettingsHostServerId, localServerId, sortedHosts]);
return resolveActiveHostServerId({
selectedServerId: selectedSettingsHostServerId,
localServerId,
hosts,
orderedHosts: sortedHosts,
});
}, [view, selectedSettingsHostServerId, localServerId, hosts, sortedHosts]);
const handleSendBehaviorChange = useCallback(
(behavior: SendBehavior) => {