mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-08 17:34:51 +00:00
* fix(app): translate the PR checks summary, sidebar status labels, and "Worked for" line These were written in the components, so they stayed English in every other language. They now come from the translation files, with copy for all nine supported languages. Closes #6190 * fix(app): rebuild translated labels when the app language changes The checks summary, sidebar status groups, and turn footer now take the translation function, so their memoized labels rebuild on a language switch. Russian one-check group labels use singular wording. * test(app): compare compact footer targets at sub-pixel precision The browser reports the 44pt footer buttons as 43.99999 wide on some runs, which fails the finger-size check on main as well. --------- Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
109 lines
3.9 KiB
TypeScript
109 lines
3.9 KiB
TypeScript
import type { TFunction } from "i18next";
|
|
import { buildStatusGroups } 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 {
|
|
resolveSidebarProjectIconTargets,
|
|
type SidebarProjectIconTarget,
|
|
} from "@/utils/sidebar-project-row-model";
|
|
import {
|
|
buildSidebarShortcutSections,
|
|
type SidebarShortcutModel,
|
|
type SidebarShortcutSection,
|
|
} from "@/utils/sidebar-shortcuts";
|
|
import { statusWorkspaceGroups, type SidebarWorkspaceGroup } from "./sidebar-labels";
|
|
|
|
export interface SidebarProjection {
|
|
pinnedGroups: PinnedSidebarGroups;
|
|
workspaceGroups: SidebarWorkspaceGroup[];
|
|
/**
|
|
* The project icons this projection needs fetched, keyed by `projectViewKey` — one per project,
|
|
* whatever the mode groups by. It sits here rather than beside `useProjectIcons` in the list
|
|
* because it is the same `projects` the rows above are projected from: a mode that renders a
|
|
* row can only ever ask for an icon this list already covers. It used to be derived in the
|
|
* list, under a `groupMode === "status"` gate written when status was the only mode that put
|
|
* icons on rows.
|
|
*/
|
|
projectIconTargets: SidebarProjectIconTarget[];
|
|
shortcutModel: SidebarShortcutModel;
|
|
}
|
|
|
|
export interface SidebarProjectionInput {
|
|
projects: SidebarProjectEntry[];
|
|
pinnedKeys: PinnedSidebarKeys;
|
|
pinnedWorkspaceOrder: string[];
|
|
workspaceEntriesByKey: ReadonlyMap<string, SidebarWorkspaceEntry>;
|
|
projectNamesByViewKey: Map<string, string>;
|
|
groupMode: SidebarGroupMode;
|
|
pinnedCollapsed: boolean;
|
|
collapsedProjectKeys: ReadonlySet<string>;
|
|
collapsedWorkspaceGroupKeys: ReadonlySet<string>;
|
|
t: TFunction;
|
|
}
|
|
|
|
export function buildSidebarProjection(input: SidebarProjectionInput): SidebarProjection {
|
|
const pinnedGroups = splitPinnedSidebarGroups({
|
|
projects: input.projects,
|
|
keys: input.pinnedKeys,
|
|
pinnedWorkspaceOrder: input.pinnedWorkspaceOrder,
|
|
});
|
|
const pinnedWorkspaceKeys = new Set(input.pinnedKeys.pinnedWorkspaceKeys);
|
|
const unpinnedWorkspaces = Array.from(input.workspaceEntriesByKey.values()).filter(
|
|
(workspace) => !pinnedWorkspaceKeys.has(workspace.workspaceKey),
|
|
);
|
|
// One switch decides both what the list groups by and what the keyboard shortcuts walk, so the
|
|
// two cannot disagree and a new grouping mode is a compile error here rather than a silent
|
|
// fall-through to the project rows.
|
|
const workspaceGroups = buildWorkspaceGroups(input, unpinnedWorkspaces);
|
|
|
|
const sections: SidebarShortcutSection[] = [];
|
|
if (!input.pinnedCollapsed) {
|
|
sections.push({ workspaces: pinnedGroups.pinnedChats });
|
|
}
|
|
if (input.groupMode === "project") {
|
|
sections.push(
|
|
...pinnedGroups.unpinnedProjects.map((project) => ({
|
|
workspaces: project.workspaces,
|
|
collapsed: input.collapsedProjectKeys.has(project.viewKey),
|
|
})),
|
|
);
|
|
} else {
|
|
sections.push(
|
|
...workspaceGroups.map((group) => ({
|
|
workspaces: group.rows,
|
|
collapsed: input.collapsedWorkspaceGroupKeys.has(group.key),
|
|
})),
|
|
);
|
|
}
|
|
|
|
return {
|
|
pinnedGroups,
|
|
workspaceGroups,
|
|
projectIconTargets: resolveSidebarProjectIconTargets(input.projects),
|
|
shortcutModel: buildSidebarShortcutSections({ sections }),
|
|
};
|
|
}
|
|
|
|
/** Project mode keeps its project headers and groups nothing; status mode groups the rows. */
|
|
function buildWorkspaceGroups(
|
|
input: SidebarProjectionInput,
|
|
unpinnedWorkspaces: SidebarWorkspaceEntry[],
|
|
): SidebarWorkspaceGroup[] {
|
|
switch (input.groupMode) {
|
|
case "project":
|
|
return [];
|
|
case "status":
|
|
return statusWorkspaceGroups(
|
|
buildStatusGroups(unpinnedWorkspaces, input.projectNamesByViewKey, input.t),
|
|
);
|
|
}
|
|
}
|