Reuse the existing workspace drag interaction for pinned rows and persist their local order across grouping modes. Keep pressed and dragged row scrims aligned with the active backdrop, and preserve memoized row rendering on web.
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { buildStatusGroups, type StatusGroup } from "@/hooks/sidebar-status-view-model";
|
|
import {
|
|
splitPinnedSidebarGroups,
|
|
type PinnedSidebarGroups,
|
|
type PinnedSidebarKeys,
|
|
} from "@/hooks/use-sidebar-pins";
|
|
import type {
|
|
SidebarProjectEntry,
|
|
SidebarWorkspaceEntry,
|
|
} from "@/hooks/use-sidebar-workspaces-list";
|
|
import type { SidebarGroupMode } from "@/stores/sidebar-view-store";
|
|
import {
|
|
buildSidebarShortcutSections,
|
|
type SidebarShortcutModel,
|
|
type SidebarShortcutSection,
|
|
} from "@/utils/sidebar-shortcuts";
|
|
|
|
export interface SidebarProjection {
|
|
pinnedGroups: PinnedSidebarGroups;
|
|
statusGroups: StatusGroup[];
|
|
shortcutModel: SidebarShortcutModel;
|
|
}
|
|
|
|
export function buildSidebarProjection(input: {
|
|
projects: SidebarProjectEntry[];
|
|
pinnedKeys: PinnedSidebarKeys;
|
|
pinnedWorkspaceOrder: string[];
|
|
workspaceEntriesByKey: ReadonlyMap<string, SidebarWorkspaceEntry>;
|
|
projectNamesByViewKey: Map<string, string>;
|
|
groupMode: SidebarGroupMode;
|
|
pinnedCollapsed: boolean;
|
|
collapsedProjectKeys: ReadonlySet<string>;
|
|
collapsedStatusGroupKeys: ReadonlySet<string>;
|
|
}): SidebarProjection {
|
|
const pinnedGroups = splitPinnedSidebarGroups({
|
|
projects: input.projects,
|
|
keys: input.pinnedKeys,
|
|
pinnedWorkspaceOrder: input.pinnedWorkspaceOrder,
|
|
});
|
|
const pinnedWorkspaceKeys = new Set(input.pinnedKeys.pinnedWorkspaceKeys);
|
|
const statusGroups =
|
|
input.groupMode === "status"
|
|
? buildStatusGroups(
|
|
Array.from(input.workspaceEntriesByKey.values()).filter(
|
|
(workspace) => !pinnedWorkspaceKeys.has(workspace.workspaceKey),
|
|
),
|
|
input.projectNamesByViewKey,
|
|
)
|
|
: [];
|
|
|
|
const sections: SidebarShortcutSection[] = [];
|
|
if (!input.pinnedCollapsed) {
|
|
sections.push({ workspaces: pinnedGroups.pinnedChats });
|
|
}
|
|
if (input.groupMode === "status") {
|
|
sections.push(
|
|
...statusGroups.map((group) => ({
|
|
workspaces: group.rows,
|
|
collapsed: input.collapsedStatusGroupKeys.has(group.bucket),
|
|
})),
|
|
);
|
|
} else {
|
|
sections.push(
|
|
...pinnedGroups.unpinnedProjects.map((project) => ({
|
|
workspaces: project.workspaces,
|
|
collapsed: input.collapsedProjectKeys.has(project.viewKey),
|
|
})),
|
|
);
|
|
}
|
|
|
|
return {
|
|
pinnedGroups,
|
|
statusGroups,
|
|
shortcutModel: buildSidebarShortcutSections({ sections }),
|
|
};
|
|
}
|