b4ce4d6eef
* refactor(web): improve compact desktop layouts * fix(web): address compact desktop review feedback * fix(web): address responsive review followups * fix(web): preserve compact sidebar restore sizing * fix(web): harden compact preset sidebar test * refactor(web): extract dockview layout hooks
92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
import type { LayoutState, LayoutIntent, LayoutIntentPanel, LayoutPanel } from "./types";
|
|
import { CENTER_GROUP, RIGHT_TOP_GROUP, RIGHT_BOTTOM_GROUP } from "./constants";
|
|
|
|
/** Well-known intent name constants (used as URL ?layout= values). */
|
|
export const INTENT_COMPACT = "compact";
|
|
export const INTENT_PLAN = "plan";
|
|
export const INTENT_PR_REVIEW = "pr-review";
|
|
|
|
/** Registry of named layout intents, keyed by URL param value. */
|
|
const NAMED_INTENTS: Record<string, LayoutIntent> = {
|
|
[INTENT_COMPACT]: { preset: "compact" },
|
|
[INTENT_PLAN]: { preset: "plan" },
|
|
[INTENT_PR_REVIEW]: {
|
|
panels: [
|
|
{
|
|
id: "pr-detail",
|
|
component: "pr-detail",
|
|
title: "Pull Request",
|
|
targetGroup: "center",
|
|
},
|
|
],
|
|
activePanels: {
|
|
[CENTER_GROUP]: "pr-detail",
|
|
[RIGHT_TOP_GROUP]: "changes",
|
|
},
|
|
},
|
|
};
|
|
|
|
/** Resolve a named intent string (from URL param) to a LayoutIntent, or null if unknown. */
|
|
export function resolveNamedIntent(name: string): LayoutIntent | null {
|
|
return NAMED_INTENTS[name] ?? null;
|
|
}
|
|
|
|
/** Map short aliases to well-known group IDs. */
|
|
const GROUP_ALIASES: Record<string, string> = {
|
|
center: CENTER_GROUP,
|
|
"right-top": RIGHT_TOP_GROUP,
|
|
"right-bottom": RIGHT_BOTTOM_GROUP,
|
|
};
|
|
|
|
function resolveGroupId(target: string): string {
|
|
return GROUP_ALIASES[target] ?? target;
|
|
}
|
|
|
|
/** Inject LayoutIntentPanels into the matching groups of a LayoutState. */
|
|
export function injectIntentPanels(state: LayoutState, panels: LayoutIntentPanel[]): LayoutState {
|
|
const columns = state.columns.map((col) => {
|
|
const groups = col.groups.map((group) => {
|
|
const matching = panels.filter((p) => {
|
|
const targetId = resolveGroupId(p.targetGroup ?? "center");
|
|
if (group.id === targetId) return true;
|
|
// Fallback: match center column's first group when no explicit group ID
|
|
if (targetId === CENTER_GROUP && col.id === "center" && col.groups[0] === group) {
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (matching.length === 0) return group;
|
|
|
|
const newPanels: LayoutPanel[] = matching.map((p) => ({
|
|
id: p.id,
|
|
component: p.component,
|
|
title: p.title,
|
|
...(p.tabComponent ? { tabComponent: p.tabComponent } : {}),
|
|
...(p.params ? { params: p.params } : {}),
|
|
}));
|
|
|
|
return { ...group, panels: [...group.panels, ...newPanels] };
|
|
});
|
|
return { ...col, groups };
|
|
});
|
|
return { columns };
|
|
}
|
|
|
|
/** Set activePanel on groups that match the override map. */
|
|
export function applyActivePanelOverrides(
|
|
state: LayoutState,
|
|
overrides: Record<string, string>,
|
|
): LayoutState {
|
|
const columns = state.columns.map((col) => {
|
|
const groups = col.groups.map((group) => {
|
|
if (!group.id || !overrides[group.id]) return group;
|
|
const targetPanelId = overrides[group.id];
|
|
if (!group.panels.some((p) => p.id === targetPanelId)) return group;
|
|
return { ...group, activePanel: targetPanelId };
|
|
});
|
|
return { ...col, groups };
|
|
});
|
|
return { columns };
|
|
}
|