86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import type { DockviewApi } from "dockview-react";
|
|
import type { LayoutState } from "./types";
|
|
import { toSerializedDockview } from "./serializer";
|
|
import {
|
|
SIDEBAR_LOCK,
|
|
SIDEBAR_GROUP,
|
|
CENTER_GROUP,
|
|
RIGHT_TOP_GROUP,
|
|
RIGHT_BOTTOM_GROUP,
|
|
TERMINAL_DEFAULT_ID,
|
|
LAYOUT_SIDEBAR_MAX_PX,
|
|
} from "./constants";
|
|
|
|
export type LayoutGroupIds = {
|
|
centerGroupId: string;
|
|
rightTopGroupId: string;
|
|
rightBottomGroupId: string;
|
|
sidebarGroupId: string;
|
|
};
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
export function getRootSplitview(api: DockviewApi): any | null {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const sv = (api as any).component?.gridview?.root?.splitview;
|
|
return sv?.resizeView && sv?.getViewSize ? sv : null;
|
|
}
|
|
|
|
/** Find a group by well-known ID, falling back to panel-based lookup. */
|
|
function findGroupId(api: DockviewApi, knownId: string, fallbackPanelId: string): string {
|
|
if (api.groups.some((g) => g.id === knownId)) return knownId;
|
|
const pnl = api.getPanel(fallbackPanelId);
|
|
return pnl?.group?.id ?? knownId;
|
|
}
|
|
|
|
export function resolveGroupIds(api: DockviewApi): LayoutGroupIds {
|
|
return {
|
|
sidebarGroupId: findGroupId(api, SIDEBAR_GROUP, "sidebar"),
|
|
centerGroupId: findGroupId(api, CENTER_GROUP, "chat"),
|
|
// Always use the well-known constant — do NOT fall back to the "changes"
|
|
// panel's current group. In plan mode the "changes" panel moves into the
|
|
// center group; a panel-based fallback would return the center group ID and
|
|
// defeat the auto-focus guard in changes-tab.tsx.
|
|
rightTopGroupId: RIGHT_TOP_GROUP,
|
|
rightBottomGroupId: findGroupId(api, RIGHT_BOTTOM_GROUP, TERMINAL_DEFAULT_ID),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Apply a LayoutState to DockviewApi via fromJSON.
|
|
* Computes sizes, serializes, applies, and returns group IDs.
|
|
*/
|
|
export function applyLayout(
|
|
api: DockviewApi,
|
|
state: LayoutState,
|
|
pinnedWidths: Map<string, number>,
|
|
): LayoutGroupIds {
|
|
const serialized = toSerializedDockview(state, api.width, api.height, pinnedWidths);
|
|
|
|
api.fromJSON(serialized);
|
|
|
|
// Lock sidebar group and enforce max-width constraint.
|
|
// Constraints are not serialized with layouts, so we must reapply after fromJSON.
|
|
const sb = api.getPanel("sidebar");
|
|
if (sb) {
|
|
sb.group.locked = SIDEBAR_LOCK;
|
|
sb.group.header.hidden = false;
|
|
sb.group.api.setConstraints({ maximumWidth: LAYOUT_SIDEBAR_MAX_PX });
|
|
}
|
|
|
|
// Enforce max-width on other pinned columns (e.g. right panel group).
|
|
for (const col of state.columns) {
|
|
if (col.id === "sidebar" || !col.pinned || !col.maxWidth) continue;
|
|
for (const group of col.groups) {
|
|
for (const p of group.panels) {
|
|
const pnl = api.getPanel(p.id);
|
|
if (pnl) {
|
|
pnl.group.api.setConstraints({ maximumWidth: col.maxWidth });
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return resolveGroupIds(api);
|
|
}
|