@xia-sc/dsh-git 0.5.3 → 0.6.1
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 +34 -10
- package/README.md +22 -9
- package/lib/client.js +618 -254
- package/lib/index.js +63 -20
- package/package.json +6 -3
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 拒绝,请先提交或暂存",
|
|
@@ -75,10 +76,16 @@ window.__ModuleLoader__.load({
|
|
|
75
76
|
"generate.truncated": "模型还没写出提交信息就用完了 token 上限(思考模型会先花掉这份预算),再点一次通常即可",
|
|
76
77
|
"generate.cancelled": "生成已取消",
|
|
77
78
|
"generate.failed": "生成失败",
|
|
79
|
+
"generate.failedDetail": "生成失败:{message}",
|
|
80
|
+
"generate.failedRoute": "生成失败:{message}(模型路由 {provider} / {model})",
|
|
78
81
|
"commit.placeholder": "提交信息(可多行,Ctrl+Enter 提交)…",
|
|
79
82
|
"commit.empty": "请输入提交信息",
|
|
80
|
-
"changes.title": "
|
|
83
|
+
"changes.title": "变更",
|
|
81
84
|
"changes.none": "工作区干净",
|
|
85
|
+
// Section footer: the list previews its first N rows and this says how
|
|
86
|
+
// many more there are, instead of a bare "▾ 13".
|
|
87
|
+
"section.more": "显示全部 {count} 项",
|
|
88
|
+
"section.less": "只看前几项",
|
|
82
89
|
"diff.title": "差异",
|
|
83
90
|
"diff.open": "查看差异",
|
|
84
91
|
"diff.close": "关闭差异",
|
|
@@ -137,6 +144,7 @@ window.__ModuleLoader__.load({
|
|
|
137
144
|
"panel.title": "Git",
|
|
138
145
|
"panel.collapse": "Collapse",
|
|
139
146
|
"refresh.aria": "Refresh Git status",
|
|
147
|
+
"refresh.busy": "Refreshing…",
|
|
140
148
|
"branch.aria": "Current git branch",
|
|
141
149
|
"switch.aria": "Switch branch",
|
|
142
150
|
"switch.dirtyWarn": "{count} uncommitted file(s) (e.g. {paths}) may block the switch — commit or stash first",
|
|
@@ -174,10 +182,14 @@ window.__ModuleLoader__.load({
|
|
|
174
182
|
"generate.truncated": "The model hit its token cap before writing anything (a reasoning model spends that budget thinking first) — trying again usually works",
|
|
175
183
|
"generate.cancelled": "Draft cancelled",
|
|
176
184
|
"generate.failed": "Draft failed",
|
|
185
|
+
"generate.failedDetail": "Draft failed: {message}",
|
|
186
|
+
"generate.failedRoute": "Draft failed: {message} (route {provider} / {model})",
|
|
177
187
|
"commit.placeholder": "Commit message (multi-line allowed, Ctrl+Enter commits)…",
|
|
178
188
|
"commit.empty": "Enter a commit message",
|
|
179
|
-
"changes.title": "Changes
|
|
189
|
+
"changes.title": "Changes",
|
|
180
190
|
"changes.none": "Working tree clean",
|
|
191
|
+
"section.more": "Show all {count}",
|
|
192
|
+
"section.less": "Show fewer",
|
|
181
193
|
"diff.title": "Diff",
|
|
182
194
|
"diff.open": "View diff",
|
|
183
195
|
"diff.close": "Close diff",
|
|
@@ -243,7 +255,12 @@ window.__ModuleLoader__.load({
|
|
|
243
255
|
panel: {
|
|
244
256
|
position: "fixed",
|
|
245
257
|
// Sit above the composer card so the expanded panel never covers
|
|
246
|
-
// the input box
|
|
258
|
+
// the input box. 168px is a measurement of the composer stack
|
|
259
|
+
// (card + tool row + the dock band), not a published contract:
|
|
260
|
+
// ui-conversation keeps that geometry in its own module CSS
|
|
261
|
+
// (`--dsh-composer-stack-gap` etc.). If the composer grows or
|
|
262
|
+
// shrinks, re-measure here and in DIFF_PANEL_HEIGHT below — the
|
|
263
|
+
// panel is anchored by `bottom`, so both move together.
|
|
247
264
|
bottom: 168,
|
|
248
265
|
left: "50%",
|
|
249
266
|
transform: "translateX(-50%)",
|
|
@@ -269,8 +286,8 @@ window.__ModuleLoader__.load({
|
|
|
269
286
|
display: "flex",
|
|
270
287
|
alignItems: "center",
|
|
271
288
|
gap: 8,
|
|
272
|
-
padding: "8px
|
|
273
|
-
borderBottom: "1px solid var(--dsw-alias-border-
|
|
289
|
+
padding: "8px 10px",
|
|
290
|
+
borderBottom: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.22))",
|
|
274
291
|
flex: "none",
|
|
275
292
|
cursor: "move",
|
|
276
293
|
userSelect: "none",
|
|
@@ -284,11 +301,39 @@ window.__ModuleLoader__.load({
|
|
|
284
301
|
fontSize: 13,
|
|
285
302
|
fontWeight: 600,
|
|
286
303
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
304
|
+
flex: "none",
|
|
305
|
+
whiteSpace: "nowrap"
|
|
306
|
+
},
|
|
307
|
+
// The workspace path takes the header's slack: it is the one field whose
|
|
308
|
+
// truncation must never move the buttons beside it.
|
|
309
|
+
cwdPath: {
|
|
287
310
|
flex: "1",
|
|
288
311
|
minWidth: 0,
|
|
289
312
|
overflow: "hidden",
|
|
290
313
|
textOverflow: "ellipsis",
|
|
291
|
-
whiteSpace: "nowrap"
|
|
314
|
+
whiteSpace: "nowrap",
|
|
315
|
+
fontSize: 11,
|
|
316
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
317
|
+
textAlign: "right"
|
|
318
|
+
},
|
|
319
|
+
// Square ghost icon button: the panel's own chrome (refresh / collapse).
|
|
320
|
+
iconButton: {
|
|
321
|
+
flex: "none",
|
|
322
|
+
display: "inline-flex",
|
|
323
|
+
alignItems: "center",
|
|
324
|
+
justifyContent: "center",
|
|
325
|
+
width: 24,
|
|
326
|
+
height: 24,
|
|
327
|
+
padding: 0,
|
|
328
|
+
border: "1px solid transparent",
|
|
329
|
+
borderRadius: 6,
|
|
330
|
+
background: "transparent",
|
|
331
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
332
|
+
font: "inherit",
|
|
333
|
+
fontSize: 13,
|
|
334
|
+
lineHeight: "20px",
|
|
335
|
+
boxSizing: "border-box",
|
|
336
|
+
cursor: "pointer"
|
|
292
337
|
},
|
|
293
338
|
body: {
|
|
294
339
|
flex: "1",
|
|
@@ -299,9 +344,36 @@ window.__ModuleLoader__.load({
|
|
|
299
344
|
row: {
|
|
300
345
|
display: "flex",
|
|
301
346
|
alignItems: "center",
|
|
302
|
-
gap:
|
|
347
|
+
gap: 6,
|
|
303
348
|
margin: "6px 0"
|
|
304
349
|
},
|
|
350
|
+
// One action row inside a card: the gap is owned by the card, not the row.
|
|
351
|
+
rowTight: {
|
|
352
|
+
display: "flex",
|
|
353
|
+
alignItems: "center",
|
|
354
|
+
gap: 6,
|
|
355
|
+
minWidth: 0
|
|
356
|
+
},
|
|
357
|
+
// Equal-width action buttons: a row of auto-width labels was the messy
|
|
358
|
+
// part of the old layout — every group now shares the row evenly.
|
|
359
|
+
grow: {
|
|
360
|
+
flex: "1 1 0",
|
|
361
|
+
minWidth: 0,
|
|
362
|
+
padding: "0 6px",
|
|
363
|
+
textAlign: "center"
|
|
364
|
+
},
|
|
365
|
+
// Card grouping the whole commit flow (stage → draft → message → commit).
|
|
366
|
+
card: {
|
|
367
|
+
margin: "6px 0",
|
|
368
|
+
padding: 8,
|
|
369
|
+
display: "flex",
|
|
370
|
+
flexDirection: "column",
|
|
371
|
+
gap: 6,
|
|
372
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.22))",
|
|
373
|
+
borderRadius: 8,
|
|
374
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(127,127,127,0.06))",
|
|
375
|
+
minWidth: 0
|
|
376
|
+
},
|
|
305
377
|
warn: {
|
|
306
378
|
display: "flex",
|
|
307
379
|
alignItems: "center",
|
|
@@ -309,18 +381,22 @@ window.__ModuleLoader__.load({
|
|
|
309
381
|
margin: "6px 0",
|
|
310
382
|
padding: "6px 8px",
|
|
311
383
|
borderRadius: 8,
|
|
312
|
-
background: "var(--dsw-alias-state-
|
|
313
|
-
border: "1px solid var(--dsw-alias-state-
|
|
314
|
-
color: "var(--dsw-alias-state-
|
|
384
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f0a020) 14%, transparent)",
|
|
385
|
+
border: "1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f0a020) 40%, transparent)",
|
|
386
|
+
color: "var(--dsw-alias-state-warn-primary, #f0a020)",
|
|
315
387
|
fontSize: 12,
|
|
316
388
|
lineHeight: "16px"
|
|
317
389
|
},
|
|
390
|
+
// The branch chip — only for the detached-HEAD notice, so it carries the
|
|
391
|
+
// warning colour rather than the accent.
|
|
318
392
|
chip: {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
borderRadius: 999,
|
|
393
|
+
flex: "none",
|
|
394
|
+
maxWidth: "62%",
|
|
322
395
|
padding: "0 8px",
|
|
323
|
-
|
|
396
|
+
borderRadius: 6,
|
|
397
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-warn-primary, #f0a020) 16%, transparent)",
|
|
398
|
+
color: "var(--dsw-alias-state-warn-primary, #f0a020)",
|
|
399
|
+
fontWeight: 600,
|
|
324
400
|
fontSize: 12,
|
|
325
401
|
lineHeight: "20px",
|
|
326
402
|
overflow: "hidden",
|
|
@@ -328,40 +404,58 @@ window.__ModuleLoader__.load({
|
|
|
328
404
|
whiteSpace: "nowrap"
|
|
329
405
|
},
|
|
330
406
|
dirty: {
|
|
407
|
+
flex: "none",
|
|
331
408
|
color: "var(--dsw-alias-state-warn-primary, #f0a020)",
|
|
332
409
|
fontWeight: 600,
|
|
333
410
|
fontSize: 12
|
|
334
411
|
},
|
|
335
412
|
meta: {
|
|
336
|
-
color: "var(--dsw-alias-label-
|
|
337
|
-
fontSize:
|
|
413
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
414
|
+
fontSize: 11
|
|
338
415
|
},
|
|
339
416
|
button: {
|
|
340
|
-
background: "var(--dsw-alias-
|
|
417
|
+
background: "color-mix(in srgb, var(--dsw-alias-label-primary, #e5e7eb) 8%, transparent)",
|
|
341
418
|
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
342
|
-
borderRadius:
|
|
343
|
-
color: "var(--dsw-alias-label-
|
|
419
|
+
borderRadius: 7,
|
|
420
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
344
421
|
font: "inherit",
|
|
345
422
|
fontSize: 12,
|
|
346
|
-
lineHeight: "
|
|
423
|
+
lineHeight: "24px",
|
|
424
|
+
height: 26,
|
|
347
425
|
padding: "0 10px",
|
|
426
|
+
boxSizing: "border-box",
|
|
348
427
|
cursor: "pointer",
|
|
349
|
-
flex: "none"
|
|
428
|
+
flex: "none",
|
|
429
|
+
whiteSpace: "nowrap",
|
|
430
|
+
overflow: "hidden",
|
|
431
|
+
textOverflow: "ellipsis"
|
|
350
432
|
},
|
|
351
433
|
buttonPrimary: {
|
|
352
|
-
|
|
434
|
+
// The harness's own primary button: the label token IS the fill, with
|
|
435
|
+
// `label-primary-foreground` as the text on top. It reads near-black on
|
|
436
|
+
// light and near-white on dark (an inverted contrast button).
|
|
437
|
+
// `--dsw-alias-brand-primary` is that same contrast colour, NOT an
|
|
438
|
+
// accent — pairing it with `#fff` text made 推送 a white block with
|
|
439
|
+
// invisible text in the dark theme, and 提交 an empty grey box.
|
|
440
|
+
background: "var(--dsw-alias-button-primary-fill, var(--dsw-alias-label-primary, #e5e7eb))",
|
|
353
441
|
border: "1px solid transparent",
|
|
354
|
-
borderRadius:
|
|
355
|
-
color: "#
|
|
442
|
+
borderRadius: 7,
|
|
443
|
+
color: "var(--dsw-alias-label-primary-foreground, var(--dsw-alias-bg-base, #1e1e1e))",
|
|
356
444
|
font: "inherit",
|
|
357
445
|
fontSize: 12,
|
|
358
|
-
|
|
446
|
+
fontWeight: 600,
|
|
447
|
+
lineHeight: "24px",
|
|
448
|
+
height: 26,
|
|
359
449
|
padding: "0 10px",
|
|
450
|
+
boxSizing: "border-box",
|
|
360
451
|
cursor: "pointer",
|
|
361
|
-
flex: "none"
|
|
452
|
+
flex: "none",
|
|
453
|
+
whiteSpace: "nowrap",
|
|
454
|
+
overflow: "hidden",
|
|
455
|
+
textOverflow: "ellipsis"
|
|
362
456
|
},
|
|
363
457
|
buttonDisabled: {
|
|
364
|
-
opacity: 0.
|
|
458
|
+
opacity: 0.4,
|
|
365
459
|
cursor: "default"
|
|
366
460
|
},
|
|
367
461
|
select: {
|
|
@@ -369,14 +463,16 @@ window.__ModuleLoader__.load({
|
|
|
369
463
|
// theme (dark list on dark pages) instead of the OS default
|
|
370
464
|
// white; option/optgroup styles above reinforce it.
|
|
371
465
|
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-
|
|
466
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.1))",
|
|
467
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
468
|
+
borderRadius: 7,
|
|
469
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
376
470
|
font: "inherit",
|
|
377
471
|
fontSize: 12,
|
|
378
|
-
lineHeight: "
|
|
379
|
-
|
|
472
|
+
lineHeight: "24px",
|
|
473
|
+
height: 26,
|
|
474
|
+
padding: "0 6px",
|
|
475
|
+
boxSizing: "border-box",
|
|
380
476
|
maxWidth: 220,
|
|
381
477
|
cursor: "pointer",
|
|
382
478
|
flex: "1",
|
|
@@ -384,14 +480,16 @@ window.__ModuleLoader__.load({
|
|
|
384
480
|
outline: "none"
|
|
385
481
|
},
|
|
386
482
|
input: {
|
|
387
|
-
background: "
|
|
388
|
-
border: "1px solid var(--dsw-alias-
|
|
389
|
-
borderRadius:
|
|
483
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.1))",
|
|
484
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
485
|
+
borderRadius: 7,
|
|
390
486
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
391
487
|
font: "inherit",
|
|
392
488
|
fontSize: 12,
|
|
393
|
-
lineHeight: "
|
|
394
|
-
|
|
489
|
+
lineHeight: "24px",
|
|
490
|
+
height: 26,
|
|
491
|
+
padding: "0 8px",
|
|
492
|
+
boxSizing: "border-box",
|
|
395
493
|
flex: "1",
|
|
396
494
|
minWidth: 0,
|
|
397
495
|
outline: "none"
|
|
@@ -400,47 +498,123 @@ window.__ModuleLoader__.load({
|
|
|
400
498
|
// silently strips every line feed, so a drafted subject+body would lose
|
|
401
499
|
// its body before the request was ever sent.
|
|
402
500
|
textarea: {
|
|
403
|
-
background: "
|
|
404
|
-
border: "1px solid var(--dsw-alias-
|
|
405
|
-
borderRadius:
|
|
501
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.1))",
|
|
502
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.3))",
|
|
503
|
+
borderRadius: 7,
|
|
406
504
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
407
505
|
font: "inherit",
|
|
408
506
|
fontSize: 12,
|
|
409
|
-
lineHeight: "
|
|
507
|
+
lineHeight: "17px",
|
|
410
508
|
padding: "4px 8px",
|
|
509
|
+
minHeight: 46,
|
|
411
510
|
flex: "1",
|
|
412
511
|
minWidth: 0,
|
|
512
|
+
boxSizing: "border-box",
|
|
413
513
|
outline: "none",
|
|
414
514
|
resize: "vertical",
|
|
415
515
|
overflowY: "auto"
|
|
416
516
|
},
|
|
417
|
-
|
|
517
|
+
// ── list sections (changes / recent commits) ─────────────────────
|
|
518
|
+
// A section is a card: a full-width header toggle (chevron + label +
|
|
519
|
+
// count) and its rows. Collapsing hides the rows outright — the old
|
|
520
|
+
// header doubled as "show more" for a preview, so its chevron pointed
|
|
521
|
+
// the wrong way for a list that was already on screen.
|
|
522
|
+
section: {
|
|
523
|
+
marginTop: 8,
|
|
524
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.22))",
|
|
525
|
+
borderRadius: 8,
|
|
526
|
+
background: "var(--dsw-alias-bg-layer-1, rgba(127,127,127,0.06))",
|
|
527
|
+
overflow: "hidden"
|
|
528
|
+
},
|
|
529
|
+
sectionHeader: {
|
|
530
|
+
display: "flex",
|
|
531
|
+
alignItems: "center",
|
|
532
|
+
gap: 6,
|
|
533
|
+
width: "100%",
|
|
534
|
+
padding: "6px 8px",
|
|
535
|
+
background: "transparent",
|
|
536
|
+
border: "none",
|
|
537
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
538
|
+
font: "inherit",
|
|
418
539
|
fontSize: 12,
|
|
419
540
|
fontWeight: 600,
|
|
420
|
-
|
|
421
|
-
|
|
541
|
+
lineHeight: "18px",
|
|
542
|
+
boxSizing: "border-box",
|
|
543
|
+
cursor: "pointer",
|
|
544
|
+
textAlign: "left"
|
|
545
|
+
},
|
|
546
|
+
sectionChevron: {
|
|
547
|
+
flex: "none",
|
|
548
|
+
width: 10,
|
|
549
|
+
fontSize: 10,
|
|
550
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
551
|
+
},
|
|
552
|
+
sectionLabel: {
|
|
553
|
+
flex: "1",
|
|
554
|
+
minWidth: 0,
|
|
555
|
+
overflow: "hidden",
|
|
556
|
+
textOverflow: "ellipsis",
|
|
557
|
+
whiteSpace: "nowrap"
|
|
558
|
+
},
|
|
559
|
+
sectionCount: {
|
|
560
|
+
flex: "none",
|
|
561
|
+
padding: "0 6px",
|
|
562
|
+
borderRadius: 999,
|
|
563
|
+
background: "color-mix(in srgb, var(--dsw-alias-label-primary, #e5e7eb) 10%, transparent)",
|
|
564
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
565
|
+
fontSize: 11,
|
|
566
|
+
fontWeight: 500,
|
|
567
|
+
lineHeight: "16px"
|
|
568
|
+
},
|
|
569
|
+
sectionBody: {
|
|
570
|
+
padding: "0 4px 4px"
|
|
571
|
+
},
|
|
572
|
+
sectionEmpty: {
|
|
573
|
+
padding: "2px 6px 6px",
|
|
574
|
+
fontSize: 12,
|
|
575
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
576
|
+
},
|
|
577
|
+
sectionMore: {
|
|
578
|
+
display: "block",
|
|
579
|
+
width: "100%",
|
|
580
|
+
padding: "2px 0 4px",
|
|
581
|
+
background: "transparent",
|
|
582
|
+
border: "none",
|
|
583
|
+
color: "var(--dsw-alias-link, #4f8cff)",
|
|
584
|
+
font: "inherit",
|
|
585
|
+
fontSize: 11,
|
|
422
586
|
cursor: "pointer",
|
|
423
|
-
|
|
587
|
+
textAlign: "center"
|
|
424
588
|
},
|
|
425
589
|
changeRow: {
|
|
426
590
|
display: "flex",
|
|
427
591
|
alignItems: "center",
|
|
428
592
|
gap: 8,
|
|
429
593
|
fontSize: 12,
|
|
430
|
-
lineHeight: "
|
|
431
|
-
|
|
432
|
-
padding: "1px 6px",
|
|
433
|
-
margin: "0 -6px",
|
|
594
|
+
lineHeight: "18px",
|
|
595
|
+
padding: "3px 6px",
|
|
434
596
|
borderRadius: 6,
|
|
435
597
|
minWidth: 0,
|
|
436
598
|
cursor: "pointer"
|
|
437
599
|
},
|
|
438
600
|
changePath: {
|
|
601
|
+
flex: "1",
|
|
602
|
+
minWidth: 0,
|
|
439
603
|
overflow: "hidden",
|
|
440
604
|
textOverflow: "ellipsis",
|
|
441
605
|
whiteSpace: "nowrap",
|
|
442
|
-
|
|
443
|
-
|
|
606
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
607
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)"
|
|
608
|
+
},
|
|
609
|
+
// Per-status chip; `color-mix(currentColor)` gives every status the same
|
|
610
|
+
// tint shape from whichever state colour it carries.
|
|
611
|
+
changeTag: {
|
|
612
|
+
flex: "none",
|
|
613
|
+
padding: "0 6px",
|
|
614
|
+
borderRadius: 4,
|
|
615
|
+
fontSize: 11,
|
|
616
|
+
lineHeight: "16px",
|
|
617
|
+
background: "color-mix(in srgb, currentColor 15%, transparent)"
|
|
444
618
|
},
|
|
445
619
|
// A change row is the diff viewer's navigation: it has to read as a
|
|
446
620
|
// control, and to show which file the right-hand pane is showing.
|
|
@@ -449,14 +623,12 @@ window.__ModuleLoader__.load({
|
|
|
449
623
|
alignItems: "center",
|
|
450
624
|
gap: 8,
|
|
451
625
|
fontSize: 12,
|
|
452
|
-
lineHeight: "
|
|
453
|
-
|
|
454
|
-
padding: "1px 6px",
|
|
455
|
-
margin: "0 -6px",
|
|
626
|
+
lineHeight: "18px",
|
|
627
|
+
padding: "3px 6px",
|
|
456
628
|
borderRadius: 6,
|
|
457
629
|
minWidth: 0,
|
|
458
630
|
cursor: "pointer",
|
|
459
|
-
background: "var(--dsw-alias-
|
|
631
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-business-primary, #4f8cff) 15%, transparent)"
|
|
460
632
|
},
|
|
461
633
|
// ── two-pane (changes + diff) layout ────────────────────────────
|
|
462
634
|
// `bodySplit` replaces `body` while a file is selected: the left pane
|
|
@@ -528,9 +700,9 @@ window.__ModuleLoader__.load({
|
|
|
528
700
|
lineHeight: "18px",
|
|
529
701
|
padding: "0 8px",
|
|
530
702
|
borderRadius: 999,
|
|
531
|
-
border: "1px solid var(--dsw-alias-
|
|
703
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.25))",
|
|
532
704
|
background: "transparent",
|
|
533
|
-
color: "var(--dsw-alias-label-
|
|
705
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
534
706
|
font: "inherit",
|
|
535
707
|
fontSize: 11,
|
|
536
708
|
cursor: "pointer"
|
|
@@ -541,7 +713,7 @@ window.__ModuleLoader__.load({
|
|
|
541
713
|
padding: "0 8px",
|
|
542
714
|
borderRadius: 999,
|
|
543
715
|
border: "1px solid transparent",
|
|
544
|
-
background: "var(--dsw-alias-
|
|
716
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-business-primary, #4f8cff) 16%, transparent)",
|
|
545
717
|
color: "var(--dsw-alias-label-primary, #e5e7eb)",
|
|
546
718
|
font: "inherit",
|
|
547
719
|
fontSize: 11,
|
|
@@ -571,7 +743,7 @@ window.__ModuleLoader__.load({
|
|
|
571
743
|
width: 34,
|
|
572
744
|
textAlign: "right",
|
|
573
745
|
paddingRight: 6,
|
|
574
|
-
color: "var(--dsw-alias-label-
|
|
746
|
+
color: "var(--dsw-alias-label-tertiary, #6b7280)",
|
|
575
747
|
userSelect: "none",
|
|
576
748
|
WebkitUserSelect: "none"
|
|
577
749
|
},
|
|
@@ -595,7 +767,7 @@ window.__ModuleLoader__.load({
|
|
|
595
767
|
color: "var(--dsw-alias-state-business-primary, #4f8cff)"
|
|
596
768
|
},
|
|
597
769
|
diffMetaRow: {
|
|
598
|
-
color: "var(--dsw-alias-label-
|
|
770
|
+
color: "var(--dsw-alias-label-tertiary, #6b7280)"
|
|
599
771
|
},
|
|
600
772
|
diffNotice: {
|
|
601
773
|
margin: "6px 10px",
|
|
@@ -603,7 +775,7 @@ window.__ModuleLoader__.load({
|
|
|
603
775
|
borderRadius: 8,
|
|
604
776
|
fontSize: 12,
|
|
605
777
|
lineHeight: "18px",
|
|
606
|
-
background: "var(--dsw-alias-
|
|
778
|
+
background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.12))",
|
|
607
779
|
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
608
780
|
},
|
|
609
781
|
statusTag: {
|
|
@@ -612,22 +784,32 @@ window.__ModuleLoader__.load({
|
|
|
612
784
|
lineHeight: "16px",
|
|
613
785
|
padding: "0 6px",
|
|
614
786
|
borderRadius: 4,
|
|
615
|
-
background: "var(--dsw-alias-
|
|
787
|
+
background: "color-mix(in srgb, var(--dsw-alias-label-primary, #e5e7eb) 10%, transparent)",
|
|
788
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
616
789
|
},
|
|
617
790
|
logRow: {
|
|
618
791
|
display: "flex",
|
|
619
792
|
alignItems: "center",
|
|
620
793
|
gap: 8,
|
|
621
794
|
fontSize: 12,
|
|
622
|
-
lineHeight: "
|
|
623
|
-
|
|
624
|
-
|
|
795
|
+
lineHeight: "18px",
|
|
796
|
+
padding: "3px 6px",
|
|
797
|
+
borderRadius: 6,
|
|
625
798
|
minWidth: 0
|
|
626
799
|
},
|
|
627
800
|
logSha: {
|
|
628
801
|
flex: "none",
|
|
629
|
-
|
|
630
|
-
|
|
802
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
803
|
+
fontSize: 11,
|
|
804
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)"
|
|
805
|
+
},
|
|
806
|
+
logSubject: {
|
|
807
|
+
flex: "1",
|
|
808
|
+
minWidth: 0,
|
|
809
|
+
overflow: "hidden",
|
|
810
|
+
textOverflow: "ellipsis",
|
|
811
|
+
whiteSpace: "nowrap",
|
|
812
|
+
color: "var(--dsw-alias-label-primary, #e5e7eb)"
|
|
631
813
|
},
|
|
632
814
|
output: {
|
|
633
815
|
// Sits at the top of the body, so the breathing room belongs below it.
|
|
@@ -667,8 +849,8 @@ window.__ModuleLoader__.load({
|
|
|
667
849
|
outputDetail: {
|
|
668
850
|
marginTop: 6,
|
|
669
851
|
paddingTop: 6,
|
|
670
|
-
borderTop: "1px solid
|
|
671
|
-
fontFamily: "monospace",
|
|
852
|
+
borderTop: "1px solid color-mix(in srgb, currentColor 30%, transparent)",
|
|
853
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
672
854
|
fontSize: 11,
|
|
673
855
|
lineHeight: "16px",
|
|
674
856
|
wordBreak: "break-word",
|
|
@@ -677,11 +859,11 @@ window.__ModuleLoader__.load({
|
|
|
677
859
|
whiteSpace: "pre-wrap"
|
|
678
860
|
},
|
|
679
861
|
outputOk: {
|
|
680
|
-
background: "var(--dsw-alias-state-success-
|
|
862
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-success-primary, #34c759) 14%, transparent)",
|
|
681
863
|
color: "var(--dsw-alias-state-success-primary, #34c759)"
|
|
682
864
|
},
|
|
683
865
|
outputError: {
|
|
684
|
-
background: "var(--dsw-alias-state-error-
|
|
866
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-error-primary, #ef4444) 14%, transparent)",
|
|
685
867
|
color: "var(--dsw-alias-state-error-primary, #ef4444)"
|
|
686
868
|
},
|
|
687
869
|
dockWrap: {
|
|
@@ -691,7 +873,7 @@ window.__ModuleLoader__.load({
|
|
|
691
873
|
maxWidth: "100%",
|
|
692
874
|
fontSize: 12,
|
|
693
875
|
lineHeight: "20px",
|
|
694
|
-
color: "var(--dsw-alias-label-
|
|
876
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
695
877
|
whiteSpace: "nowrap",
|
|
696
878
|
overflow: "hidden",
|
|
697
879
|
textOverflow: "ellipsis",
|
|
@@ -705,6 +887,33 @@ window.__ModuleLoader__.load({
|
|
|
705
887
|
return text.length > max ? text.slice(0, max - 1) + "…" : text;
|
|
706
888
|
}
|
|
707
889
|
|
|
890
|
+
/**
|
|
891
|
+
* The model route one session's AI draft should use, or null to let the
|
|
892
|
+
* host fall back to its first registered provider route.
|
|
893
|
+
*
|
|
894
|
+
* Two host generations carry the same `modelSelection` projection: the
|
|
895
|
+
* row's own `projectionValues` (present since 0.1.6) and, since 0.1.7,
|
|
896
|
+
* the snapshot's per-session `projectionsBySession[id].values`. Read the
|
|
897
|
+
* row first, then the shared record, so neither generation loses a route
|
|
898
|
+
* the user already chose. `next` (a pending pick) beats `lastUsed`.
|
|
899
|
+
*
|
|
900
|
+
* @param summary - `byId[sessionId]` row, when the snapshot has one.
|
|
901
|
+
* @param sessions - the whole `useSessions` snapshot (may be undefined).
|
|
902
|
+
* @param sessionId - the bound session id, or null/undefined.
|
|
903
|
+
* @returns `{ provider, model }`, or null.
|
|
904
|
+
*/
|
|
905
|
+
function sessionModelRoute(summary, sessions, sessionId) {
|
|
906
|
+
var selection = summary && summary.projectionValues ? summary.projectionValues.modelSelection : undefined;
|
|
907
|
+
if (!selection && sessionId !== null && sessionId !== undefined && sessions && sessions.projectionsBySession) {
|
|
908
|
+
var record = sessions.projectionsBySession[sessionId];
|
|
909
|
+
selection = record && record.values ? record.values.modelSelection : undefined;
|
|
910
|
+
}
|
|
911
|
+
if (!selection) return null;
|
|
912
|
+
var effective = selection.next || selection.lastUsed;
|
|
913
|
+
if (!effective || !effective.provider || !effective.model) return null;
|
|
914
|
+
return { provider: effective.provider, model: effective.model };
|
|
915
|
+
}
|
|
916
|
+
|
|
708
917
|
/**
|
|
709
918
|
* Strip ANSI/VT escape sequences from git's human-readable output.
|
|
710
919
|
*
|
|
@@ -824,6 +1033,84 @@ window.__ModuleLoader__.load({
|
|
|
824
1033
|
}, children);
|
|
825
1034
|
}
|
|
826
1035
|
|
|
1036
|
+
/** Rows a collapsed-by-default list shows before its "show all" footer. */
|
|
1037
|
+
var CHANGES_PREVIEW = 8;
|
|
1038
|
+
/** Same, for the recent-commit list (shorter rows, less to say). */
|
|
1039
|
+
var LOG_PREVIEW = 5;
|
|
1040
|
+
|
|
1041
|
+
/** The state colour one porcelain status carries, in theme tokens. */
|
|
1042
|
+
function changeTagStyle(status) {
|
|
1043
|
+
var color = status === "added" || status === "untracked"
|
|
1044
|
+
? "var(--dsw-alias-state-success-primary, #34c759)"
|
|
1045
|
+
: status === "deleted" || status === "conflict"
|
|
1046
|
+
? "var(--dsw-alias-state-error-primary, #ef4444)"
|
|
1047
|
+
: status === "renamed" || status === "copied"
|
|
1048
|
+
// `state-business-primary` is the real accent (deepseek blue);
|
|
1049
|
+
// `brand-primary` is the inverted contrast colour and would make
|
|
1050
|
+
// this chip white-on-white in the dark theme.
|
|
1051
|
+
? "var(--dsw-alias-state-business-primary, #4f8cff)"
|
|
1052
|
+
: status === "modified" || status === "changed"
|
|
1053
|
+
? "var(--dsw-alias-state-warn-primary, #f0a020)"
|
|
1054
|
+
: "var(--dsw-alias-label-secondary, #c8ccd2)";
|
|
1055
|
+
// `changeTag`'s background is `color-mix(currentColor…)`, so the tint
|
|
1056
|
+
// follows whichever colour the status carries.
|
|
1057
|
+
return Object.assign({}, S.changeTag, { color: color });
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* One collapsible list section: a full-width header toggle (chevron +
|
|
1062
|
+
* label + count) and, while open, its rows plus a footer that expands the
|
|
1063
|
+
* preview. Two separate states on purpose — the header collapses the
|
|
1064
|
+
* section, the footer widens it — because one flag doing both made the
|
|
1065
|
+
* chevron point the wrong way for a list that was already on screen.
|
|
1066
|
+
*
|
|
1067
|
+
* @param spec - `{ hook, label, count, open, all, cap, empty, rows, onToggle, onMore }`.
|
|
1068
|
+
* @param t - the locale translator.
|
|
1069
|
+
* @returns the section element.
|
|
1070
|
+
*/
|
|
1071
|
+
function sectionView(spec, t) {
|
|
1072
|
+
var children = [h("button", {
|
|
1073
|
+
key: "header",
|
|
1074
|
+
type: "button",
|
|
1075
|
+
"data-dsh-git": spec.hook + "-header",
|
|
1076
|
+
style: S.sectionHeader,
|
|
1077
|
+
"aria-expanded": spec.open ? "true" : "false",
|
|
1078
|
+
onClick: spec.onToggle
|
|
1079
|
+
}, [
|
|
1080
|
+
h("span", { key: "chevron", style: S.sectionChevron }, spec.open ? "▾" : "▸"),
|
|
1081
|
+
h("span", { key: "label", style: S.sectionLabel }, spec.label),
|
|
1082
|
+
h("span", { key: "count", style: S.sectionCount }, String(spec.count))
|
|
1083
|
+
])];
|
|
1084
|
+
if (spec.open) {
|
|
1085
|
+
var previewed = spec.all || spec.count <= spec.cap;
|
|
1086
|
+
children.push(h("div", {
|
|
1087
|
+
key: "body",
|
|
1088
|
+
"data-dsh-git": spec.hook + "-body",
|
|
1089
|
+
style: S.sectionBody
|
|
1090
|
+
}, spec.count === 0
|
|
1091
|
+
? h("div", { key: "empty", style: S.sectionEmpty }, spec.empty)
|
|
1092
|
+
: (previewed ? spec.rows : spec.rows.slice(0, spec.cap))));
|
|
1093
|
+
if (!previewed) {
|
|
1094
|
+
children.push(h("button", {
|
|
1095
|
+
key: "more",
|
|
1096
|
+
type: "button",
|
|
1097
|
+
"data-dsh-git": spec.hook + "-more",
|
|
1098
|
+
style: S.sectionMore,
|
|
1099
|
+
onClick: spec.onMore
|
|
1100
|
+
}, t("section.more", { count: spec.count })));
|
|
1101
|
+
} else if (spec.all && spec.count > spec.cap) {
|
|
1102
|
+
children.push(h("button", {
|
|
1103
|
+
key: "more",
|
|
1104
|
+
type: "button",
|
|
1105
|
+
"data-dsh-git": spec.hook + "-more",
|
|
1106
|
+
style: S.sectionMore,
|
|
1107
|
+
onClick: spec.onMore
|
|
1108
|
+
}, t("section.less")));
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return h("div", { key: spec.hook, "data-dsh-git": spec.hook, style: S.section }, children);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
827
1114
|
/** Call one /dsh-git-rpc endpoint. */
|
|
828
1115
|
function rpc(ctx, endpoint, args) {
|
|
829
1116
|
return ctx.connection.rpc.call("/dsh-git-rpc", endpoint, { args: args || {} }).then(sanitizeResult);
|
|
@@ -849,8 +1136,11 @@ window.__ModuleLoader__.load({
|
|
|
849
1136
|
commit: function (cwd, message) { return rpc(ctx, "commit", { cwd: cwd, message: message }); },
|
|
850
1137
|
push: function (cwd) { return rpc(ctx, "push", { cwd: cwd }); },
|
|
851
1138
|
log: function (cwd) { return rpc(ctx, "log", { cwd: cwd, count: 10 }); },
|
|
852
|
-
generateMessage: function (cwd, mode, provider, model) {
|
|
853
|
-
|
|
1139
|
+
generateMessage: function (cwd, mode, provider, model, sessionId) {
|
|
1140
|
+
// The session travels with the request: session-labelled
|
|
1141
|
+
// providers reject an unidentified call, and the host forwards
|
|
1142
|
+
// a session id to its adapter only when one is present.
|
|
1143
|
+
return rpc(ctx, "generateMessage", { cwd: cwd, mode: mode, provider: provider, model: model, sessionId: sessionId });
|
|
854
1144
|
}
|
|
855
1145
|
};
|
|
856
1146
|
|
|
@@ -881,6 +1171,7 @@ window.__ModuleLoader__.load({
|
|
|
881
1171
|
commits: [],
|
|
882
1172
|
error: null,
|
|
883
1173
|
busy: null,
|
|
1174
|
+
refreshing: false,
|
|
884
1175
|
lastResult: null,
|
|
885
1176
|
panelOpen: false
|
|
886
1177
|
};
|
|
@@ -942,7 +1233,19 @@ window.__ModuleLoader__.load({
|
|
|
942
1233
|
|
|
943
1234
|
function doRefresh(cwd) {
|
|
944
1235
|
var mySeq = ++seq;
|
|
945
|
-
|
|
1236
|
+
// Re-reading the SAME workspace keeps what is already on screen.
|
|
1237
|
+
// Flipping the body to "loading" for a few hundred milliseconds
|
|
1238
|
+
// collapsed the whole workbench and snapped it back — that is the
|
|
1239
|
+
// jump you saw after clicking ↻ or any action button. Only a first
|
|
1240
|
+
// load (or a workspace switch) has nothing to keep.
|
|
1241
|
+
var keep = cwd !== null && cwd === state.cwd && state.phase === "ready";
|
|
1242
|
+
emit(Object.assign({}, state, {
|
|
1243
|
+
sessionId: sessionId,
|
|
1244
|
+
cwd: cwd,
|
|
1245
|
+
phase: keep ? state.phase : (cwd ? "loading" : "idle"),
|
|
1246
|
+
refreshing: keep,
|
|
1247
|
+
error: keep ? state.error : null
|
|
1248
|
+
}));
|
|
946
1249
|
if (!cwd) return Promise.resolve();
|
|
947
1250
|
return Promise.all([
|
|
948
1251
|
verbs.status(cwd),
|
|
@@ -1052,7 +1355,7 @@ window.__ModuleLoader__.load({
|
|
|
1052
1355
|
};
|
|
1053
1356
|
var OPTGROUP_STYLE = {
|
|
1054
1357
|
background: "var(--dsw-alias-bg-base, #1e1e1e)",
|
|
1055
|
-
color: "var(--dsw-alias-label-
|
|
1358
|
+
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
1056
1359
|
fontWeight: 600
|
|
1057
1360
|
};
|
|
1058
1361
|
|
|
@@ -1203,6 +1506,32 @@ window.__ModuleLoader__.load({
|
|
|
1203
1506
|
var PANEL_MARGIN = 24;
|
|
1204
1507
|
/** Grab width of the panel's right-edge resize handle. */
|
|
1205
1508
|
var PANEL_RESIZE_GRIP = 6;
|
|
1509
|
+
/**
|
|
1510
|
+
* Height the panel takes while the diff pane is open: a fixed height, not a
|
|
1511
|
+
* cap. With a cap the panel's height followed its content, so the moment the
|
|
1512
|
+
* diff arrived the pane grew and — anchored by `bottom` — the whole panel
|
|
1513
|
+
* jumped (the flash you saw when opening a diff). The `min()` keeps the panel
|
|
1514
|
+
* on screen in a short window (168px is the panel's bottom offset).
|
|
1515
|
+
*/
|
|
1516
|
+
var DIFF_PANEL_HEIGHT = "min(72vh, calc(100vh - 184px))";
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* The panel's box in either mode: the compact single column, or workbench +
|
|
1520
|
+
* diff with a height that cannot move once the pane is open.
|
|
1521
|
+
* @param selected - the change the diff pane shows, or null.
|
|
1522
|
+
* @param diffWidth - width of the diff pane.
|
|
1523
|
+
* @returns the panel's inline style.
|
|
1524
|
+
*/
|
|
1525
|
+
function panelBoxStyle(selected, diffWidth) {
|
|
1526
|
+
var box = Object.assign({}, S.panel, {
|
|
1527
|
+
width: selected === null ? S.panel.width : DIFF_LEFT_PANE_WIDTH + PANEL_BORDER_WIDTH + diffWidth
|
|
1528
|
+
});
|
|
1529
|
+
if (selected !== null) {
|
|
1530
|
+
box.height = DIFF_PANEL_HEIGHT;
|
|
1531
|
+
box.maxHeight = DIFF_PANEL_HEIGHT;
|
|
1532
|
+
}
|
|
1533
|
+
return box;
|
|
1534
|
+
}
|
|
1206
1535
|
|
|
1207
1536
|
/** The last path segment, for chip-sized text. */
|
|
1208
1537
|
function baseName(file) {
|
|
@@ -1510,10 +1839,14 @@ window.__ModuleLoader__.load({
|
|
|
1510
1839
|
// with "selector is not a function".
|
|
1511
1840
|
var sessions = useSessions(function (s) { return s; });
|
|
1512
1841
|
|
|
1513
|
-
// NOTE:
|
|
1514
|
-
//
|
|
1515
|
-
//
|
|
1516
|
-
//
|
|
1842
|
+
// NOTE: subscribe through the classic useState + useEffect pattern
|
|
1843
|
+
// instead of React.useSyncExternalStore, so this store's own
|
|
1844
|
+
// subscription is independent of whichever implementation the seed
|
|
1845
|
+
// ships. This is about keeping one dependency out of the path, not a
|
|
1846
|
+
// claim that the seeded build is broken: the framework's own
|
|
1847
|
+
// `useSessions` prop already goes through the renderer's
|
|
1848
|
+
// useSyncExternalStoreWithSelector, so an unusable seed would break
|
|
1849
|
+
// the session list before it broke this panel.
|
|
1517
1850
|
var stateRef = React.useState(function () { return store.getSnapshot(); });
|
|
1518
1851
|
var state = stateRef[0];
|
|
1519
1852
|
var setState = stateRef[1];
|
|
@@ -1534,16 +1867,10 @@ window.__ModuleLoader__.load({
|
|
|
1534
1867
|
var sessionId = state.sessionId;
|
|
1535
1868
|
var currentSummary = sessionId !== null && sessions && sessions.byId ? sessions.byId[sessionId] : undefined;
|
|
1536
1869
|
|
|
1537
|
-
// The session's own model route, when one is recorded
|
|
1538
|
-
//
|
|
1539
|
-
//
|
|
1540
|
-
var sessionRoute = (
|
|
1541
|
-
var selection = currentSummary && currentSummary.projectionValues ? currentSummary.projectionValues.modelSelection : undefined;
|
|
1542
|
-
if (!selection) return null;
|
|
1543
|
-
var effective = selection.next || selection.lastUsed;
|
|
1544
|
-
if (!effective || !effective.provider || !effective.model) return null;
|
|
1545
|
-
return { provider: effective.provider, model: effective.model };
|
|
1546
|
-
})();
|
|
1870
|
+
// The session's own model route, when one is recorded. Both projection
|
|
1871
|
+
// surfaces it can come from are handled by sessionModelRoute; a
|
|
1872
|
+
// missing route leaves generation to the host's first registered one.
|
|
1873
|
+
var sessionRoute = sessionModelRoute(currentSummary, sessions, sessionId);
|
|
1547
1874
|
|
|
1548
1875
|
var messageRef = React.useState("");
|
|
1549
1876
|
var message = messageRef[0];
|
|
@@ -1553,12 +1880,22 @@ window.__ModuleLoader__.load({
|
|
|
1553
1880
|
var generateModeRef = React.useState("staged");
|
|
1554
1881
|
var generateMode = generateModeRef[0];
|
|
1555
1882
|
var setGenerateMode = generateModeRef[1];
|
|
1556
|
-
|
|
1883
|
+
// Sections start OPEN: a Git panel that hides the user's own changes
|
|
1884
|
+
// behind a chevron is a panel that looks empty. Collapsing is the
|
|
1885
|
+
// explicit choice, and widening a long list past its preview is a
|
|
1886
|
+
// separate one (`…All`), so the chevron always tells the truth.
|
|
1887
|
+
var changesOpenRef = React.useState(true);
|
|
1557
1888
|
var changesOpen = changesOpenRef[0];
|
|
1558
1889
|
var setChangesOpen = changesOpenRef[1];
|
|
1559
|
-
var
|
|
1890
|
+
var changesAllRef = React.useState(false);
|
|
1891
|
+
var changesAll = changesAllRef[0];
|
|
1892
|
+
var setChangesAll = changesAllRef[1];
|
|
1893
|
+
var logOpenRef = React.useState(true);
|
|
1560
1894
|
var logOpen = logOpenRef[0];
|
|
1561
1895
|
var setLogOpen = logOpenRef[1];
|
|
1896
|
+
var logAllRef = React.useState(false);
|
|
1897
|
+
var logAll = logAllRef[0];
|
|
1898
|
+
var setLogAll = logAllRef[1];
|
|
1562
1899
|
// Whether the last operation's git output is expanded. A new result
|
|
1563
1900
|
// always starts collapsed: the summary line is the notification, the
|
|
1564
1901
|
// raw output is opt-in.
|
|
@@ -1820,11 +2157,7 @@ window.__ModuleLoader__.load({
|
|
|
1820
2157
|
// while nothing is selected, and the two-pane width (workbench + diff)
|
|
1821
2158
|
// once a file is open. Dragging the panel's right edge is what resizes
|
|
1822
2159
|
// 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
|
-
});
|
|
2160
|
+
var panelStyle = panelBoxStyle(selected, diffWidth);
|
|
1828
2161
|
if (dragPos) {
|
|
1829
2162
|
panelStyle = Object.assign(panelStyle, {
|
|
1830
2163
|
left: dragPos.left,
|
|
@@ -1858,20 +2191,24 @@ window.__ModuleLoader__.load({
|
|
|
1858
2191
|
"data-dsh-git": "panel-drag"
|
|
1859
2192
|
}, [
|
|
1860
2193
|
h("span", { key: "title", style: S.title }, "⎇ " + t("panel.title")),
|
|
1861
|
-
h("span", { key: "cwd", style: S.
|
|
2194
|
+
h("span", { key: "cwd", style: S.cwdPath, title: cwd }, shortText(cwd, 80)),
|
|
1862
2195
|
h("button", {
|
|
1863
2196
|
key: "refresh",
|
|
1864
2197
|
type: "button",
|
|
1865
|
-
|
|
1866
|
-
|
|
2198
|
+
// A re-read keeps the whole workbench on screen and reports itself
|
|
2199
|
+
// here instead of collapsing the body to a "loading" line and
|
|
2200
|
+
// snapping back — that flash was the jump.
|
|
2201
|
+
style: Object.assign({}, S.iconButton, busy !== null || state.refreshing ? S.buttonDisabled : null),
|
|
2202
|
+
disabled: busy !== null || state.refreshing === true,
|
|
1867
2203
|
onClick: function () { store.refresh(state.cwd); },
|
|
1868
2204
|
"aria-label": t("refresh.aria"),
|
|
1869
|
-
|
|
1870
|
-
|
|
2205
|
+
"aria-busy": state.refreshing === true ? "true" : "false",
|
|
2206
|
+
title: state.refreshing === true ? t("refresh.busy") : t("refresh.aria")
|
|
2207
|
+
}, state.refreshing === true ? "⋯" : "↻"),
|
|
1871
2208
|
h("button", {
|
|
1872
2209
|
key: "collapse",
|
|
1873
2210
|
type: "button",
|
|
1874
|
-
style: S.
|
|
2211
|
+
style: S.iconButton,
|
|
1875
2212
|
onClick: function () { store.setPanelOpen(false); },
|
|
1876
2213
|
"aria-label": t("panel.collapse"),
|
|
1877
2214
|
title: t("panel.collapse")
|
|
@@ -1896,15 +2233,21 @@ window.__ModuleLoader__.load({
|
|
|
1896
2233
|
} else if (!state.repo) {
|
|
1897
2234
|
bodyChildren.push(h("div", { key: "norepo", style: S.meta }, t("notRepo")));
|
|
1898
2235
|
} else {
|
|
1899
|
-
// status line
|
|
2236
|
+
// status line — the branch itself lives in the select right below,
|
|
2237
|
+
// so this row carries only what the select cannot say: pending
|
|
2238
|
+
// changes and how the branch sits against its upstream.
|
|
1900
2239
|
var statusLine = [];
|
|
1901
2240
|
var branchText = state.branch;
|
|
1902
2241
|
if (!branchText && state.detached) {
|
|
1903
2242
|
branchText = t("detached") + (state.oid ? " " + state.oid.slice(0, 7) : "");
|
|
1904
2243
|
}
|
|
1905
|
-
|
|
2244
|
+
if (state.detached) {
|
|
2245
|
+
statusLine.push(h("span", { key: "chip", style: S.chip, title: branchText }, branchText));
|
|
2246
|
+
}
|
|
1906
2247
|
if (state.dirty > 0) {
|
|
1907
|
-
statusLine.push(h("span", { key: "dirty", style: S.dirty, title: t("dirty", { count: state.dirty }) }, "● " + state.dirty));
|
|
2248
|
+
statusLine.push(h("span", { key: "dirty", style: S.dirty, title: t("dirty", { count: state.dirty }) }, "● " + t("dirty", { count: state.dirty })));
|
|
2249
|
+
} else {
|
|
2250
|
+
statusLine.push(h("span", { key: "clean", style: S.meta }, "✓ " + t("changes.none")));
|
|
1908
2251
|
}
|
|
1909
2252
|
if (state.ahead > 0 || state.behind > 0) {
|
|
1910
2253
|
statusLine.push(h("span", { key: "ab", style: S.meta }, "↑" + state.ahead + " ↓" + state.behind));
|
|
@@ -2024,94 +2367,96 @@ window.__ModuleLoader__.load({
|
|
|
2024
2367
|
]));
|
|
2025
2368
|
}
|
|
2026
2369
|
|
|
2027
|
-
// network
|
|
2370
|
+
// network actions — three equal columns. Auto-width labels used to
|
|
2371
|
+
// give each button a different width for the same job, which is what
|
|
2372
|
+
// made this row read as a pile rather than a toolbar.
|
|
2028
2373
|
bodyChildren.push(h("div", { key: "net", style: S.row }, [
|
|
2029
2374
|
h("button", {
|
|
2030
2375
|
key: "fetch",
|
|
2031
2376
|
type: "button",
|
|
2032
|
-
style: Object.assign({}, S.button, busy !== null ? S.buttonDisabled : null),
|
|
2377
|
+
style: Object.assign({}, S.button, S.grow, busy !== null ? S.buttonDisabled : null),
|
|
2033
2378
|
disabled: busy !== null,
|
|
2034
2379
|
onClick: function () { store.act("fetch", function () { return store.verbs.fetch(state.cwd); }); }
|
|
2035
2380
|
}, busy === "fetch" ? t("busy.fetch") : t("action.fetch")),
|
|
2036
2381
|
h("button", {
|
|
2037
2382
|
key: "pull",
|
|
2038
2383
|
type: "button",
|
|
2039
|
-
style: Object.assign({}, S.button, busy !== null ? S.buttonDisabled : null),
|
|
2384
|
+
style: Object.assign({}, S.button, S.grow, busy !== null ? S.buttonDisabled : null),
|
|
2040
2385
|
disabled: busy !== null,
|
|
2041
2386
|
onClick: function () { store.act("pull", function () { return store.verbs.pull(state.cwd); }); }
|
|
2042
2387
|
}, busy === "pull" ? t("busy.pull") : t("action.pull")),
|
|
2043
2388
|
h("button", {
|
|
2044
2389
|
key: "push",
|
|
2045
2390
|
type: "button",
|
|
2046
|
-
style: Object.assign({}, S.buttonPrimary, busy !== null ? S.buttonDisabled : null),
|
|
2391
|
+
style: Object.assign({}, S.buttonPrimary, S.grow, busy !== null ? S.buttonDisabled : null),
|
|
2047
2392
|
disabled: busy !== null,
|
|
2048
2393
|
onClick: function () { store.act("push", function () { return store.verbs.push(state.cwd); }); }
|
|
2049
2394
|
}, busy === "push" ? t("busy.push") : t("action.push"))
|
|
2050
2395
|
]));
|
|
2051
2396
|
|
|
2052
|
-
// commit
|
|
2053
|
-
//
|
|
2054
|
-
//
|
|
2055
|
-
// message row.
|
|
2397
|
+
// commit flow, one card: stage all → draft basis + draft → message →
|
|
2398
|
+
// commit. Grouping it keeps the 400px column readable and puts the
|
|
2399
|
+
// primary action (提交) in the same surface as the text it sends.
|
|
2056
2400
|
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
|
-
|
|
2401
|
+
bodyChildren.push(h("div", { key: "commitCard", style: S.card }, [
|
|
2402
|
+
h("div", { key: "tools", style: S.rowTight }, [
|
|
2403
|
+
h("button", {
|
|
2404
|
+
key: "stage",
|
|
2405
|
+
type: "button",
|
|
2406
|
+
style: Object.assign({}, S.button, S.grow, busy !== null || noChanges ? S.buttonDisabled : null),
|
|
2407
|
+
disabled: busy !== null || noChanges,
|
|
2408
|
+
title: noChanges ? t("changes.none") : t("action.stage"),
|
|
2409
|
+
onClick: function () { store.act("stage", function () { return store.verbs.stage(state.cwd); }); }
|
|
2410
|
+
}, busy === "stage" ? t("busy.stage") : t("action.stage")),
|
|
2411
|
+
h("select", {
|
|
2412
|
+
key: "mode",
|
|
2413
|
+
style: Object.assign({}, S.select, S.grow, { maxWidth: "none" }),
|
|
2414
|
+
value: generateMode,
|
|
2415
|
+
disabled: busy !== null,
|
|
2416
|
+
title: t("generate.mode.title"),
|
|
2417
|
+
"aria-label": t("generate.mode.title"),
|
|
2418
|
+
onChange: function (event) { setGenerateMode(event.target.value); }
|
|
2419
|
+
}, [
|
|
2420
|
+
h("option", { key: "staged", value: "staged", style: OPTION_STYLE }, t("generate.mode.staged")),
|
|
2421
|
+
h("option", { key: "unstaged", value: "unstaged", style: OPTION_STYLE }, t("generate.mode.unstaged")),
|
|
2422
|
+
h("option", { key: "all", value: "all", style: OPTION_STYLE }, t("generate.mode.all"))
|
|
2423
|
+
]),
|
|
2424
|
+
h("button", {
|
|
2425
|
+
key: "generate",
|
|
2426
|
+
type: "button",
|
|
2427
|
+
style: Object.assign({}, S.button, S.grow, busy !== null || noChanges ? S.buttonDisabled : null),
|
|
2428
|
+
disabled: busy !== null || noChanges,
|
|
2429
|
+
title: noChanges ? t("changes.none") : t("action.generate"),
|
|
2430
|
+
onClick: doGenerate
|
|
2431
|
+
}, busy === "generate" ? t("busy.generate") : "✨ " + t("action.generate"))
|
|
2078
2432
|
]),
|
|
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();
|
|
2433
|
+
h("div", { key: "message", style: S.rowTight }, [
|
|
2434
|
+
h("textarea", {
|
|
2435
|
+
key: "msg",
|
|
2436
|
+
rows: 2,
|
|
2437
|
+
style: S.textarea,
|
|
2438
|
+
value: message,
|
|
2439
|
+
placeholder: t("commit.placeholder"),
|
|
2440
|
+
disabled: busy !== null,
|
|
2441
|
+
onChange: function (event) { setMessage(event.target.value); },
|
|
2442
|
+
// Enter inserts a newline (a message may have a body); the
|
|
2443
|
+
// explicit commit chord is Ctrl/Cmd+Enter.
|
|
2444
|
+
onKeyDown: function (event) {
|
|
2445
|
+
if (event.key === "Enter" && (event.ctrlKey || event.metaKey) && message.trim() !== "" && busy === null) {
|
|
2446
|
+
event.preventDefault();
|
|
2447
|
+
doCommit();
|
|
2448
|
+
}
|
|
2104
2449
|
}
|
|
2105
|
-
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2450
|
+
}),
|
|
2451
|
+
h("button", {
|
|
2452
|
+
key: "commit",
|
|
2453
|
+
type: "button",
|
|
2454
|
+
style: Object.assign({}, S.buttonPrimary, { alignSelf: "flex-end", padding: "0 14px" }, busy !== null || message.trim() === "" ? S.buttonDisabled : null),
|
|
2455
|
+
disabled: busy !== null || message.trim() === "",
|
|
2456
|
+
title: message.trim() === "" ? t("commit.empty") : undefined,
|
|
2457
|
+
onClick: doCommit
|
|
2458
|
+
}, busy === "commit" ? t("busy.commit") : t("action.commit"))
|
|
2459
|
+
])
|
|
2115
2460
|
]));
|
|
2116
2461
|
|
|
2117
2462
|
function doCommit() {
|
|
@@ -2141,7 +2486,26 @@ window.__ModuleLoader__.load({
|
|
|
2141
2486
|
};
|
|
2142
2487
|
var text = known[details.code];
|
|
2143
2488
|
if (text === undefined) {
|
|
2144
|
-
|
|
2489
|
+
// Unknown code (a transport failure, a provider rejection,
|
|
2490
|
+
// …): lead with the localized sentence, keep the host's
|
|
2491
|
+
// own words as the diagnosis, and name the route that
|
|
2492
|
+
// failed — "which provider is broken" is the actionable
|
|
2493
|
+
// part when a gateway refuses the call.
|
|
2494
|
+
var detail = res && res.error && res.error.message ? String(res.error.message) : "";
|
|
2495
|
+
var failedRoute = details.provider && details.model
|
|
2496
|
+
? { provider: details.provider, model: details.model }
|
|
2497
|
+
: null;
|
|
2498
|
+
if (detail === "") {
|
|
2499
|
+
text = t("generate.failed");
|
|
2500
|
+
} else if (failedRoute !== null) {
|
|
2501
|
+
text = t("generate.failedRoute", {
|
|
2502
|
+
message: shortText(detail, 160),
|
|
2503
|
+
provider: failedRoute.provider,
|
|
2504
|
+
model: failedRoute.model
|
|
2505
|
+
});
|
|
2506
|
+
} else {
|
|
2507
|
+
text = t("generate.failedDetail", { message: shortText(detail, 160) });
|
|
2508
|
+
}
|
|
2145
2509
|
}
|
|
2146
2510
|
return { kind: "error", text: text };
|
|
2147
2511
|
}
|
|
@@ -2154,7 +2518,8 @@ window.__ModuleLoader__.load({
|
|
|
2154
2518
|
state.cwd,
|
|
2155
2519
|
generateMode,
|
|
2156
2520
|
route ? route.provider : undefined,
|
|
2157
|
-
route ? route.model : undefined
|
|
2521
|
+
route ? route.model : undefined,
|
|
2522
|
+
state.sessionId === null ? undefined : state.sessionId
|
|
2158
2523
|
);
|
|
2159
2524
|
}, describeGenerate).then(function (res) {
|
|
2160
2525
|
if (res && res.ok === true && res.value && res.value.message) {
|
|
@@ -2163,79 +2528,67 @@ window.__ModuleLoader__.load({
|
|
|
2163
2528
|
});
|
|
2164
2529
|
}
|
|
2165
2530
|
|
|
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
|
-
}
|
|
2531
|
+
// changes (one row per file) — the diff viewer's navigation:
|
|
2532
|
+
// clicking a row opens that file's diff on the right. The chip
|
|
2533
|
+
// trails the path so paths line up in one column and the eye can
|
|
2534
|
+
// scan them; the status only has to say which kind of change it is.
|
|
2535
|
+
var changesRows = state.changes.map(function (change, index) {
|
|
2536
|
+
var file = change.file !== undefined ? change.file : change.path;
|
|
2537
|
+
var origFile = change.origFile !== undefined ? change.origFile : null;
|
|
2538
|
+
var isActive = selected !== null && selected.file === file && selected.origFile === origFile;
|
|
2539
|
+
return h("div", {
|
|
2540
|
+
key: index,
|
|
2541
|
+
style: isActive ? S.changeRowActive : S.changeRow,
|
|
2542
|
+
role: "button",
|
|
2543
|
+
tabIndex: 0,
|
|
2544
|
+
title: change.path,
|
|
2545
|
+
"aria-label": t("diff.open") + " " + change.path,
|
|
2546
|
+
"data-dsh-git": "change-row",
|
|
2547
|
+
"data-active": isActive === true ? "true" : "false",
|
|
2548
|
+
onClick: function () { selectChange(change); },
|
|
2549
|
+
onKeyDown: function (event) {
|
|
2550
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
2551
|
+
if (event.preventDefault) event.preventDefault();
|
|
2552
|
+
selectChange(change);
|
|
2192
2553
|
}
|
|
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));
|
|
2554
|
+
}
|
|
2555
|
+
}, [
|
|
2556
|
+
h("span", { key: "path", style: S.changePath }, change.path),
|
|
2557
|
+
h("span", { key: "tag", style: changeTagStyle(change.status) }, t("status." + change.status))
|
|
2558
|
+
]);
|
|
2559
|
+
});
|
|
2560
|
+
bodyChildren.push(sectionView({
|
|
2561
|
+
hook: "changes",
|
|
2562
|
+
label: t("changes.title"),
|
|
2563
|
+
count: state.changes.length,
|
|
2564
|
+
open: changesOpen,
|
|
2565
|
+
all: changesAll,
|
|
2566
|
+
cap: CHANGES_PREVIEW,
|
|
2567
|
+
empty: "✓ " + t("changes.none"),
|
|
2568
|
+
rows: changesRows,
|
|
2569
|
+
onToggle: function () { setChangesOpen(!changesOpen); },
|
|
2570
|
+
onMore: function () { setChangesAll(!changesAll); }
|
|
2571
|
+
}, t));
|
|
2572
|
+
|
|
2573
|
+
// recent commits — same card, one row per commit
|
|
2574
|
+
var logRows = state.commits.map(function (commit, index) {
|
|
2575
|
+
return h("div", { key: index, style: S.logRow, title: commit.subject }, [
|
|
2576
|
+
h("span", { key: "sha", style: S.logSha }, commit.sha),
|
|
2577
|
+
h("span", { key: "subj", style: S.logSubject }, commit.subject)
|
|
2578
|
+
]);
|
|
2579
|
+
});
|
|
2580
|
+
bodyChildren.push(sectionView({
|
|
2581
|
+
hook: "log",
|
|
2582
|
+
label: t("log.title"),
|
|
2583
|
+
count: state.commits.length,
|
|
2584
|
+
open: logOpen,
|
|
2585
|
+
all: logAll,
|
|
2586
|
+
cap: LOG_PREVIEW,
|
|
2587
|
+
empty: t("log.none"),
|
|
2588
|
+
rows: logRows,
|
|
2589
|
+
onToggle: function () { setLogOpen(!logOpen); },
|
|
2590
|
+
onMore: function () { setLogAll(!logAll); }
|
|
2591
|
+
}, t));
|
|
2239
2592
|
}
|
|
2240
2593
|
|
|
2241
2594
|
// Everything the open diff depends on, as one comparable string: a
|
|
@@ -2345,7 +2698,8 @@ window.__ModuleLoader__.load({
|
|
|
2345
2698
|
? true
|
|
2346
2699
|
: (summary.retainedBy.mainView || 0) > 0;
|
|
2347
2700
|
|
|
2348
|
-
// Classic subscription pattern (see GitFloatingPanel
|
|
2701
|
+
// Classic subscription pattern (see GitFloatingPanel's note: keep this
|
|
2702
|
+
// store independent of the seed's useSyncExternalStore build).
|
|
2349
2703
|
var stateRef = React.useState(function () { return store.getSnapshot(); });
|
|
2350
2704
|
var state = stateRef[0];
|
|
2351
2705
|
var setState = stateRef[1];
|
|
@@ -2381,17 +2735,22 @@ window.__ModuleLoader__.load({
|
|
|
2381
2735
|
}
|
|
2382
2736
|
|
|
2383
2737
|
// Left-aligned compact pill in the row band ABOVE the composer card
|
|
2384
|
-
// (conversation.input.dock). The
|
|
2385
|
-
// card's
|
|
2386
|
-
//
|
|
2738
|
+
// (conversation.input.dock). The row box is capped at the composer
|
|
2739
|
+
// card's own width and centered — the same way ui-conversation's own
|
|
2740
|
+
// dock occupant (QueueDock) aligns itself — so the pill hugs the
|
|
2741
|
+
// textarea's top-left corner instead of floating at the conversation
|
|
2742
|
+
// column's edge. `--dsh-composer-card-max-width` is ui-conversation's
|
|
2743
|
+
// internal variable (no published contract, and 0.1.7 added a second
|
|
2744
|
+
// value for the embedded body); the 778px fallback keeps this row sane
|
|
2745
|
+
// if it is ever renamed.
|
|
2387
2746
|
return h("div", {
|
|
2388
2747
|
style: {
|
|
2389
2748
|
boxSizing: "border-box",
|
|
2390
2749
|
display: "flex",
|
|
2391
2750
|
justifyContent: "flex-start",
|
|
2392
2751
|
width: "100%",
|
|
2393
|
-
|
|
2394
|
-
margin: "2px
|
|
2752
|
+
maxWidth: "var(--dsh-composer-card-max-width, 778px)",
|
|
2753
|
+
margin: "2px auto"
|
|
2395
2754
|
},
|
|
2396
2755
|
"data-dsh-git": "dock-row"
|
|
2397
2756
|
}, h("button", {
|
|
@@ -2403,7 +2762,7 @@ window.__ModuleLoader__.load({
|
|
|
2403
2762
|
maxWidth: 220,
|
|
2404
2763
|
padding: "1px 10px",
|
|
2405
2764
|
borderRadius: 999,
|
|
2406
|
-
border: "1px solid var(--dsw-alias-
|
|
2765
|
+
border: "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.25))",
|
|
2407
2766
|
background: "var(--dsw-alias-bg-layer-1, rgba(127,127,127,0.12))",
|
|
2408
2767
|
color: "var(--dsw-alias-label-secondary, #c8ccd2)",
|
|
2409
2768
|
font: "inherit",
|
|
@@ -2472,7 +2831,12 @@ window.__ModuleLoader__.load({
|
|
|
2472
2831
|
GitDiffPane: GitDiffPane,
|
|
2473
2832
|
DIFF_ROW: DIFF_ROW,
|
|
2474
2833
|
stripAnsiEscapes: stripAnsiEscapes,
|
|
2475
|
-
outputView: outputView
|
|
2834
|
+
outputView: outputView,
|
|
2835
|
+
sectionView: sectionView,
|
|
2836
|
+
changeTagStyle: changeTagStyle,
|
|
2837
|
+
panelBoxStyle: panelBoxStyle,
|
|
2838
|
+
DIFF_PANEL_HEIGHT: DIFF_PANEL_HEIGHT,
|
|
2839
|
+
sessionModelRoute: sessionModelRoute
|
|
2476
2840
|
};
|
|
2477
2841
|
return module.exports;
|
|
2478
2842
|
}
|