@xia-sc/dsh-git 0.5.3 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +26 -7
- package/README.md +16 -6
- package/lib/client.js +529 -229
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -15,13 +15,16 @@ new-branch-from-base.
|
|
|
15
15
|
## UI
|
|
16
16
|
|
|
17
17
|
- **Floating block** (`shell.overlay`): collapsed = renders nothing (no
|
|
18
|
-
floating element that could cover the input); expanded =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
the affected files instead of switching,
|
|
22
|
-
hatch
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
floating element that could cover the input); expanded = one workflow read
|
|
19
|
+
top-down: status line (pending count, ahead/behind, upstream) → the branch
|
|
20
|
+
switcher with its **dirty-tree pre-check** (selecting a branch while
|
|
21
|
+
uncommitted changes exist warns with the affected files instead of switching,
|
|
22
|
+
plus a "switch anyway" escape hatch) → a **network toolbar** (Fetch / Pull /
|
|
23
|
+
Push, three equal columns, Push being the primary button) → a **commit card**
|
|
24
|
+
(Stage all + draft basis + "✨ AI draft" in equal columns, the message input
|
|
25
|
+
below it and the commit button) → two list cards. Every button group is split
|
|
26
|
+
evenly instead of sizing itself to its label.
|
|
27
|
+
**Operation feedback is pinned to the very
|
|
25
28
|
top of the panel and stays one line tall** — the busy label and the last
|
|
26
29
|
operation's result are the first rows of the body. The result is a localized
|
|
27
30
|
phrase ("Pushed", "Staged everything", "Switched to x"); git's own output (a
|
|
@@ -36,6 +39,18 @@ new-branch-from-base.
|
|
|
36
39
|
new branch name + base-branch picker (local branches or full remote refs
|
|
37
40
|
like `origin/feature/x`) — confirming creates the branch from the base and
|
|
38
41
|
switches to it.
|
|
42
|
+
- **Changes and recent commits are two cards**: a change row is "monospace path
|
|
43
|
+
+ status chip" (path first, so the paths line up in a column; modified=amber,
|
|
44
|
+
added/untracked=green, deleted/conflict=red, renamed=blue; the file the diff
|
|
45
|
+
pane is showing is highlighted), a commit row is "short sha + subject". Each
|
|
46
|
+
card's header (`▾ Changes 12`) collapses the whole section and starts
|
|
47
|
+
**expanded** — a Git panel must not hide the user's own changes; a list past
|
|
48
|
+
8 / 5 rows offers "Show all N" at the bottom, which is a separate state, so the
|
|
49
|
+
chevron always points the right way.
|
|
50
|
+
- **Refreshing never flashes**: clicking ↻ or any post-action re-read keeps the
|
|
51
|
+
panel's content (a same-workspace re-read does not fall back to a "loading"
|
|
52
|
+
line and snap back); the header's refresh button greys out and reads
|
|
53
|
+
"Refreshing…".
|
|
39
54
|
- **Click a change to see its diff**: clicking any row of the change list grows
|
|
40
55
|
the panel from its 400px single column into two panes — the full workbench on
|
|
41
56
|
the left, that file's unified diff on the right (see *The diff viewer* below).
|
|
@@ -62,6 +77,10 @@ the first selection expands the list to its full length.
|
|
|
62
77
|
panel (the workbench keeps its width) and the diff takes the rest, 1:1 with the
|
|
63
78
|
pointer because the panel anchors its left edge on grab. Double-clicking the
|
|
64
79
|
edge resets the width, and the panel always stays inside the viewport.
|
|
80
|
+
- **A stable box while the diff is open**: selecting a file pins the panel's height
|
|
81
|
+
(both columns run to the bottom), so the diff arriving, switching files and
|
|
82
|
+
collapsing again only scroll inside the panes — the panel never resizes under
|
|
83
|
+
the pointer.
|
|
65
84
|
- **Staged / unstaged**: by default the pane follows the data — unstaged when
|
|
66
85
|
that side has anything, staged otherwise — with two chips to switch by hand
|
|
67
86
|
(an empty side is dimmed). When a file has changes on both sides, one click
|
package/README.md
CHANGED
|
@@ -13,12 +13,13 @@ DeepSeek Harness Web GUI 的完整 Git 管理插件,形态为一个**可折叠
|
|
|
13
13
|
## 界面
|
|
14
14
|
|
|
15
15
|
- **悬浮面板**(`shell.overlay`):折叠时不渲染任何元素(不会遮挡输入框);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"仍要切换"
|
|
19
|
-
|
|
20
|
-
Ctrl/Cmd+Enter
|
|
21
|
-
|
|
16
|
+
展开后自上而下是一条工作流:状态行(未提交计数、领先/落后、上游)→
|
|
17
|
+
带 **脏树预检** 的分支切换器(有未提交修改时选择分支,会先显示受影响文件列表
|
|
18
|
+
警告而不是直接切换,并提供"仍要切换"按钮)→ **网络工具条**(拉取更新 / 拉取合并 /
|
|
19
|
+
推送,三等宽,"推送"是主按钮)→ **提交卡片**("暂存全部" + AI 生成依据 +
|
|
20
|
+
"✨ AI 生成"三等宽,下面是提交信息输入框(多行文本框,回车换行、Ctrl/Cmd+Enter
|
|
21
|
+
提交)与提交按钮)→ 两张列表卡片。按钮一律**等宽分栏**,不再是一排宽窄不一的按钮。
|
|
22
|
+
**操作反馈固定钉在面板最上边,而且只有一行**——"推送中…"和上次操作的结果都在
|
|
22
23
|
body 的第一行;结果是一个中文短句("已推送"/"已暂存全部"/"已切换到 xxx"),git 自己的输出
|
|
23
24
|
(push 的 sideband banner、`LF will be replaced by CRLF` 这类提示)收在右侧的"详情 ▾"里,点开才展开,
|
|
24
25
|
不会被变更列表和最近提交顶到看不见的地方。面板**可通过顶栏拖动**(按住带 Git 标题的
|
|
@@ -27,6 +28,13 @@ DeepSeek Harness Web GUI 的完整 Git 管理插件,形态为一个**可折叠
|
|
|
27
28
|
分支切换器旁边的"+ 新建分支"按钮会展开一个内联表单:新分支名 + 基分支
|
|
28
29
|
选择器(本地分支或 `origin/feature/x` 这样的完整远端引用)——确认后从
|
|
29
30
|
该基分支创建新分支并切换过去。
|
|
31
|
+
- **变更 / 最近提交两张卡片**:变更列表每行是「等宽路径 + 状态色标签」(路径在左,
|
|
32
|
+
所以一列路径对得齐;修改=橙、新增·未跟踪=绿、删除·冲突=红、重命名=蓝,
|
|
33
|
+
当前正在看的那一行整行高亮);最近提交每行是「短 sha + 主题」。两张卡片的标题行
|
|
34
|
+
(`▾ 变更 12`)点一下整段收起/展开,**默认展开**——面板不该把用户自己的改动藏起来;
|
|
35
|
+
列表超过 8 / 5 行时底部出现「显示全部 N 项」,与折叠是两件事,所以箭头永远指对方向。
|
|
36
|
+
- **刷新不闪**:点 ↻ 或任何操作之后的重读都**保留面板内容**(同一个工作区不会退回
|
|
37
|
+
一行 "读取中…" 再弹回来),只在标题栏把刷新按钮置灰并写着"刷新中…"。
|
|
30
38
|
- **点击变更看差异**:点变更列表里的任意一行,面板会从 400px 的单栏展开成
|
|
31
39
|
两栏——左边照旧是完整工作台,右边是该文件的 unified diff(见下文
|
|
32
40
|
「差异查看」)。再点同一行、或点差异标题栏的 `×`,就收回单栏。
|
|
@@ -47,6 +55,8 @@ DeepSeek Harness Web GUI 的完整 Git 管理插件,形态为一个**可折叠
|
|
|
47
55
|
- **可拖拽调宽**:拖动**面板最右侧那条边**即改差异栏宽度——左栏(工作台)宽度不变,
|
|
48
56
|
面板整体变宽、差异栏跟着长;双击这条边复位。面板始终留在视口内,窗口变窄时
|
|
49
57
|
会自动收回;拖动时面板会就地锚定左边缘,所以指针与这条边是 1:1 跟手的。
|
|
58
|
+
- **打开差异时尺寸是稳定的**:一选中文件,面板就定好了高度(两栏都铺到面板底部),
|
|
59
|
+
diff 读回来、切文件、来回点收起都只在栏内滚动,面板本身不会跟着内容跳一下。
|
|
50
60
|
- **未暂存 / 已暂存**:默认自动跟随数据——未暂存有内容就显示未暂存,否则显示
|
|
51
61
|
已暂存;顶部两个 chip 可手动切换,空的一侧置灰。同一个文件两边都有改动时,
|
|
52
62
|
一次点击看到的是最关心的那一侧,另一侧一键可达。
|
package/lib/client.js
CHANGED
|
@@ -38,6 +38,7 @@ window.__ModuleLoader__.load({
|
|
|
38
38
|
"panel.title": "Git",
|
|
39
39
|
"panel.collapse": "收起",
|
|
40
40
|
"refresh.aria": "刷新 Git 状态",
|
|
41
|
+
"refresh.busy": "刷新中…",
|
|
41
42
|
"branch.aria": "当前 Git 分支",
|
|
42
43
|
"switch.aria": "切换分支",
|
|
43
44
|
"switch.dirtyWarn": "有 {count} 个未提交文件(如 {paths}),切换分支可能被 git 拒绝,请先提交或暂存",
|
|
@@ -77,8 +78,12 @@ window.__ModuleLoader__.load({
|
|
|
77
78
|
"generate.failed": "生成失败",
|
|
78
79
|
"commit.placeholder": "提交信息(可多行,Ctrl+Enter 提交)…",
|
|
79
80
|
"commit.empty": "请输入提交信息",
|
|
80
|
-
"changes.title": "
|
|
81
|
+
"changes.title": "变更",
|
|
81
82
|
"changes.none": "工作区干净",
|
|
83
|
+
// Section footer: the list previews its first N rows and this says how
|
|
84
|
+
// many more there are, instead of a bare "▾ 13".
|
|
85
|
+
"section.more": "显示全部 {count} 项",
|
|
86
|
+
"section.less": "只看前几项",
|
|
82
87
|
"diff.title": "差异",
|
|
83
88
|
"diff.open": "查看差异",
|
|
84
89
|
"diff.close": "关闭差异",
|
|
@@ -137,6 +142,7 @@ window.__ModuleLoader__.load({
|
|
|
137
142
|
"panel.title": "Git",
|
|
138
143
|
"panel.collapse": "Collapse",
|
|
139
144
|
"refresh.aria": "Refresh Git status",
|
|
145
|
+
"refresh.busy": "Refreshing…",
|
|
140
146
|
"branch.aria": "Current git branch",
|
|
141
147
|
"switch.aria": "Switch branch",
|
|
142
148
|
"switch.dirtyWarn": "{count} uncommitted file(s) (e.g. {paths}) may block the switch — commit or stash first",
|
|
@@ -176,8 +182,10 @@ window.__ModuleLoader__.load({
|
|
|
176
182
|
"generate.failed": "Draft failed",
|
|
177
183
|
"commit.placeholder": "Commit message (multi-line allowed, Ctrl+Enter commits)…",
|
|
178
184
|
"commit.empty": "Enter a commit message",
|
|
179
|
-
"changes.title": "Changes
|
|
185
|
+
"changes.title": "Changes",
|
|
180
186
|
"changes.none": "Working tree clean",
|
|
187
|
+
"section.more": "Show all {count}",
|
|
188
|
+
"section.less": "Show fewer",
|
|
181
189
|
"diff.title": "Diff",
|
|
182
190
|
"diff.open": "View diff",
|
|
183
191
|
"diff.close": "Close diff",
|
|
@@ -269,8 +277,8 @@ window.__ModuleLoader__.load({
|
|
|
269
277
|
display: "flex",
|
|
270
278
|
alignItems: "center",
|
|
271
279
|
gap: 8,
|
|
272
|
-
padding: "8px
|
|
273
|
-
borderBottom: "1px solid var(--dsw-alias-border-
|
|
280
|
+
padding: "8px 10px",
|
|
281
|
+
borderBottom: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.22))",
|
|
274
282
|
flex: "none",
|
|
275
283
|
cursor: "move",
|
|
276
284
|
userSelect: "none",
|
|
@@ -284,11 +292,39 @@ window.__ModuleLoader__.load({
|
|
|
284
292
|
fontSize: 13,
|
|
285
293
|
fontWeight: 600,
|
|
286
294
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
295
|
+
flex: "none",
|
|
296
|
+
whiteSpace: "nowrap"
|
|
297
|
+
},
|
|
298
|
+
// The workspace path takes the header's slack: it is the one field whose
|
|
299
|
+
// truncation must never move the buttons beside it.
|
|
300
|
+
cwdPath: {
|
|
287
301
|
flex: "1",
|
|
288
302
|
minWidth: 0,
|
|
289
303
|
overflow: "hidden",
|
|
290
304
|
textOverflow: "ellipsis",
|
|
291
|
-
whiteSpace: "nowrap"
|
|
305
|
+
whiteSpace: "nowrap",
|
|
306
|
+
fontSize: 11,
|
|
307
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
308
|
+
textAlign: "right"
|
|
309
|
+
},
|
|
310
|
+
// Square ghost icon button: the panel's own chrome (refresh / collapse).
|
|
311
|
+
iconButton: {
|
|
312
|
+
flex: "none",
|
|
313
|
+
display: "inline-flex",
|
|
314
|
+
alignItems: "center",
|
|
315
|
+
justifyContent: "center",
|
|
316
|
+
width: 24,
|
|
317
|
+
height: 24,
|
|
318
|
+
padding: 0,
|
|
319
|
+
border: "1px solid transparent",
|
|
320
|
+
borderRadius: 6,
|
|
321
|
+
background: "transparent",
|
|
322
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
323
|
+
font: "inherit",
|
|
324
|
+
fontSize: 13,
|
|
325
|
+
lineHeight: "20px",
|
|
326
|
+
boxSizing: "border-box",
|
|
327
|
+
cursor: "pointer"
|
|
292
328
|
},
|
|
293
329
|
body: {
|
|
294
330
|
flex: "1",
|
|
@@ -299,9 +335,36 @@ window.__ModuleLoader__.load({
|
|
|
299
335
|
row: {
|
|
300
336
|
display: "flex",
|
|
301
337
|
alignItems: "center",
|
|
302
|
-
gap:
|
|
338
|
+
gap: 6,
|
|
303
339
|
margin: "6px 0"
|
|
304
340
|
},
|
|
341
|
+
// One action row inside a card: the gap is owned by the card, not the row.
|
|
342
|
+
rowTight: {
|
|
343
|
+
display: "flex",
|
|
344
|
+
alignItems: "center",
|
|
345
|
+
gap: 6,
|
|
346
|
+
minWidth: 0
|
|
347
|
+
},
|
|
348
|
+
// Equal-width action buttons: a row of auto-width labels was the messy
|
|
349
|
+
// part of the old layout — every group now shares the row evenly.
|
|
350
|
+
grow: {
|
|
351
|
+
flex: "1 1 0",
|
|
352
|
+
minWidth: 0,
|
|
353
|
+
padding: "0 6px",
|
|
354
|
+
textAlign: "center"
|
|
355
|
+
},
|
|
356
|
+
// Card grouping the whole commit flow (stage → draft → message → commit).
|
|
357
|
+
card: {
|
|
358
|
+
margin: "6px 0",
|
|
359
|
+
padding: 8,
|
|
360
|
+
display: "flex",
|
|
361
|
+
flexDirection: "column",
|
|
362
|
+
gap: 6,
|
|
363
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.22))",
|
|
364
|
+
borderRadius: 8,
|
|
365
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(127,127,127,0.06))",
|
|
366
|
+
minWidth: 0
|
|
367
|
+
},
|
|
305
368
|
warn: {
|
|
306
369
|
display: "flex",
|
|
307
370
|
alignItems: "center",
|
|
@@ -309,18 +372,22 @@ window.__ModuleLoader__.load({
|
|
|
309
372
|
margin: "6px 0",
|
|
310
373
|
padding: "6px 8px",
|
|
311
374
|
borderRadius: 8,
|
|
312
|
-
background: "var(--dsw-alias-state-
|
|
313
|
-
border: "1px solid var(--dsw-alias-state-
|
|
314
|
-
color: "var(--dsw-alias-state-
|
|
375
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f0a020) 14%, transparent)",
|
|
376
|
+
border: "1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f0a020) 40%, transparent)",
|
|
377
|
+
color: "var(--dsw-alias-state-warn-primary, #f0a020)",
|
|
315
378
|
fontSize: 12,
|
|
316
379
|
lineHeight: "16px"
|
|
317
380
|
},
|
|
381
|
+
// The branch chip — only for the detached-HEAD notice, so it carries the
|
|
382
|
+
// warning colour rather than the accent.
|
|
318
383
|
chip: {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
borderRadius: 999,
|
|
384
|
+
flex: "none",
|
|
385
|
+
maxWidth: "62%",
|
|
322
386
|
padding: "0 8px",
|
|
323
|
-
|
|
387
|
+
borderRadius: 6,
|
|
388
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f0a020) 16%, transparent)",
|
|
389
|
+
color: "var(--dsw-alias-state-warn-primary, #f0a020)",
|
|
390
|
+
fontWeight: 600,
|
|
324
391
|
fontSize: 12,
|
|
325
392
|
lineHeight: "20px",
|
|
326
393
|
overflow: "hidden",
|
|
@@ -328,40 +395,58 @@ window.__ModuleLoader__.load({
|
|
|
328
395
|
whiteSpace: "nowrap"
|
|
329
396
|
},
|
|
330
397
|
dirty: {
|
|
398
|
+
flex: "none",
|
|
331
399
|
color: "var(--dsw-alias-state-warn-primary, #f0a020)",
|
|
332
400
|
fontWeight: 600,
|
|
333
401
|
fontSize: 12
|
|
334
402
|
},
|
|
335
403
|
meta: {
|
|
336
|
-
color: "var(--dsw-alias-label-
|
|
337
|
-
fontSize:
|
|
404
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
405
|
+
fontSize: 11
|
|
338
406
|
},
|
|
339
407
|
button: {
|
|
340
|
-
background: "var(--dsw-alias-
|
|
408
|
+
background: "color-mix(in srgb, var(--dsw-alias-label-primary, #e5e7eb) 8%, transparent)",
|
|
341
409
|
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
342
|
-
borderRadius:
|
|
343
|
-
color: "var(--dsw-alias-label-
|
|
410
|
+
borderRadius: 7,
|
|
411
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
344
412
|
font: "inherit",
|
|
345
413
|
fontSize: 12,
|
|
346
|
-
lineHeight: "
|
|
414
|
+
lineHeight: "24px",
|
|
415
|
+
height: 26,
|
|
347
416
|
padding: "0 10px",
|
|
417
|
+
boxSizing: "border-box",
|
|
348
418
|
cursor: "pointer",
|
|
349
|
-
flex: "none"
|
|
419
|
+
flex: "none",
|
|
420
|
+
whiteSpace: "nowrap",
|
|
421
|
+
overflow: "hidden",
|
|
422
|
+
textOverflow: "ellipsis"
|
|
350
423
|
},
|
|
351
424
|
buttonPrimary: {
|
|
352
|
-
|
|
425
|
+
// The harness's own primary button: the label token IS the fill, with
|
|
426
|
+
// `label-primary-foreground` as the text on top. It reads near-black on
|
|
427
|
+
// light and near-white on dark (an inverted contrast button).
|
|
428
|
+
// `--dsw-alias-brand-primary` is that same contrast colour, NOT an
|
|
429
|
+
// accent — pairing it with `#fff` text made 推送 a white block with
|
|
430
|
+
// invisible text in the dark theme, and 提交 an empty grey box.
|
|
431
|
+
background: "var(--dsw-alias-button-primary-fill, var(--dsw-alias-label-primary, #e5e7eb))",
|
|
353
432
|
border: "1px solid transparent",
|
|
354
|
-
borderRadius:
|
|
355
|
-
color: "#
|
|
433
|
+
borderRadius: 7,
|
|
434
|
+
color: "var(--dsw-alias-label-primary-foreground, var(--dsw-alias-bg-base, #1e1e1e))",
|
|
356
435
|
font: "inherit",
|
|
357
436
|
fontSize: 12,
|
|
358
|
-
|
|
437
|
+
fontWeight: 600,
|
|
438
|
+
lineHeight: "24px",
|
|
439
|
+
height: 26,
|
|
359
440
|
padding: "0 10px",
|
|
441
|
+
boxSizing: "border-box",
|
|
360
442
|
cursor: "pointer",
|
|
361
|
-
flex: "none"
|
|
443
|
+
flex: "none",
|
|
444
|
+
whiteSpace: "nowrap",
|
|
445
|
+
overflow: "hidden",
|
|
446
|
+
textOverflow: "ellipsis"
|
|
362
447
|
},
|
|
363
448
|
buttonDisabled: {
|
|
364
|
-
opacity: 0.
|
|
449
|
+
opacity: 0.4,
|
|
365
450
|
cursor: "default"
|
|
366
451
|
},
|
|
367
452
|
select: {
|
|
@@ -369,14 +454,16 @@ window.__ModuleLoader__.load({
|
|
|
369
454
|
// theme (dark list on dark pages) instead of the OS default
|
|
370
455
|
// white; option/optgroup styles above reinforce it.
|
|
371
456
|
colorScheme: "light dark",
|
|
372
|
-
background: "var(--dsw-alias-bg-layer-
|
|
373
|
-
border: "1px solid var(--dsw-alias-
|
|
374
|
-
borderRadius:
|
|
375
|
-
color: "var(--dsw-alias-label-
|
|
457
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.1))",
|
|
458
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
459
|
+
borderRadius: 7,
|
|
460
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
376
461
|
font: "inherit",
|
|
377
462
|
fontSize: 12,
|
|
378
|
-
lineHeight: "
|
|
379
|
-
|
|
463
|
+
lineHeight: "24px",
|
|
464
|
+
height: 26,
|
|
465
|
+
padding: "0 6px",
|
|
466
|
+
boxSizing: "border-box",
|
|
380
467
|
maxWidth: 220,
|
|
381
468
|
cursor: "pointer",
|
|
382
469
|
flex: "1",
|
|
@@ -384,14 +471,16 @@ window.__ModuleLoader__.load({
|
|
|
384
471
|
outline: "none"
|
|
385
472
|
},
|
|
386
473
|
input: {
|
|
387
|
-
background: "
|
|
388
|
-
border: "1px solid var(--dsw-alias-
|
|
389
|
-
borderRadius:
|
|
474
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.1))",
|
|
475
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
476
|
+
borderRadius: 7,
|
|
390
477
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
391
478
|
font: "inherit",
|
|
392
479
|
fontSize: 12,
|
|
393
|
-
lineHeight: "
|
|
394
|
-
|
|
480
|
+
lineHeight: "24px",
|
|
481
|
+
height: 26,
|
|
482
|
+
padding: "0 8px",
|
|
483
|
+
boxSizing: "border-box",
|
|
395
484
|
flex: "1",
|
|
396
485
|
minWidth: 0,
|
|
397
486
|
outline: "none"
|
|
@@ -400,47 +489,123 @@ window.__ModuleLoader__.load({
|
|
|
400
489
|
// silently strips every line feed, so a drafted subject+body would lose
|
|
401
490
|
// its body before the request was ever sent.
|
|
402
491
|
textarea: {
|
|
403
|
-
background: "
|
|
404
|
-
border: "1px solid var(--dsw-alias-
|
|
405
|
-
borderRadius:
|
|
492
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.1))",
|
|
493
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
494
|
+
borderRadius: 7,
|
|
406
495
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
407
496
|
font: "inherit",
|
|
408
497
|
fontSize: 12,
|
|
409
|
-
lineHeight: "
|
|
498
|
+
lineHeight: "17px",
|
|
410
499
|
padding: "4px 8px",
|
|
500
|
+
minHeight: 46,
|
|
411
501
|
flex: "1",
|
|
412
502
|
minWidth: 0,
|
|
503
|
+
boxSizing: "border-box",
|
|
413
504
|
outline: "none",
|
|
414
505
|
resize: "vertical",
|
|
415
506
|
overflowY: "auto"
|
|
416
507
|
},
|
|
417
|
-
|
|
508
|
+
// ── list sections (changes / recent commits) ─────────────────────
|
|
509
|
+
// A section is a card: a full-width header toggle (chevron + label +
|
|
510
|
+
// count) and its rows. Collapsing hides the rows outright — the old
|
|
511
|
+
// header doubled as "show more" for a preview, so its chevron pointed
|
|
512
|
+
// the wrong way for a list that was already on screen.
|
|
513
|
+
section: {
|
|
514
|
+
marginTop: 8,
|
|
515
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.22))",
|
|
516
|
+
borderRadius: 8,
|
|
517
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(127,127,127,0.06))",
|
|
518
|
+
overflow: "hidden"
|
|
519
|
+
},
|
|
520
|
+
sectionHeader: {
|
|
521
|
+
display: "flex",
|
|
522
|
+
alignItems: "center",
|
|
523
|
+
gap: 6,
|
|
524
|
+
width: "100%",
|
|
525
|
+
padding: "6px 8px",
|
|
526
|
+
background: "transparent",
|
|
527
|
+
border: "none",
|
|
528
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
529
|
+
font: "inherit",
|
|
418
530
|
fontSize: 12,
|
|
419
531
|
fontWeight: 600,
|
|
420
|
-
|
|
421
|
-
|
|
532
|
+
lineHeight: "18px",
|
|
533
|
+
boxSizing: "border-box",
|
|
534
|
+
cursor: "pointer",
|
|
535
|
+
textAlign: "left"
|
|
536
|
+
},
|
|
537
|
+
sectionChevron: {
|
|
538
|
+
flex: "none",
|
|
539
|
+
width: 10,
|
|
540
|
+
fontSize: 10,
|
|
541
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
542
|
+
},
|
|
543
|
+
sectionLabel: {
|
|
544
|
+
flex: "1",
|
|
545
|
+
minWidth: 0,
|
|
546
|
+
overflow: "hidden",
|
|
547
|
+
textOverflow: "ellipsis",
|
|
548
|
+
whiteSpace: "nowrap"
|
|
549
|
+
},
|
|
550
|
+
sectionCount: {
|
|
551
|
+
flex: "none",
|
|
552
|
+
padding: "0 6px",
|
|
553
|
+
borderRadius: 999,
|
|
554
|
+
background: "color-mix(in srgb, var(--dsw-alias-label-primary, #e5e7eb) 10%, transparent)",
|
|
555
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
556
|
+
fontSize: 11,
|
|
557
|
+
fontWeight: 500,
|
|
558
|
+
lineHeight: "16px"
|
|
559
|
+
},
|
|
560
|
+
sectionBody: {
|
|
561
|
+
padding: "0 4px 4px"
|
|
562
|
+
},
|
|
563
|
+
sectionEmpty: {
|
|
564
|
+
padding: "2px 6px 6px",
|
|
565
|
+
fontSize: 12,
|
|
566
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
567
|
+
},
|
|
568
|
+
sectionMore: {
|
|
569
|
+
display: "block",
|
|
570
|
+
width: "100%",
|
|
571
|
+
padding: "2px 0 4px",
|
|
572
|
+
background: "transparent",
|
|
573
|
+
border: "none",
|
|
574
|
+
color: "var(--dsw-alias-link, #4f8cff)",
|
|
575
|
+
font: "inherit",
|
|
576
|
+
fontSize: 11,
|
|
422
577
|
cursor: "pointer",
|
|
423
|
-
|
|
578
|
+
textAlign: "center"
|
|
424
579
|
},
|
|
425
580
|
changeRow: {
|
|
426
581
|
display: "flex",
|
|
427
582
|
alignItems: "center",
|
|
428
583
|
gap: 8,
|
|
429
584
|
fontSize: 12,
|
|
430
|
-
lineHeight: "
|
|
431
|
-
|
|
432
|
-
padding: "1px 6px",
|
|
433
|
-
margin: "0 -6px",
|
|
585
|
+
lineHeight: "18px",
|
|
586
|
+
padding: "3px 6px",
|
|
434
587
|
borderRadius: 6,
|
|
435
588
|
minWidth: 0,
|
|
436
589
|
cursor: "pointer"
|
|
437
590
|
},
|
|
438
591
|
changePath: {
|
|
592
|
+
flex: "1",
|
|
593
|
+
minWidth: 0,
|
|
439
594
|
overflow: "hidden",
|
|
440
595
|
textOverflow: "ellipsis",
|
|
441
596
|
whiteSpace: "nowrap",
|
|
442
|
-
|
|
443
|
-
|
|
597
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
598
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)"
|
|
599
|
+
},
|
|
600
|
+
// Per-status chip; `color-mix(currentColor)` gives every status the same
|
|
601
|
+
// tint shape from whichever state colour it carries.
|
|
602
|
+
changeTag: {
|
|
603
|
+
flex: "none",
|
|
604
|
+
padding: "0 6px",
|
|
605
|
+
borderRadius: 4,
|
|
606
|
+
fontSize: 11,
|
|
607
|
+
lineHeight: "16px",
|
|
608
|
+
background: "color-mix(in srgb, currentColor 15%, transparent)"
|
|
444
609
|
},
|
|
445
610
|
// A change row is the diff viewer's navigation: it has to read as a
|
|
446
611
|
// control, and to show which file the right-hand pane is showing.
|
|
@@ -449,14 +614,12 @@ window.__ModuleLoader__.load({
|
|
|
449
614
|
alignItems: "center",
|
|
450
615
|
gap: 8,
|
|
451
616
|
fontSize: 12,
|
|
452
|
-
lineHeight: "
|
|
453
|
-
|
|
454
|
-
padding: "1px 6px",
|
|
455
|
-
margin: "0 -6px",
|
|
617
|
+
lineHeight: "18px",
|
|
618
|
+
padding: "3px 6px",
|
|
456
619
|
borderRadius: 6,
|
|
457
620
|
minWidth: 0,
|
|
458
621
|
cursor: "pointer",
|
|
459
|
-
background: "var(--dsw-alias-
|
|
622
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-business-primary, #4f8cff) 15%, transparent)"
|
|
460
623
|
},
|
|
461
624
|
// ── two-pane (changes + diff) layout ────────────────────────────
|
|
462
625
|
// `bodySplit` replaces `body` while a file is selected: the left pane
|
|
@@ -528,9 +691,9 @@ window.__ModuleLoader__.load({
|
|
|
528
691
|
lineHeight: "18px",
|
|
529
692
|
padding: "0 8px",
|
|
530
693
|
borderRadius: 999,
|
|
531
|
-
border: "1px solid var(--dsw-alias-
|
|
694
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.25))",
|
|
532
695
|
background: "transparent",
|
|
533
|
-
color: "var(--dsw-alias-label-
|
|
696
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
534
697
|
font: "inherit",
|
|
535
698
|
fontSize: 11,
|
|
536
699
|
cursor: "pointer"
|
|
@@ -541,7 +704,7 @@ window.__ModuleLoader__.load({
|
|
|
541
704
|
padding: "0 8px",
|
|
542
705
|
borderRadius: 999,
|
|
543
706
|
border: "1px solid transparent",
|
|
544
|
-
background: "var(--dsw-alias-
|
|
707
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-business-primary, #4f8cff) 16%, transparent)",
|
|
545
708
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
546
709
|
font: "inherit",
|
|
547
710
|
fontSize: 11,
|
|
@@ -571,7 +734,7 @@ window.__ModuleLoader__.load({
|
|
|
571
734
|
width: 34,
|
|
572
735
|
textAlign: "right",
|
|
573
736
|
paddingRight: 6,
|
|
574
|
-
color: "var(--dsw-alias-label-
|
|
737
|
+
color: "var(--dsw-alias-label-tertiary, #6b7280)",
|
|
575
738
|
userSelect: "none",
|
|
576
739
|
WebkitUserSelect: "none"
|
|
577
740
|
},
|
|
@@ -595,7 +758,7 @@ window.__ModuleLoader__.load({
|
|
|
595
758
|
color: "var(--dsw-alias-state-business-primary, #4f8cff)"
|
|
596
759
|
},
|
|
597
760
|
diffMetaRow: {
|
|
598
|
-
color: "var(--dsw-alias-label-
|
|
761
|
+
color: "var(--dsw-alias-label-tertiary, #6b7280)"
|
|
599
762
|
},
|
|
600
763
|
diffNotice: {
|
|
601
764
|
margin: "6px 10px",
|
|
@@ -603,7 +766,7 @@ window.__ModuleLoader__.load({
|
|
|
603
766
|
borderRadius: 8,
|
|
604
767
|
fontSize: 12,
|
|
605
768
|
lineHeight: "18px",
|
|
606
|
-
background: "var(--dsw-alias-
|
|
769
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.12))",
|
|
607
770
|
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
608
771
|
},
|
|
609
772
|
statusTag: {
|
|
@@ -612,22 +775,32 @@ window.__ModuleLoader__.load({
|
|
|
612
775
|
lineHeight: "16px",
|
|
613
776
|
padding: "0 6px",
|
|
614
777
|
borderRadius: 4,
|
|
615
|
-
background: "var(--dsw-alias-
|
|
778
|
+
background: "color-mix(in srgb, var(--dsw-alias-label-primary, #e5e7eb) 10%, transparent)",
|
|
779
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
616
780
|
},
|
|
617
781
|
logRow: {
|
|
618
782
|
display: "flex",
|
|
619
783
|
alignItems: "center",
|
|
620
784
|
gap: 8,
|
|
621
785
|
fontSize: 12,
|
|
622
|
-
lineHeight: "
|
|
623
|
-
|
|
624
|
-
|
|
786
|
+
lineHeight: "18px",
|
|
787
|
+
padding: "3px 6px",
|
|
788
|
+
borderRadius: 6,
|
|
625
789
|
minWidth: 0
|
|
626
790
|
},
|
|
627
791
|
logSha: {
|
|
628
792
|
flex: "none",
|
|
629
|
-
|
|
630
|
-
|
|
793
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
794
|
+
fontSize: 11,
|
|
795
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
796
|
+
},
|
|
797
|
+
logSubject: {
|
|
798
|
+
flex: "1",
|
|
799
|
+
minWidth: 0,
|
|
800
|
+
overflow: "hidden",
|
|
801
|
+
textOverflow: "ellipsis",
|
|
802
|
+
whiteSpace: "nowrap",
|
|
803
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)"
|
|
631
804
|
},
|
|
632
805
|
output: {
|
|
633
806
|
// Sits at the top of the body, so the breathing room belongs below it.
|
|
@@ -667,8 +840,8 @@ window.__ModuleLoader__.load({
|
|
|
667
840
|
outputDetail: {
|
|
668
841
|
marginTop: 6,
|
|
669
842
|
paddingTop: 6,
|
|
670
|
-
borderTop: "1px solid
|
|
671
|
-
fontFamily: "monospace",
|
|
843
|
+
borderTop: "1px solid color-mix(in srgb, currentColor 30%, transparent)",
|
|
844
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
672
845
|
fontSize: 11,
|
|
673
846
|
lineHeight: "16px",
|
|
674
847
|
wordBreak: "break-word",
|
|
@@ -677,11 +850,11 @@ window.__ModuleLoader__.load({
|
|
|
677
850
|
whiteSpace: "pre-wrap"
|
|
678
851
|
},
|
|
679
852
|
outputOk: {
|
|
680
|
-
background: "var(--dsw-alias-state-success-
|
|
853
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-success-primary, #34c759) 14%, transparent)",
|
|
681
854
|
color: "var(--dsw-alias-state-success-primary, #34c759)"
|
|
682
855
|
},
|
|
683
856
|
outputError: {
|
|
684
|
-
background: "var(--dsw-alias-state-error-
|
|
857
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-error-primary, #ef4444) 14%, transparent)",
|
|
685
858
|
color: "var(--dsw-alias-state-error-primary, #ef4444)"
|
|
686
859
|
},
|
|
687
860
|
dockWrap: {
|
|
@@ -691,7 +864,7 @@ window.__ModuleLoader__.load({
|
|
|
691
864
|
maxWidth: "100%",
|
|
692
865
|
fontSize: 12,
|
|
693
866
|
lineHeight: "20px",
|
|
694
|
-
color: "var(--dsw-alias-label-
|
|
867
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
695
868
|
whiteSpace: "nowrap",
|
|
696
869
|
overflow: "hidden",
|
|
697
870
|
textOverflow: "ellipsis",
|
|
@@ -824,6 +997,84 @@ window.__ModuleLoader__.load({
|
|
|
824
997
|
}, children);
|
|
825
998
|
}
|
|
826
999
|
|
|
1000
|
+
/** Rows a collapsed-by-default list shows before its "show all" footer. */
|
|
1001
|
+
var CHANGES_PREVIEW = 8;
|
|
1002
|
+
/** Same, for the recent-commit list (shorter rows, less to say). */
|
|
1003
|
+
var LOG_PREVIEW = 5;
|
|
1004
|
+
|
|
1005
|
+
/** The state colour one porcelain status carries, in theme tokens. */
|
|
1006
|
+
function changeTagStyle(status) {
|
|
1007
|
+
var color = status === "added" || status === "untracked"
|
|
1008
|
+
? "var(--dsw-alias-state-success-primary, #34c759)"
|
|
1009
|
+
: status === "deleted" || status === "conflict"
|
|
1010
|
+
? "var(--dsw-alias-state-error-primary, #ef4444)"
|
|
1011
|
+
: status === "renamed" || status === "copied"
|
|
1012
|
+
// `state-business-primary` is the real accent (deepseek blue);
|
|
1013
|
+
// `brand-primary` is the inverted contrast colour and would make
|
|
1014
|
+
// this chip white-on-white in the dark theme.
|
|
1015
|
+
? "var(--dsw-alias-state-business-primary, #4f8cff)"
|
|
1016
|
+
: status === "modified" || status === "changed"
|
|
1017
|
+
? "var(--dsw-alias-state-warn-primary, #f0a020)"
|
|
1018
|
+
: "var(--dsw-alias-label-secondary, #c8ccd2)";
|
|
1019
|
+
// `changeTag`'s background is `color-mix(currentColor…)`, so the tint
|
|
1020
|
+
// follows whichever colour the status carries.
|
|
1021
|
+
return Object.assign({}, S.changeTag, { color: color });
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* One collapsible list section: a full-width header toggle (chevron +
|
|
1026
|
+
* label + count) and, while open, its rows plus a footer that expands the
|
|
1027
|
+
* preview. Two separate states on purpose — the header collapses the
|
|
1028
|
+
* section, the footer widens it — because one flag doing both made the
|
|
1029
|
+
* chevron point the wrong way for a list that was already on screen.
|
|
1030
|
+
*
|
|
1031
|
+
* @param spec - `{ hook, label, count, open, all, cap, empty, rows, onToggle, onMore }`.
|
|
1032
|
+
* @param t - the locale translator.
|
|
1033
|
+
* @returns the section element.
|
|
1034
|
+
*/
|
|
1035
|
+
function sectionView(spec, t) {
|
|
1036
|
+
var children = [h("button", {
|
|
1037
|
+
key: "header",
|
|
1038
|
+
type: "button",
|
|
1039
|
+
"data-dsh-git": spec.hook + "-header",
|
|
1040
|
+
style: S.sectionHeader,
|
|
1041
|
+
"aria-expanded": spec.open ? "true" : "false",
|
|
1042
|
+
onClick: spec.onToggle
|
|
1043
|
+
}, [
|
|
1044
|
+
h("span", { key: "chevron", style: S.sectionChevron }, spec.open ? "▾" : "▸"),
|
|
1045
|
+
h("span", { key: "label", style: S.sectionLabel }, spec.label),
|
|
1046
|
+
h("span", { key: "count", style: S.sectionCount }, String(spec.count))
|
|
1047
|
+
])];
|
|
1048
|
+
if (spec.open) {
|
|
1049
|
+
var previewed = spec.all || spec.count <= spec.cap;
|
|
1050
|
+
children.push(h("div", {
|
|
1051
|
+
key: "body",
|
|
1052
|
+
"data-dsh-git": spec.hook + "-body",
|
|
1053
|
+
style: S.sectionBody
|
|
1054
|
+
}, spec.count === 0
|
|
1055
|
+
? h("div", { key: "empty", style: S.sectionEmpty }, spec.empty)
|
|
1056
|
+
: (previewed ? spec.rows : spec.rows.slice(0, spec.cap))));
|
|
1057
|
+
if (!previewed) {
|
|
1058
|
+
children.push(h("button", {
|
|
1059
|
+
key: "more",
|
|
1060
|
+
type: "button",
|
|
1061
|
+
"data-dsh-git": spec.hook + "-more",
|
|
1062
|
+
style: S.sectionMore,
|
|
1063
|
+
onClick: spec.onMore
|
|
1064
|
+
}, t("section.more", { count: spec.count })));
|
|
1065
|
+
} else if (spec.all && spec.count > spec.cap) {
|
|
1066
|
+
children.push(h("button", {
|
|
1067
|
+
key: "more",
|
|
1068
|
+
type: "button",
|
|
1069
|
+
"data-dsh-git": spec.hook + "-more",
|
|
1070
|
+
style: S.sectionMore,
|
|
1071
|
+
onClick: spec.onMore
|
|
1072
|
+
}, t("section.less")));
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
return h("div", { key: spec.hook, "data-dsh-git": spec.hook, style: S.section }, children);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
827
1078
|
/** Call one /dsh-git-rpc endpoint. */
|
|
828
1079
|
function rpc(ctx, endpoint, args) {
|
|
829
1080
|
return ctx.connection.rpc.call("/dsh-git-rpc", endpoint, { args: args || {} }).then(sanitizeResult);
|
|
@@ -881,6 +1132,7 @@ window.__ModuleLoader__.load({
|
|
|
881
1132
|
commits: [],
|
|
882
1133
|
error: null,
|
|
883
1134
|
busy: null,
|
|
1135
|
+
refreshing: false,
|
|
884
1136
|
lastResult: null,
|
|
885
1137
|
panelOpen: false
|
|
886
1138
|
};
|
|
@@ -942,7 +1194,19 @@ window.__ModuleLoader__.load({
|
|
|
942
1194
|
|
|
943
1195
|
function doRefresh(cwd) {
|
|
944
1196
|
var mySeq = ++seq;
|
|
945
|
-
|
|
1197
|
+
// Re-reading the SAME workspace keeps what is already on screen.
|
|
1198
|
+
// Flipping the body to "loading" for a few hundred milliseconds
|
|
1199
|
+
// collapsed the whole workbench and snapped it back — that is the
|
|
1200
|
+
// jump you saw after clicking ↻ or any action button. Only a first
|
|
1201
|
+
// load (or a workspace switch) has nothing to keep.
|
|
1202
|
+
var keep = cwd !== null && cwd === state.cwd && state.phase === "ready";
|
|
1203
|
+
emit(Object.assign({}, state, {
|
|
1204
|
+
sessionId: sessionId,
|
|
1205
|
+
cwd: cwd,
|
|
1206
|
+
phase: keep ? state.phase : (cwd ? "loading" : "idle"),
|
|
1207
|
+
refreshing: keep,
|
|
1208
|
+
error: keep ? state.error : null
|
|
1209
|
+
}));
|
|
946
1210
|
if (!cwd) return Promise.resolve();
|
|
947
1211
|
return Promise.all([
|
|
948
1212
|
verbs.status(cwd),
|
|
@@ -1052,7 +1316,7 @@ window.__ModuleLoader__.load({
|
|
|
1052
1316
|
};
|
|
1053
1317
|
var OPTGROUP_STYLE = {
|
|
1054
1318
|
background: "var(--dsw-alias-bg-base, #1e1e1e)",
|
|
1055
|
-
color: "var(--dsw-alias-label-
|
|
1319
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
1056
1320
|
fontWeight: 600
|
|
1057
1321
|
};
|
|
1058
1322
|
|
|
@@ -1203,6 +1467,32 @@ window.__ModuleLoader__.load({
|
|
|
1203
1467
|
var PANEL_MARGIN = 24;
|
|
1204
1468
|
/** Grab width of the panel's right-edge resize handle. */
|
|
1205
1469
|
var PANEL_RESIZE_GRIP = 6;
|
|
1470
|
+
/**
|
|
1471
|
+
* Height the panel takes while the diff pane is open: a fixed height, not a
|
|
1472
|
+
* cap. With a cap the panel's height followed its content, so the moment the
|
|
1473
|
+
* diff arrived the pane grew and — anchored by `bottom` — the whole panel
|
|
1474
|
+
* jumped (the flash you saw when opening a diff). The `min()` keeps the panel
|
|
1475
|
+
* on screen in a short window (168px is the panel's bottom offset).
|
|
1476
|
+
*/
|
|
1477
|
+
var DIFF_PANEL_HEIGHT = "min(72vh, calc(100vh - 184px))";
|
|
1478
|
+
|
|
1479
|
+
/**
|
|
1480
|
+
* The panel's box in either mode: the compact single column, or workbench +
|
|
1481
|
+
* diff with a height that cannot move once the pane is open.
|
|
1482
|
+
* @param selected - the change the diff pane shows, or null.
|
|
1483
|
+
* @param diffWidth - width of the diff pane.
|
|
1484
|
+
* @returns the panel's inline style.
|
|
1485
|
+
*/
|
|
1486
|
+
function panelBoxStyle(selected, diffWidth) {
|
|
1487
|
+
var box = Object.assign({}, S.panel, {
|
|
1488
|
+
width: selected === null ? S.panel.width : DIFF_LEFT_PANE_WIDTH + PANEL_BORDER_WIDTH + diffWidth
|
|
1489
|
+
});
|
|
1490
|
+
if (selected !== null) {
|
|
1491
|
+
box.height = DIFF_PANEL_HEIGHT;
|
|
1492
|
+
box.maxHeight = DIFF_PANEL_HEIGHT;
|
|
1493
|
+
}
|
|
1494
|
+
return box;
|
|
1495
|
+
}
|
|
1206
1496
|
|
|
1207
1497
|
/** The last path segment, for chip-sized text. */
|
|
1208
1498
|
function baseName(file) {
|
|
@@ -1553,12 +1843,22 @@ window.__ModuleLoader__.load({
|
|
|
1553
1843
|
var generateModeRef = React.useState("staged");
|
|
1554
1844
|
var generateMode = generateModeRef[0];
|
|
1555
1845
|
var setGenerateMode = generateModeRef[1];
|
|
1556
|
-
|
|
1846
|
+
// Sections start OPEN: a Git panel that hides the user's own changes
|
|
1847
|
+
// behind a chevron is a panel that looks empty. Collapsing is the
|
|
1848
|
+
// explicit choice, and widening a long list past its preview is a
|
|
1849
|
+
// separate one (`…All`), so the chevron always tells the truth.
|
|
1850
|
+
var changesOpenRef = React.useState(true);
|
|
1557
1851
|
var changesOpen = changesOpenRef[0];
|
|
1558
1852
|
var setChangesOpen = changesOpenRef[1];
|
|
1559
|
-
var
|
|
1853
|
+
var changesAllRef = React.useState(false);
|
|
1854
|
+
var changesAll = changesAllRef[0];
|
|
1855
|
+
var setChangesAll = changesAllRef[1];
|
|
1856
|
+
var logOpenRef = React.useState(true);
|
|
1560
1857
|
var logOpen = logOpenRef[0];
|
|
1561
1858
|
var setLogOpen = logOpenRef[1];
|
|
1859
|
+
var logAllRef = React.useState(false);
|
|
1860
|
+
var logAll = logAllRef[0];
|
|
1861
|
+
var setLogAll = logAllRef[1];
|
|
1562
1862
|
// Whether the last operation's git output is expanded. A new result
|
|
1563
1863
|
// always starts collapsed: the summary line is the notification, the
|
|
1564
1864
|
// raw output is opt-in.
|
|
@@ -1820,11 +2120,7 @@ window.__ModuleLoader__.load({
|
|
|
1820
2120
|
// while nothing is selected, and the two-pane width (workbench + diff)
|
|
1821
2121
|
// once a file is open. Dragging the panel's right edge is what resizes
|
|
1822
2122
|
// the diff, so the panel grows and shrinks with it.
|
|
1823
|
-
var
|
|
1824
|
-
var panelStyle = Object.assign({}, S.panel, {
|
|
1825
|
-
width: panelWidth,
|
|
1826
|
-
maxHeight: selected === null ? S.panel.maxHeight : "72vh"
|
|
1827
|
-
});
|
|
2123
|
+
var panelStyle = panelBoxStyle(selected, diffWidth);
|
|
1828
2124
|
if (dragPos) {
|
|
1829
2125
|
panelStyle = Object.assign(panelStyle, {
|
|
1830
2126
|
left: dragPos.left,
|
|
@@ -1858,20 +2154,24 @@ window.__ModuleLoader__.load({
|
|
|
1858
2154
|
"data-dsh-git": "panel-drag"
|
|
1859
2155
|
}, [
|
|
1860
2156
|
h("span", { key: "title", style: S.title }, "⎇ " + t("panel.title")),
|
|
1861
|
-
h("span", { key: "cwd", style: S.
|
|
2157
|
+
h("span", { key: "cwd", style: S.cwdPath, title: cwd }, shortText(cwd, 80)),
|
|
1862
2158
|
h("button", {
|
|
1863
2159
|
key: "refresh",
|
|
1864
2160
|
type: "button",
|
|
1865
|
-
|
|
1866
|
-
|
|
2161
|
+
// A re-read keeps the whole workbench on screen and reports itself
|
|
2162
|
+
// here instead of collapsing the body to a "loading" line and
|
|
2163
|
+
// snapping back — that flash was the jump.
|
|
2164
|
+
style: Object.assign({}, S.iconButton, busy !== null || state.refreshing ? S.buttonDisabled : null),
|
|
2165
|
+
disabled: busy !== null || state.refreshing === true,
|
|
1867
2166
|
onClick: function () { store.refresh(state.cwd); },
|
|
1868
2167
|
"aria-label": t("refresh.aria"),
|
|
1869
|
-
|
|
1870
|
-
|
|
2168
|
+
"aria-busy": state.refreshing === true ? "true" : "false",
|
|
2169
|
+
title: state.refreshing === true ? t("refresh.busy") : t("refresh.aria")
|
|
2170
|
+
}, state.refreshing === true ? "⋯" : "↻"),
|
|
1871
2171
|
h("button", {
|
|
1872
2172
|
key: "collapse",
|
|
1873
2173
|
type: "button",
|
|
1874
|
-
style: S.
|
|
2174
|
+
style: S.iconButton,
|
|
1875
2175
|
onClick: function () { store.setPanelOpen(false); },
|
|
1876
2176
|
"aria-label": t("panel.collapse"),
|
|
1877
2177
|
title: t("panel.collapse")
|
|
@@ -1896,15 +2196,21 @@ window.__ModuleLoader__.load({
|
|
|
1896
2196
|
} else if (!state.repo) {
|
|
1897
2197
|
bodyChildren.push(h("div", { key: "norepo", style: S.meta }, t("notRepo")));
|
|
1898
2198
|
} else {
|
|
1899
|
-
// status line
|
|
2199
|
+
// status line — the branch itself lives in the select right below,
|
|
2200
|
+
// so this row carries only what the select cannot say: pending
|
|
2201
|
+
// changes and how the branch sits against its upstream.
|
|
1900
2202
|
var statusLine = [];
|
|
1901
2203
|
var branchText = state.branch;
|
|
1902
2204
|
if (!branchText && state.detached) {
|
|
1903
2205
|
branchText = t("detached") + (state.oid ? " " + state.oid.slice(0, 7) : "");
|
|
1904
2206
|
}
|
|
1905
|
-
|
|
2207
|
+
if (state.detached) {
|
|
2208
|
+
statusLine.push(h("span", { key: "chip", style: S.chip, title: branchText }, branchText));
|
|
2209
|
+
}
|
|
1906
2210
|
if (state.dirty > 0) {
|
|
1907
|
-
statusLine.push(h("span", { key: "dirty", style: S.dirty, title: t("dirty", { count: state.dirty }) }, "● " + state.dirty));
|
|
2211
|
+
statusLine.push(h("span", { key: "dirty", style: S.dirty, title: t("dirty", { count: state.dirty }) }, "● " + t("dirty", { count: state.dirty })));
|
|
2212
|
+
} else {
|
|
2213
|
+
statusLine.push(h("span", { key: "clean", style: S.meta }, "✓ " + t("changes.none")));
|
|
1908
2214
|
}
|
|
1909
2215
|
if (state.ahead > 0 || state.behind > 0) {
|
|
1910
2216
|
statusLine.push(h("span", { key: "ab", style: S.meta }, "↑" + state.ahead + " ↓" + state.behind));
|
|
@@ -2024,94 +2330,96 @@ window.__ModuleLoader__.load({
|
|
|
2024
2330
|
]));
|
|
2025
2331
|
}
|
|
2026
2332
|
|
|
2027
|
-
// network
|
|
2333
|
+
// network actions — three equal columns. Auto-width labels used to
|
|
2334
|
+
// give each button a different width for the same job, which is what
|
|
2335
|
+
// made this row read as a pile rather than a toolbar.
|
|
2028
2336
|
bodyChildren.push(h("div", { key: "net", style: S.row }, [
|
|
2029
2337
|
h("button", {
|
|
2030
2338
|
key: "fetch",
|
|
2031
2339
|
type: "button",
|
|
2032
|
-
style: Object.assign({}, S.button, busy !== null ? S.buttonDisabled : null),
|
|
2340
|
+
style: Object.assign({}, S.button, S.grow, busy !== null ? S.buttonDisabled : null),
|
|
2033
2341
|
disabled: busy !== null,
|
|
2034
2342
|
onClick: function () { store.act("fetch", function () { return store.verbs.fetch(state.cwd); }); }
|
|
2035
2343
|
}, busy === "fetch" ? t("busy.fetch") : t("action.fetch")),
|
|
2036
2344
|
h("button", {
|
|
2037
2345
|
key: "pull",
|
|
2038
2346
|
type: "button",
|
|
2039
|
-
style: Object.assign({}, S.button, busy !== null ? S.buttonDisabled : null),
|
|
2347
|
+
style: Object.assign({}, S.button, S.grow, busy !== null ? S.buttonDisabled : null),
|
|
2040
2348
|
disabled: busy !== null,
|
|
2041
2349
|
onClick: function () { store.act("pull", function () { return store.verbs.pull(state.cwd); }); }
|
|
2042
2350
|
}, busy === "pull" ? t("busy.pull") : t("action.pull")),
|
|
2043
2351
|
h("button", {
|
|
2044
2352
|
key: "push",
|
|
2045
2353
|
type: "button",
|
|
2046
|
-
style: Object.assign({}, S.buttonPrimary, busy !== null ? S.buttonDisabled : null),
|
|
2354
|
+
style: Object.assign({}, S.buttonPrimary, S.grow, busy !== null ? S.buttonDisabled : null),
|
|
2047
2355
|
disabled: busy !== null,
|
|
2048
2356
|
onClick: function () { store.act("push", function () { return store.verbs.push(state.cwd); }); }
|
|
2049
2357
|
}, busy === "push" ? t("busy.push") : t("action.push"))
|
|
2050
2358
|
]));
|
|
2051
2359
|
|
|
2052
|
-
// commit
|
|
2053
|
-
//
|
|
2054
|
-
//
|
|
2055
|
-
// message row.
|
|
2360
|
+
// commit flow, one card: stage all → draft basis + draft → message →
|
|
2361
|
+
// commit. Grouping it keeps the 400px column readable and puts the
|
|
2362
|
+
// primary action (提交) in the same surface as the text it sends.
|
|
2056
2363
|
var noChanges = state.dirty === 0;
|
|
2057
|
-
bodyChildren.push(h("div", { key: "
|
|
2058
|
-
h("
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2364
|
+
bodyChildren.push(h("div", { key: "commitCard", style: S.card }, [
|
|
2365
|
+
h("div", { key: "tools", style: S.rowTight }, [
|
|
2366
|
+
h("button", {
|
|
2367
|
+
key: "stage",
|
|
2368
|
+
type: "button",
|
|
2369
|
+
style: Object.assign({}, S.button, S.grow, busy !== null || noChanges ? S.buttonDisabled : null),
|
|
2370
|
+
disabled: busy !== null || noChanges,
|
|
2371
|
+
title: noChanges ? t("changes.none") : t("action.stage"),
|
|
2372
|
+
onClick: function () { store.act("stage", function () { return store.verbs.stage(state.cwd); }); }
|
|
2373
|
+
}, busy === "stage" ? t("busy.stage") : t("action.stage")),
|
|
2374
|
+
h("select", {
|
|
2375
|
+
key: "mode",
|
|
2376
|
+
style: Object.assign({}, S.select, S.grow, { maxWidth: "none" }),
|
|
2377
|
+
value: generateMode,
|
|
2378
|
+
disabled: busy !== null,
|
|
2379
|
+
title: t("generate.mode.title"),
|
|
2380
|
+
"aria-label": t("generate.mode.title"),
|
|
2381
|
+
onChange: function (event) { setGenerateMode(event.target.value); }
|
|
2382
|
+
}, [
|
|
2383
|
+
h("option", { key: "staged", value: "staged", style: OPTION_STYLE }, t("generate.mode.staged")),
|
|
2384
|
+
h("option", { key: "unstaged", value: "unstaged", style: OPTION_STYLE }, t("generate.mode.unstaged")),
|
|
2385
|
+
h("option", { key: "all", value: "all", style: OPTION_STYLE }, t("generate.mode.all"))
|
|
2386
|
+
]),
|
|
2387
|
+
h("button", {
|
|
2388
|
+
key: "generate",
|
|
2389
|
+
type: "button",
|
|
2390
|
+
style: Object.assign({}, S.button, S.grow, busy !== null || noChanges ? S.buttonDisabled : null),
|
|
2391
|
+
disabled: busy !== null || noChanges,
|
|
2392
|
+
title: noChanges ? t("changes.none") : t("action.generate"),
|
|
2393
|
+
onClick: doGenerate
|
|
2394
|
+
}, busy === "generate" ? t("busy.generate") : "✨ " + t("action.generate"))
|
|
2078
2395
|
]),
|
|
2079
|
-
h("
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
placeholder: t("commit.placeholder"),
|
|
2096
|
-
disabled: busy !== null,
|
|
2097
|
-
onChange: function (event) { setMessage(event.target.value); },
|
|
2098
|
-
// Enter inserts a newline (a message may have a body); the
|
|
2099
|
-
// explicit commit chord is Ctrl/Cmd+Enter.
|
|
2100
|
-
onKeyDown: function (event) {
|
|
2101
|
-
if (event.key === "Enter" && (event.ctrlKey || event.metaKey) && message.trim() !== "" && busy === null) {
|
|
2102
|
-
event.preventDefault();
|
|
2103
|
-
doCommit();
|
|
2396
|
+
h("div", { key: "message", style: S.rowTight }, [
|
|
2397
|
+
h("textarea", {
|
|
2398
|
+
key: "msg",
|
|
2399
|
+
rows: 2,
|
|
2400
|
+
style: S.textarea,
|
|
2401
|
+
value: message,
|
|
2402
|
+
placeholder: t("commit.placeholder"),
|
|
2403
|
+
disabled: busy !== null,
|
|
2404
|
+
onChange: function (event) { setMessage(event.target.value); },
|
|
2405
|
+
// Enter inserts a newline (a message may have a body); the
|
|
2406
|
+
// explicit commit chord is Ctrl/Cmd+Enter.
|
|
2407
|
+
onKeyDown: function (event) {
|
|
2408
|
+
if (event.key === "Enter" && (event.ctrlKey || event.metaKey) && message.trim() !== "" && busy === null) {
|
|
2409
|
+
event.preventDefault();
|
|
2410
|
+
doCommit();
|
|
2411
|
+
}
|
|
2104
2412
|
}
|
|
2105
|
-
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2413
|
+
}),
|
|
2414
|
+
h("button", {
|
|
2415
|
+
key: "commit",
|
|
2416
|
+
type: "button",
|
|
2417
|
+
style: Object.assign({}, S.buttonPrimary, { alignSelf: "flex-end", padding: "0 14px" }, busy !== null || message.trim() === "" ? S.buttonDisabled : null),
|
|
2418
|
+
disabled: busy !== null || message.trim() === "",
|
|
2419
|
+
title: message.trim() === "" ? t("commit.empty") : undefined,
|
|
2420
|
+
onClick: doCommit
|
|
2421
|
+
}, busy === "commit" ? t("busy.commit") : t("action.commit"))
|
|
2422
|
+
])
|
|
2115
2423
|
]));
|
|
2116
2424
|
|
|
2117
2425
|
function doCommit() {
|
|
@@ -2163,79 +2471,67 @@ window.__ModuleLoader__.load({
|
|
|
2163
2471
|
});
|
|
2164
2472
|
}
|
|
2165
2473
|
|
|
2166
|
-
// changes (one row per file) —
|
|
2167
|
-
//
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
var
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
2189
|
-
if (event.preventDefault) event.preventDefault();
|
|
2190
|
-
selectChange(change);
|
|
2191
|
-
}
|
|
2474
|
+
// changes (one row per file) — the diff viewer's navigation:
|
|
2475
|
+
// clicking a row opens that file's diff on the right. The chip
|
|
2476
|
+
// trails the path so paths line up in one column and the eye can
|
|
2477
|
+
// scan them; the status only has to say which kind of change it is.
|
|
2478
|
+
var changesRows = state.changes.map(function (change, index) {
|
|
2479
|
+
var file = change.file !== undefined ? change.file : change.path;
|
|
2480
|
+
var origFile = change.origFile !== undefined ? change.origFile : null;
|
|
2481
|
+
var isActive = selected !== null && selected.file === file && selected.origFile === origFile;
|
|
2482
|
+
return h("div", {
|
|
2483
|
+
key: index,
|
|
2484
|
+
style: isActive ? S.changeRowActive : S.changeRow,
|
|
2485
|
+
role: "button",
|
|
2486
|
+
tabIndex: 0,
|
|
2487
|
+
title: change.path,
|
|
2488
|
+
"aria-label": t("diff.open") + " " + change.path,
|
|
2489
|
+
"data-dsh-git": "change-row",
|
|
2490
|
+
"data-active": isActive === true ? "true" : "false",
|
|
2491
|
+
onClick: function () { selectChange(change); },
|
|
2492
|
+
onKeyDown: function (event) {
|
|
2493
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
2494
|
+
if (event.preventDefault) event.preventDefault();
|
|
2495
|
+
selectChange(change);
|
|
2192
2496
|
}
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
}
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
style: S.button,
|
|
2232
|
-
onClick: function () { setLogOpen(!logOpen); }
|
|
2233
|
-
}, logOpen ? "▴" : "▾ " + (state.commits.length - logShown.length))
|
|
2234
|
-
]);
|
|
2235
|
-
}
|
|
2236
|
-
}
|
|
2237
|
-
bodyChildren.push(h("div", { key: "logTitle", style: S.sectionTitle, onClick: function () { setLogOpen(!logOpen); } }, (logOpen ? "▾ " : "▸ ") + t("log.title")));
|
|
2238
|
-
bodyChildren.push(h("div", { key: "logBody" }, logRows));
|
|
2497
|
+
}
|
|
2498
|
+
}, [
|
|
2499
|
+
h("span", { key: "path", style: S.changePath }, change.path),
|
|
2500
|
+
h("span", { key: "tag", style: changeTagStyle(change.status) }, t("status." + change.status))
|
|
2501
|
+
]);
|
|
2502
|
+
});
|
|
2503
|
+
bodyChildren.push(sectionView({
|
|
2504
|
+
hook: "changes",
|
|
2505
|
+
label: t("changes.title"),
|
|
2506
|
+
count: state.changes.length,
|
|
2507
|
+
open: changesOpen,
|
|
2508
|
+
all: changesAll,
|
|
2509
|
+
cap: CHANGES_PREVIEW,
|
|
2510
|
+
empty: "✓ " + t("changes.none"),
|
|
2511
|
+
rows: changesRows,
|
|
2512
|
+
onToggle: function () { setChangesOpen(!changesOpen); },
|
|
2513
|
+
onMore: function () { setChangesAll(!changesAll); }
|
|
2514
|
+
}, t));
|
|
2515
|
+
|
|
2516
|
+
// recent commits — same card, one row per commit
|
|
2517
|
+
var logRows = state.commits.map(function (commit, index) {
|
|
2518
|
+
return h("div", { key: index, style: S.logRow, title: commit.subject }, [
|
|
2519
|
+
h("span", { key: "sha", style: S.logSha }, commit.sha),
|
|
2520
|
+
h("span", { key: "subj", style: S.logSubject }, commit.subject)
|
|
2521
|
+
]);
|
|
2522
|
+
});
|
|
2523
|
+
bodyChildren.push(sectionView({
|
|
2524
|
+
hook: "log",
|
|
2525
|
+
label: t("log.title"),
|
|
2526
|
+
count: state.commits.length,
|
|
2527
|
+
open: logOpen,
|
|
2528
|
+
all: logAll,
|
|
2529
|
+
cap: LOG_PREVIEW,
|
|
2530
|
+
empty: t("log.none"),
|
|
2531
|
+
rows: logRows,
|
|
2532
|
+
onToggle: function () { setLogOpen(!logOpen); },
|
|
2533
|
+
onMore: function () { setLogAll(!logAll); }
|
|
2534
|
+
}, t));
|
|
2239
2535
|
}
|
|
2240
2536
|
|
|
2241
2537
|
// Everything the open diff depends on, as one comparable string: a
|
|
@@ -2403,7 +2699,7 @@ window.__ModuleLoader__.load({
|
|
|
2403
2699
|
maxWidth: 220,
|
|
2404
2700
|
padding: "1px 10px",
|
|
2405
2701
|
borderRadius: 999,
|
|
2406
|
-
border: "1px solid var(--dsw-alias-
|
|
2702
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.25))",
|
|
2407
2703
|
background: "var(--dsw-alias-bg-layer-1, rgba(127,127,127,0.12))",
|
|
2408
2704
|
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
2409
2705
|
font: "inherit",
|
|
@@ -2472,7 +2768,11 @@ window.__ModuleLoader__.load({
|
|
|
2472
2768
|
GitDiffPane: GitDiffPane,
|
|
2473
2769
|
DIFF_ROW: DIFF_ROW,
|
|
2474
2770
|
stripAnsiEscapes: stripAnsiEscapes,
|
|
2475
|
-
outputView: outputView
|
|
2771
|
+
outputView: outputView,
|
|
2772
|
+
sectionView: sectionView,
|
|
2773
|
+
changeTagStyle: changeTagStyle,
|
|
2774
|
+
panelBoxStyle: panelBoxStyle,
|
|
2775
|
+
DIFF_PANEL_HEIGHT: DIFF_PANEL_HEIGHT
|
|
2476
2776
|
};
|
|
2477
2777
|
return module.exports;
|
|
2478
2778
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xia-sc/dsh-git",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Complete Git management for the DeepSeek Harness Web GUI: branch switch, new-branch-from-base, fetch, pull, stage-all, commit (with AI-drafted message), push, status, and a click-to-open diff viewer (staged/unstaged, resizable) — as a collapsible floating panel that follows the current session's workspace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|