fix(projects): keep settings on routed host

This commit is contained in:
Mohamed Boudra
2026-07-29 01:06:29 +00:00
parent a924d51e4c
commit 29d3b2f76c
3 changed files with 35 additions and 22 deletions

View File

@@ -3,6 +3,7 @@ import {
findProjectSettingsRouteTarget,
findProjectSettingsTarget,
resolveHostProjectSettingsRouteKey,
resolveProjectSettingsServerId,
resolveProjectSettingsRouteKey,
} from "./project-settings-target";
@@ -54,4 +55,15 @@ describe("project settings target", () => {
serverId: "host-b",
});
});
it("does not retarget an unavailable routed host", () => {
expect(
resolveProjectSettingsServerId({
projectKey: "remote:github.com/acme/app",
editableServerIds: ["host-a"],
routedServerId: "host-b",
hostSelection: { routeKey: "", serverId: "" },
}),
).toBe("host-b");
});
});

View File

@@ -42,3 +42,20 @@ export function findProjectSettingsRouteTarget<T extends ProjectSettingsTarget>(
}
return undefined;
}
export function resolveProjectSettingsServerId(input: {
projectKey: string;
editableServerIds: readonly string[];
routedServerId: string | null;
hostSelection: { routeKey: string; serverId: string };
}): string {
const editableServerIds = new Set(input.editableServerIds);
if (
input.hostSelection.routeKey === input.projectKey &&
editableServerIds.has(input.hostSelection.serverId)
) {
return input.hostSelection.serverId;
}
if (input.routedServerId) return input.routedServerId;
return input.editableServerIds[0] ?? "";
}

View File

@@ -31,7 +31,10 @@ import { SettingsGroup } from "@/screens/settings/settings-group";
import { SettingsSection } from "@/screens/settings/settings-section";
import { settingsStyles } from "@/styles/settings";
import { useProjects } from "@/hooks/use-projects";
import { findProjectSettingsRouteTarget } from "@/projects/project-settings-target";
import {
findProjectSettingsRouteTarget,
resolveProjectSettingsServerId,
} from "@/projects/project-settings-target";
import { useProjectIconDataByProjectKey } from "@/projects/project-icons";
import { useHostRuntimeClient, useHostRuntimeSnapshot } from "@/runtime/host-runtime";
import { useToast } from "@/contexts/toast-context";
@@ -97,9 +100,9 @@ export default function ProjectSettingsScreen({ projectKey }: ProjectSettingsScr
const project = routeTarget?.project;
const editableHosts = useMemo(() => filterEditableHosts(project), [project]);
const [hostSelection, setHostSelection] = useState({ routeKey: "", serverId: "" });
const selectedServerId = resolveSelectedSettingsServerId({
const selectedServerId = resolveProjectSettingsServerId({
projectKey,
editableHosts,
editableServerIds: editableHosts.map((host) => host.serverId),
routedServerId: routeTarget?.serverId ?? null,
hostSelection,
});
@@ -133,25 +136,6 @@ export default function ProjectSettingsScreen({ projectKey }: ProjectSettingsScr
);
}
function resolveSelectedSettingsServerId(input: {
projectKey: string;
editableHosts: ProjectHostEntry[];
routedServerId: string | null;
hostSelection: { routeKey: string; serverId: string };
}): string {
const availableServerIds = new Set(input.editableHosts.map((host) => host.serverId));
if (
input.hostSelection.routeKey === input.projectKey &&
availableServerIds.has(input.hostSelection.serverId)
) {
return input.hostSelection.serverId;
}
if (input.routedServerId && availableServerIds.has(input.routedServerId)) {
return input.routedServerId;
}
return input.editableHosts[0]?.serverId ?? "";
}
function filterEditableHosts(project: ProjectSummary | undefined): ProjectHostEntry[] {
if (!project) return [];
return project.hosts.filter(