Files
paseo/packages/app/src/components/sidebar/sidebar-projection.ts
T
Mohamed BoudraandGitHub b03dc804eb feat(app): make pinned workspaces sortable (#3341)
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.
2026-08-13 23:48:01 +02:00

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 }),
};
}