Fix removed host routes getting stuck connecting

This commit is contained in:
Mohamed Boudra
2026-06-09 18:06:48 +07:00
parent c5bcec5c71
commit e53d26699f
6 changed files with 115 additions and 12 deletions
-12
View File
@@ -84,7 +84,6 @@ import { resolveActiveHost } from "@/utils/active-host";
import { toggleDesktopSidebarsWithCheckoutIntent } from "@/utils/desktop-sidebar-toggle";
import {
buildHostRootRoute,
mapPathnameToServer,
parseHostAgentRouteFromPathname,
parseServerIdFromPathname,
parseWorkspaceOpenIntent,
@@ -811,7 +810,6 @@ function OpenProjectListener() {
}
function AppWithSidebar({ children }: { children: ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const params = useGlobalSearchParams<{ open?: string | string[] }>();
const hosts = useHosts();
@@ -820,16 +818,6 @@ function AppWithSidebar({ children }: { children: ReactNode }) {
const shouldShowAppChrome =
storeReady && activeServerId !== null && hosts.some((host) => host.serverId === activeServerId);
useEffect(() => {
if (!activeServerId || hosts.length === 0) {
return;
}
if (hosts.some((host) => host.serverId === activeServerId)) {
return;
}
router.replace(mapPathnameToServer(pathname, hosts[0].serverId));
}, [activeServerId, hosts, pathname, router]);
// Parse selectedAgentKey directly from pathname
// useLocalSearchParams doesn't update when navigating between same-pattern routes
const selectedAgentKey = useMemo(() => {
@@ -0,0 +1,25 @@
import { Redirect, Slot, useLocalSearchParams } from "expo-router";
import { HostRouteBootstrapBoundary } from "@/components/host-route-bootstrap-boundary";
import { useHosts } from "@/runtime/host-runtime";
import { resolveKnownHostRoute } from "@/utils/host-routes";
export default function HostRouteLayout() {
return (
<HostRouteBootstrapBoundary>
<KnownHostRoute />
</HostRouteBootstrapBoundary>
);
}
function KnownHostRoute() {
const params = useLocalSearchParams<{ serverId?: string | string[] }>();
const hosts = useHosts();
const routeServerId = typeof params.serverId === "string" ? params.serverId : null;
const resolution = resolveKnownHostRoute({ routeServerId, hosts });
if (resolution.kind === "redirect") {
return <Redirect href={resolution.href} />;
}
return <Slot />;
}
@@ -16,6 +16,7 @@ import {
parseHostWorkspaceOpenIntentFromPathname,
parseHostWorkspaceRouteFromPathname,
parseWorkspaceOpenIntent,
resolveKnownHostRoute,
} from "./host-routes";
describe("parseHostAgentRouteFromPathname", () => {
@@ -190,3 +191,32 @@ describe("host settings section slugs", () => {
expect(normalizeHostSectionSlug("daemon")).toBe("host");
});
});
describe("resolveKnownHostRoute", () => {
it("renders when the route host is still saved", () => {
expect(
resolveKnownHostRoute({
routeServerId: "srv-current",
hosts: [{ serverId: "srv-current" }, { serverId: "srv-next" }],
}),
).toEqual({ kind: "render" });
});
it("sends removed host routes to the next saved host home", () => {
expect(
resolveKnownHostRoute({
routeServerId: "srv-removed",
hosts: [{ serverId: "srv-next" }],
}),
).toEqual({ kind: "redirect", href: "/h/srv-next/open-project" });
});
it("sends host routes to welcome when no hosts are saved", () => {
expect(
resolveKnownHostRoute({
routeServerId: "srv-removed",
hosts: [],
}),
).toEqual({ kind: "redirect", href: "/welcome" });
});
});
+21
View File
@@ -355,6 +355,27 @@ export function buildHostOpenProjectRoute(serverId: string) {
return `${base}/open-project` as const;
}
export type KnownHostRouteResolution =
| { kind: "render" }
| { kind: "redirect"; href: ReturnType<typeof buildHostOpenProjectRoute> | "/welcome" };
export function resolveKnownHostRoute(input: {
routeServerId: string | null | undefined;
hosts: readonly { serverId: string }[];
}): KnownHostRouteResolution {
const routeServerId = trimNonEmpty(input.routeServerId);
if (routeServerId && input.hosts.some((host) => host.serverId === routeServerId)) {
return { kind: "render" };
}
const fallbackServerId = input.hosts[0]?.serverId;
if (fallbackServerId) {
return { kind: "redirect", href: buildHostOpenProjectRoute(fallbackServerId) };
}
return { kind: "redirect", href: "/welcome" };
}
export function buildHostNewWorkspaceRoute(
serverId: string,
sourceDirectory?: string,