Show New Workspace isolation controls immediately (#2702)
* fix(workspaces): show isolation without checkout delay * fix(workspaces): trust hydrated project capability * fix(workspaces): resolve branch before creation * fix(workspaces): honor invalidated checkout status * fix(workspaces): preserve isolation while projects load * fix(workspaces): keep provisional project routes usable Route-derived projects do not know their worktree capability. Represent that uncertainty at the placement boundary so remembered worktree intent survives hydration without disabling the New Workspace screen indefinitely.
This commit is contained in:
@@ -35,14 +35,14 @@ export function hostProjectFromRoute(route: HostProjectRouteContext): HostProjec
|
||||
viewKey: createProjectViewKey({ kind: "placement", serverId: route.serverId, projectId }),
|
||||
projectKey: null,
|
||||
projectName: trimOptional(route.displayName) || projectId,
|
||||
projectKind: "git",
|
||||
projectKind: "unknown",
|
||||
iconWorkingDir,
|
||||
hosts: [
|
||||
{
|
||||
serverId: route.serverId,
|
||||
projectId,
|
||||
iconWorkingDir,
|
||||
canCreateWorktree: true,
|
||||
worktreeSupport: "unknown",
|
||||
},
|
||||
],
|
||||
workspaceKeys: [],
|
||||
@@ -80,7 +80,7 @@ export function hostProjectFromWorkspace(input: {
|
||||
serverId: input.serverId,
|
||||
projectId: input.workspace.projectId,
|
||||
iconWorkingDir,
|
||||
canCreateWorktree: canCreate,
|
||||
worktreeSupport: canCreate ? "supported" : "unsupported",
|
||||
},
|
||||
],
|
||||
workspaceKeys: [`${input.serverId}:${input.workspace.id}`],
|
||||
@@ -88,7 +88,7 @@ export function hostProjectFromWorkspace(input: {
|
||||
}
|
||||
|
||||
function projectCanCreateWorktree(project: HostProjectListItem): boolean {
|
||||
return project.hosts.some((h) => h.canCreateWorktree);
|
||||
return project.hosts.some((host) => host.worktreeSupport !== "unsupported");
|
||||
}
|
||||
|
||||
function getHostProjectPlacement(
|
||||
@@ -101,6 +101,13 @@ function getHostProjectPlacement(
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getWorktreeSupportForHostProject(input: {
|
||||
project: HostProjectListItem;
|
||||
serverId: string;
|
||||
}): WorkspaceStructureHostPlacement["worktreeSupport"] {
|
||||
return getHostProjectPlacement(input.project, input.serverId)?.worktreeSupport ?? "unknown";
|
||||
}
|
||||
|
||||
export function getHostProjectSourceDirectory(
|
||||
project: HostProjectListItem,
|
||||
serverId: string,
|
||||
@@ -121,7 +128,7 @@ export function canCreateWorkspaceForHostProject(input: {
|
||||
if (!host) {
|
||||
return false;
|
||||
}
|
||||
return input.allowAllProjects || host.canCreateWorktree;
|
||||
return input.allowAllProjects || host.worktreeSupport !== "unsupported";
|
||||
}
|
||||
|
||||
export function filterWorkspaceProjectsForHost(input: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
canCreateWorkspaceForHostProject,
|
||||
getHostProjectId,
|
||||
getHostProjectSourceDirectory,
|
||||
getWorktreeSupportForHostProject,
|
||||
hostProjectFromRoute,
|
||||
} from "./host-project-model";
|
||||
|
||||
@@ -19,13 +20,13 @@ function project(): HostProjectListItem {
|
||||
serverId: "host-a",
|
||||
projectId: "prj_a",
|
||||
iconWorkingDir: "/repo/a",
|
||||
canCreateWorktree: true,
|
||||
worktreeSupport: "supported" as const,
|
||||
},
|
||||
{
|
||||
serverId: "host-b",
|
||||
projectId: "prj_b",
|
||||
iconWorkingDir: "/repo/b",
|
||||
canCreateWorktree: true,
|
||||
worktreeSupport: "supported" as const,
|
||||
},
|
||||
],
|
||||
workspaceKeys: [],
|
||||
@@ -49,6 +50,38 @@ describe("host project lookups", () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test("checks worktree capability against the selected host placement", () => {
|
||||
const groupedProject = project();
|
||||
groupedProject.hosts[1] = {
|
||||
...groupedProject.hosts[1]!,
|
||||
worktreeSupport: "unsupported" as const,
|
||||
};
|
||||
|
||||
expect(getWorktreeSupportForHostProject({ project: groupedProject, serverId: "host-a" })).toBe(
|
||||
"supported",
|
||||
);
|
||||
expect(getWorktreeSupportForHostProject({ project: groupedProject, serverId: "host-b" })).toBe(
|
||||
"unsupported",
|
||||
);
|
||||
expect(getWorktreeSupportForHostProject({ project: groupedProject, serverId: "missing" })).toBe(
|
||||
"unknown",
|
||||
);
|
||||
});
|
||||
|
||||
test("marks route placeholder worktree support as unknown", () => {
|
||||
const routeProject = hostProjectFromRoute({
|
||||
serverId: "host-a",
|
||||
projectId: "prj_a",
|
||||
displayName: "App",
|
||||
sourceDirectory: "/repo/a",
|
||||
});
|
||||
expect(routeProject).not.toBeNull();
|
||||
expect(routeProject!.projectKind).toBe("unknown");
|
||||
expect(getWorktreeSupportForHostProject({ project: routeProject!, serverId: "host-a" })).toBe(
|
||||
"unknown",
|
||||
);
|
||||
});
|
||||
|
||||
test("builds an unhydrated route project around the routed project id", () => {
|
||||
expect(
|
||||
hostProjectFromRoute({
|
||||
|
||||
@@ -7,6 +7,7 @@ export {
|
||||
filterWorkspaceProjectsForHost,
|
||||
getHostProjectSourceDirectory,
|
||||
getHostProjectId,
|
||||
getWorktreeSupportForHostProject,
|
||||
hostProjectFromRoute,
|
||||
hostProjectFromWorkspace,
|
||||
resolveHostProjectCandidate,
|
||||
|
||||
@@ -5,14 +5,14 @@ export interface WorkspaceStructureHostPlacement {
|
||||
serverId: string;
|
||||
projectId: string;
|
||||
iconWorkingDir: string;
|
||||
canCreateWorktree: boolean;
|
||||
worktreeSupport: "supported" | "unsupported" | "unknown";
|
||||
}
|
||||
|
||||
export interface WorkspaceStructureProject {
|
||||
viewKey: string;
|
||||
projectKey: string | null;
|
||||
projectName: string;
|
||||
projectKind: WorkspaceDescriptor["projectKind"];
|
||||
projectKind: WorkspaceDescriptor["projectKind"] | "unknown";
|
||||
iconWorkingDir: string;
|
||||
hosts: WorkspaceStructureHostPlacement[];
|
||||
workspaceKeys: string[];
|
||||
@@ -157,7 +157,7 @@ function addProjectToView(input: {
|
||||
serverId,
|
||||
projectId: project.projectId,
|
||||
iconWorkingDir: project.projectRootPath,
|
||||
canCreateWorktree: project.projectKind === "git",
|
||||
worktreeSupport: project.projectKind === "git" ? "supported" : "unsupported",
|
||||
};
|
||||
const draft = byProject.get(viewKey);
|
||||
if (!draft) {
|
||||
|
||||
Reference in New Issue
Block a user