From 7554507a6ee8d8a1689ac1947a560033a1a941eb Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Fri, 6 Nov 2026 00:37:33 +0800 Subject: [PATCH] feat(vcs): resize the Push dialog's commits and changed files with a splitter The commits list and the changed files tree had fixed heights, so a push with one commit and many files left the files in a small scroll area and empty space above the buttons. They now sit in a vertical split that fills the dialog body, and the divider position is remembered. --- src/features/vcs/common.module.css | 21 +++++- src/features/vcs/remoteUi.tsx | 117 ++++++++++++++++++++--------- 2 files changed, 101 insertions(+), 37 deletions(-) diff --git a/src/features/vcs/common.module.css b/src/features/vcs/common.module.css index 05065dc6..030e549b 100644 --- a/src/features/vcs/common.module.css +++ b/src/features/vcs/common.module.css @@ -129,15 +129,32 @@ flex-direction: column; padding: 0 14px 14px; } +/* Push dialog: commits above their changed files, split by a draggable divider; the pair fills the body. */ +.pushSplit { + flex: 1; + min-height: min(540px, 60vh); +} +/* The panel's own `height: 100%` doesn't resolve against a flex-basis height in WebKit: stretch instead. */ +.pushSplit .pushSplitPanel { + height: auto; + align-self: stretch; +} +.pushSplitPanel > .pushListWrap { + min-height: 0; + padding-bottom: 8px; +} /* Push dialogs: the outgoing commits' changed files below the commits, the diff beside them. */ .pushChanges { - flex: none; + flex: 1; display: flex; flex-direction: column; min-height: 0; + padding-top: 8px; } .pushChanges .comparison { - height: min(360px, 45vh); + flex: 1; + height: auto; + min-height: 0; padding: 0 14px 14px; } .pushChangesTitle { diff --git a/src/features/vcs/remoteUi.tsx b/src/features/vcs/remoteUi.tsx index 6bedffcd..38ce7d70 100644 --- a/src/features/vcs/remoteUi.tsx +++ b/src/features/vcs/remoteUi.tsx @@ -5,7 +5,7 @@ import { call, commands } from "@/platform/ipc"; import { tx } from "@/platform/i18n"; import { workflowSettings } from "@/platform/workflowSettings"; import { notifications } from "@/workbench/contributions"; -import { Checkbox, Dialog, Input, List, Select, Spinner, T, Tree } from "@/ui"; +import { Checkbox, Dialog, Input, List, Select, Spinner, SplitGroup, SplitHandle, SplitPanel, T, Tree } from "@/ui"; import { ask } from "@/workbench/messages"; import { openDialog } from "./dialogs"; import { formatTime } from "./model"; @@ -340,6 +340,11 @@ function PushDialog({ target: pushTarget, onClose }: { target: PushTarget; onClo const [commits, setCommits] = useState(null); // The commit whose changes are shown; -1: all outgoing commits. const [shownCommit, setShownCommit] = useState(-1); + const [pushSplit, setPushSplit] = useState(loadPushSplit); + const keepPushSplit = (layout: Record) => { + setPushSplit(layout); + savePushSplit(layout); + }; const shownCommits = useMemo( () => (commits && shownCommit >= 0 && commits[shownCommit] ? [commits[shownCommit]] : (commits ?? [])), [commits, shownCommit], @@ -440,6 +445,36 @@ function PushDialog({ target: pushTarget, onClose }: { target: PushTarget; onClo ); }; + const commitList = ( +
+ {error ? ( +
{error}
+ ) : !commits ? ( +
+ +
+ ) : ( + c.id} + activeIndex={shownCommit} + onActiveChange={setShownCommit} + rowHeight={22} + aria-label="Outgoing commits" + className={styles.boxList} + empty={{upstream ? tx("Everything is up to date") : tx("No commits")}} + renderItem={(c) => ( + + {c.shortId} + {c.summary} + {c.author} + {formatTime(c.timeMs)} + + )} + /> + )} +
+ ); return ( {tx("New")}} -
- {error ? ( -
{error}
- ) : !commits ? ( -
- -
- ) : ( - c.id} - activeIndex={shownCommit} - onActiveChange={setShownCommit} - rowHeight={22} - aria-label="Outgoing commits" - className={styles.boxList} - empty={{upstream ? tx("Everything is up to date") : tx("No commits")}} - renderItem={(c) => ( - - {c.shortId} - {c.summary} - {c.author} - {formatTime(c.timeMs)} - - )} - /> - )} -
- = 0 && (commits?.length ?? 0) > 1 ? () => setShownCommit(-1) : undefined} - /> + {commits?.length && !error ? ( + + + {commitList} + + + + = 0 && commits.length > 1 ? () => setShownCommit(-1) : undefined} + /> + + + ) : ( + commitList + )}
); } +const PUSH_SPLIT_KEY = "openidea.vcs.pushSplit"; + +/** Heights of the Push dialog's commits and changed files, as the splitter left them. */ +function loadPushSplit(): Record | undefined { + try { + const v: unknown = JSON.parse(localStorage.getItem(PUSH_SPLIT_KEY) ?? "null"); + return v && typeof v === "object" && Object.values(v).every((n) => typeof n === "number") + ? (v as Record) + : undefined; + } catch { + return undefined; + } +} + +function savePushSplit(layout: Record) { + try { + localStorage.setItem(PUSH_SPLIT_KEY, JSON.stringify(layout)); + } catch { + /* kept for this dialog only */ + } +} + const SILENT_FORCE_PUSH_KEY = "openidea.vcs.silentForcePushTargets"; function silentForcePushTargets(): string[] {