import type { SidebarProjectEntry } from "@/hooks/use-sidebar-workspaces-list"; export interface SidebarProjectHostTarget { serverId: string; iconWorkingDir: string; } export type SidebarProjectTrailingAction = | { kind: "new_workspace"; target: SidebarProjectHostTarget } | { kind: "none" }; export interface SidebarProjectSectionRowModel { kind: "project_section"; chevron: "expand" | "collapse"; trailingAction: SidebarProjectTrailingAction; } export type SidebarProjectRowModel = SidebarProjectSectionRowModel; const EMPTY_MULTIPLICITY_MAP: ReadonlyMap = new Map(); function hostTarget(input: { serverId: string; iconWorkingDir: string; }): SidebarProjectHostTarget | null { const iconWorkingDir = input.iconWorkingDir.trim(); if (!input.serverId || !iconWorkingDir) { return null; } return { serverId: input.serverId, iconWorkingDir }; } export function resolveSidebarProjectIconTarget( project: SidebarProjectEntry, ): SidebarProjectHostTarget | null { for (const host of project.hosts) { const target = hostTarget(host); if (target) { return target; } } return null; } // A project can host a brand-new workspace on a host when that host can create a // git worktree (git projects) OR the host supports running multiple independent // workspaces per directory (`workspaceMultiplicity`), which is what lets non-git // directories add a second workspace. Mirrors the gate used by the global "New // workspace" affordances (use-global-new-workspace-action.ts and left-sidebar's // SidebarNewWorkspaceHeaderRow): `canCreateWorktree || supportsMultiplicity`. function resolveNewWorkspaceTarget( project: SidebarProjectEntry, supportsMultiplicityByServerId: ReadonlyMap, ): SidebarProjectHostTarget | null { for (const host of project.hosts) { if (!host.canCreateWorktree && !supportsMultiplicityByServerId.get(host.serverId)) { continue; } const target = hostTarget(host); if (target) { return target; } } return null; } function projectTrailingAction( project: SidebarProjectEntry, supportsMultiplicityByServerId: ReadonlyMap, ): SidebarProjectTrailingAction { const target = resolveNewWorkspaceTarget(project, supportsMultiplicityByServerId); return target ? { kind: "new_workspace", target } : { kind: "none" }; } export function buildSidebarProjectRowModel(input: { project: SidebarProjectEntry; collapsed: boolean; supportsMultiplicityByServerId?: ReadonlyMap; }): SidebarProjectRowModel { return { kind: "project_section", chevron: input.collapsed ? "expand" : "collapse", trailingAction: projectTrailingAction( input.project, input.supportsMultiplicityByServerId ?? EMPTY_MULTIPLICITY_MAP, ), }; }