feat(app): polish workspace tabs and changes
Size tabs from rendered labels and switch to horizontal overflow once minimum click targets are reached, keeping the add-tab action adjacent until it must remain fixed. Make Changes an always-expanded document with an optional desktop navigation tree, keep Git actions in their platform-owned headers, remove pinned and inline split shortcuts, and place review tabs beside Changes.
This commit is contained in:
@@ -79,7 +79,6 @@ export interface PanelState {
|
||||
explorerTab: ExplorerTab;
|
||||
explorerTabByCheckout: Record<string, ExplorerTab>;
|
||||
expandedPathsByWorkspace: Record<string, string[]>;
|
||||
diffExpandedPathsByWorkspace: Record<string, string[]>;
|
||||
// Changes-view folder tree. Inverted semantics vs the fields above:
|
||||
// this stores COLLAPSED directory paths (empty = all folders expanded), keyed
|
||||
// by full uncompressed dir path, so folders default to expanded and new
|
||||
@@ -111,7 +110,6 @@ export interface PanelState {
|
||||
setExplorerTab: (tab: ExplorerTab) => void;
|
||||
setExplorerTabForCheckout: (params: ExplorerCheckoutContext & { tab: ExplorerTab }) => void;
|
||||
setExpandedPathsForWorkspace: (workspaceKey: string, paths: ExpandedPathsUpdate) => void;
|
||||
setDiffExpandedPathsForWorkspace: (workspaceKey: string, paths: string[]) => void;
|
||||
setDiffCollapsedFoldersForWorkspace: (workspaceKey: string, dirPaths: string[]) => void;
|
||||
activateExplorerTabForCheckout: (checkout: ExplorerCheckoutContext) => void;
|
||||
setSidebarWidth: (width: number) => void;
|
||||
@@ -148,7 +146,6 @@ export const usePanelStore = create<PanelState>()(
|
||||
explorerTab: "changes",
|
||||
explorerTabByCheckout: {},
|
||||
expandedPathsByWorkspace: {},
|
||||
diffExpandedPathsByWorkspace: {},
|
||||
diffCollapsedFoldersByWorkspace: {},
|
||||
sidebarWidth: DEFAULT_SIDEBAR_WIDTH,
|
||||
explorerWidth: DEFAULT_EXPLORER_SIDEBAR_WIDTH,
|
||||
@@ -276,13 +273,6 @@ export const usePanelStore = create<PanelState>()(
|
||||
},
|
||||
};
|
||||
}),
|
||||
setDiffExpandedPathsForWorkspace: (workspaceKey, paths) =>
|
||||
set((state) => ({
|
||||
diffExpandedPathsByWorkspace: {
|
||||
...state.diffExpandedPathsByWorkspace,
|
||||
[workspaceKey]: paths,
|
||||
},
|
||||
})),
|
||||
setDiffCollapsedFoldersForWorkspace: (workspaceKey, dirPaths) =>
|
||||
set((state) => ({
|
||||
diffCollapsedFoldersByWorkspace: {
|
||||
@@ -308,7 +298,7 @@ export const usePanelStore = create<PanelState>()(
|
||||
}),
|
||||
{
|
||||
name: "panel-state",
|
||||
version: 13,
|
||||
version: 14,
|
||||
storage: createValidatedPersistStorage(AsyncStorage, PanelPersistedStateSchema),
|
||||
migrate: (persistedState, version) => migratePanelState(persistedState, version, { isWeb }),
|
||||
partialize: (state) => ({
|
||||
@@ -316,7 +306,6 @@ export const usePanelStore = create<PanelState>()(
|
||||
explorerTab: state.explorerTab,
|
||||
explorerTabByCheckout: state.explorerTabByCheckout,
|
||||
expandedPathsByWorkspace: state.expandedPathsByWorkspace,
|
||||
diffExpandedPathsByWorkspace: state.diffExpandedPathsByWorkspace,
|
||||
diffCollapsedFoldersByWorkspace: state.diffCollapsedFoldersByWorkspace,
|
||||
sidebarWidth: state.sidebarWidth,
|
||||
explorerWidth: state.explorerWidth,
|
||||
|
||||
@@ -120,6 +120,14 @@ describe("panel-store migration", () => {
|
||||
expect(state.diffCollapsedFoldersByWorkspace).toEqual({ ws: ["src/app"] });
|
||||
});
|
||||
|
||||
it("drops the retired per-file diff expansion state", () => {
|
||||
const state = migratePanelState({ diffExpandedPathsByWorkspace: { ws: ["src/app.ts"] } }, 13, {
|
||||
isWeb: false,
|
||||
});
|
||||
|
||||
expect(state.diffExpandedPathsByWorkspace).toBeUndefined();
|
||||
});
|
||||
|
||||
it("replaces the dead explorer split ratio with the shared tree rail width", () => {
|
||||
const state = migratePanelState({ explorerFilesSplitRatio: 0.5 }, 12, { isWeb: false });
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ export const PanelPersistedStateSchema = z.strictObject({
|
||||
explorerTab: ExplorerTabSchema.optional(),
|
||||
explorerTabByCheckout: z.record(z.string(), ExplorerTabSchema).optional(),
|
||||
expandedPathsByWorkspace: z.record(z.string(), z.array(z.string())).optional(),
|
||||
// Accepted only so migration can discard the former per-file diff expansion state.
|
||||
diffExpandedPathsByWorkspace: z.record(z.string(), z.array(z.string())).optional(),
|
||||
diffCollapsedFoldersByWorkspace: z.record(z.string(), z.array(z.string())).optional(),
|
||||
sidebarWidth: z.number().optional(),
|
||||
@@ -290,13 +291,7 @@ export function migratePanelState(
|
||||
) {
|
||||
state.expandedPathsByWorkspace = {};
|
||||
}
|
||||
if (
|
||||
version < 10 ||
|
||||
typeof state.diffExpandedPathsByWorkspace !== "object" ||
|
||||
!state.diffExpandedPathsByWorkspace
|
||||
) {
|
||||
state.diffExpandedPathsByWorkspace = {};
|
||||
}
|
||||
delete state.diffExpandedPathsByWorkspace;
|
||||
if (
|
||||
version < 12 ||
|
||||
typeof state.diffCollapsedFoldersByWorkspace !== "object" ||
|
||||
|
||||
@@ -423,6 +423,25 @@ describe("workspace-layout-store actions", () => {
|
||||
expect(findPaneContainingTab(layout.root, "pull_request")?.id).toBe(explorerPaneId);
|
||||
});
|
||||
|
||||
it("places an auto-added pull request in the pane containing Changes", () => {
|
||||
const workspaceKey = createWorkspaceKey();
|
||||
const store = workspaceLayoutStore.getState();
|
||||
store.openTabFocused(workspaceKey, { kind: "working_diff" });
|
||||
|
||||
useWorkspaceLayoutIds("explorer");
|
||||
const explorerPaneId = store.splitPaneEmpty(workspaceKey, {
|
||||
targetPaneId: "main",
|
||||
position: "right",
|
||||
});
|
||||
store.setExplorerPaneId(workspaceKey, explorerPaneId);
|
||||
|
||||
store.observePullRequest(workspaceKey, "url:https://example.test/pulls/1");
|
||||
|
||||
const layout = workspaceLayoutStore.getState().layoutByWorkspace[workspaceKey];
|
||||
expect(findPaneContainingTab(layout.root, "working_diff")?.id).toBe("main");
|
||||
expect(findPaneContainingTab(layout.root, "pull_request")?.id).toBe("main");
|
||||
});
|
||||
|
||||
it("opens assistant files in an ensured explorer pane and reveals it on the next open", () => {
|
||||
const workspaceKey = createWorkspaceKey();
|
||||
const store = workspaceLayoutStore.getState();
|
||||
|
||||
@@ -521,10 +521,17 @@ export function createWorkspaceLayoutStore(
|
||||
}
|
||||
|
||||
const layout = getWorkspaceLayout(state.layoutByWorkspace, normalizedWorkspaceKey);
|
||||
const workingDiffTab = collectAllTabs(layout.root).find(
|
||||
(tab) => tab.target.kind === "working_diff",
|
||||
);
|
||||
const workingDiffPane = workingDiffTab
|
||||
? findPaneContainingTab(layout.root, workingDiffTab.tabId)
|
||||
: null;
|
||||
const explorerPaneId = state.explorerPaneIdByWorkspace[normalizedWorkspaceKey] ?? null;
|
||||
const explorerPane = findPaneById(layout.root, explorerPaneId);
|
||||
const placementLayout = explorerPane
|
||||
? (focusPaneInLayout({ layout, paneId: explorerPane.id }) ?? layout)
|
||||
const placementPane = workingDiffPane ?? explorerPane;
|
||||
const placementLayout = placementPane
|
||||
? (focusPaneInLayout({ layout, paneId: placementPane.id }) ?? layout)
|
||||
: layout;
|
||||
const result = openTabInLayoutFocused({
|
||||
layout: placementLayout,
|
||||
|
||||
Reference in New Issue
Block a user