dsh-gitbash-shell 0.30.0 → 0.30.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/CHANGELOG.md CHANGED
@@ -3,6 +3,49 @@
3
3
  > 倒序排列,新版本条目在最上面。条目格式:`## vX.Y.Z — YYYY-MM-DD` + 类型(feat / fix / docs / chore)+ 要点 + 相关链接。
4
4
  > 纪律见 AGENTS.md「变更记录纪律」:发版前先更新本文件并随版本提交;事故复盘、复现与真机验证记录也记在这里。
5
5
 
6
+ ## v0.30.1 — 2026-09-26
7
+
8
+ **类型**:fix(用户实测反馈 v0.30.0 的工具列表:点了按钮看不到进度、看不到在装哪一个、看不到报错、还能连点)
9
+
10
+ > 用户原话:**"我这点击升级了都不知道进度,有没有在升级,也看不到报错,你优化一下,可能看到目前按安装还是更新那个,进度条什么的放在那个列表里。然后不让我连点,开始了就不用再点。"**
11
+
12
+ ### 根因(两个都是真缺陷,不是用法问题)
13
+
14
+ 1. **busy 的生命周期错了**:`runTools()` 在 POST 收到 202 时就 `setToolBusy(false)`,而任务在**宿主侧继续跑**
15
+ —— 于是按钮在批次刚开始时就恢复可点。这正是"能连点"的来源:后端的单任务闸门确实会返回 409,
16
+ 但用户看到的是一个**亮着的按钮**,自然会再点。
17
+ 2. **进度放在了一个没人看的地方**:进度只渲染在按钮下方的一块区域,**不在工具列表行内**;
18
+ 每行也不显示自己的状态,失败原因混在一个游离的结果列表里,既不显眼也不对应行。
19
+
20
+ ### 改动(`src/client.js`)
21
+
22
+ - **busy 从「请求在飞」改为「任务在跑」**:新增派生状态 `jobRunning = toolJob && toolJob.finished !== true`
23
+ 与 `busyNow = toolBusy || jobRunning`;安装 / 刷新 / 全选三个按钮与**所有复选框**在整个批次期间禁用,
24
+ 主按钮文案变为「处理中」。开始之后不必也**不能**再点。
25
+ - **进度搬进列表行**:正在处理的那一行高亮,行内依次显示 spinner + **「安装中…」/「更新中…」**
26
+ (按该行 `state` 判断是装还是升,不靠猜)+ 一条扫动进度条;已完成的行保留 ✓/✗ 判定。
27
+ - **错误就地可见**:失败的行**正下方**用红字打印「安装中 — 失败: <winget 原文>」,不用再去别处找日志。
28
+ - **整体进度**:任务运行时显示 spinner + `当前工具 · 处理中: n / m` + 按完成数计算的进度条(宽度随 done/total 增长)。
29
+ - 移除原先那个游离的结果列表 —— 信息已全部进入对应行。
30
+ - 新增样式:行高亮、运行态徽章、行内扫动条、整体进度条、失败行、spinner,以及 `gb-spin` / `gb-slide` 两条 keyframes。
31
+ - 词典 **21 语言各补 2 键**(`tools.installing` / `tools.updating`),现共 **65 键**,键对齐由冒烟强制。
32
+
33
+ ### 验证
34
+
35
+ - `npm test` **112/112 全绿**(词典键对齐断言覆盖新键)。
36
+ - 静态校验:65 个词典键**全部**被代码引用,零悬空引用。
37
+ - ⚠️ 仍未做:浏览器端真机点击验证(需重启客户端后自测)。
38
+ - 版本号 `0.30.0` → **`0.30.1`**。
39
+
40
+ ### 附:一次误操作与回滚(如实记录)
41
+
42
+ 本次最初**误把第三方插件 `dshmarket` 当成了目标**,对
43
+ `~/.dsh/profiles/desktop/node_modules/dshmarket/client/client.js` 打了一处本地补丁(让自我更新时
44
+ dshmarket 自己出现在「已安装」列表里,以显示行内进度)。用户澄清后**已完整回滚**:
45
+ 与 npm 上的 `dshmarket@1.66.2` 逐字节 `cmp` 一致,零残留。
46
+ (该补丁对应的确实是一个真实缺陷 —— 自我更新按钮 `onClick` 会 `setTab("installed")` 想看进度,
47
+ 但列表又 `filter` 掉了 `selfName` —— 留作后续,未在本仓库处理。)
48
+
6
49
  ## v0.30.0 — 2026-09-26
7
50
 
8
51
  **类型**:feat(新能力 —— 设置卡里一键安装/升级一份**固定的终端工具清单**,全部经 winget 官方源)
package/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-gitbash-shell",
3
- "version": "0.30.0",
3
+ "version": "0.30.1",
4
4
  "main": "./src/index.js",
5
5
  "description": "Windows 全模式 Git Bash:用 Git for Windows bash 替换 PowerShell 执行器,并物化 standard/minimal/code/cordis 的 Git Bash 变体 preset。双 era 适配 dsh <= 0.1.1(内置 id 'code')与 >= 0.1.2(改名 'ptc'),启动探测自动选择,preset id 永不变。联动:dsh-ptc-cordis-preset(两者同装时 PTC 创造模式自动物化为 Git Bash 版)+ dsh-better-sidebar(终端 UI 标签与模型 terminal_* 工具自动切到 Git Bash)。",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-gitbash-shell",
3
- "version": "0.30.0",
3
+ "version": "0.30.1",
4
4
  "description": "Windows 上让 agent 的每条 shell 命令改经 Git for Windows bash 执行;物化四个内置预设的 Git Bash 变体,统一 MSYS 盘根路径方言,侧栏终端接管可开关。· Run every agent shell command through Git for Windows bash on Windows; materialize Git Bash variants of the built-in presets, unify the MSYS drive-root path dialect, and adopt the sidebar terminal behind a switch.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/client.js CHANGED
@@ -131,6 +131,8 @@ window.__ModuleLoader__.load({
131
131
  "tools.working": "处理中",
132
132
  "tools.resultOk": "成功",
133
133
  "tools.resultFail": "失败",
134
+ "tools.installing": "安装中…",
135
+ "tools.updating": "更新中…",
134
136
  };
135
137
 
136
138
  var en = {
@@ -197,6 +199,8 @@ window.__ModuleLoader__.load({
197
199
  "tools.working": "Working",
198
200
  "tools.resultOk": "succeeded",
199
201
  "tools.resultFail": "failed",
202
+ "tools.installing": "Installing…",
203
+ "tools.updating": "Updating…",
200
204
  };
201
205
 
202
206
  /* Third-language dictionaries: one entry per language, each preceded
@@ -273,6 +277,8 @@ window.__ModuleLoader__.load({
273
277
  "tools.working": "جارٍ العمل",
274
278
  "tools.resultOk": "نجح",
275
279
  "tools.resultFail": "فشل",
280
+ "tools.installing": "جارٍ التثبيت…",
281
+ "tools.updating": "جارٍ الترقية…",
276
282
  },
277
283
  /* locale: de */
278
284
  "de": {
@@ -339,6 +345,8 @@ window.__ModuleLoader__.load({
339
345
  "tools.working": "Läuft",
340
346
  "tools.resultOk": "erfolgreich",
341
347
  "tools.resultFail": "fehlgeschlagen",
348
+ "tools.installing": "Wird installiert…",
349
+ "tools.updating": "Wird aktualisiert…",
342
350
  },
343
351
  /* locale: fr */
344
352
  "fr": {
@@ -405,6 +413,8 @@ window.__ModuleLoader__.load({
405
413
  "tools.working": "En cours",
406
414
  "tools.resultOk": "réussi",
407
415
  "tools.resultFail": "échec",
416
+ "tools.installing": "Installation…",
417
+ "tools.updating": "Mise à jour…",
408
418
  },
409
419
  /* locale: hi */
410
420
  "hi": {
@@ -471,6 +481,8 @@ window.__ModuleLoader__.load({
471
481
  "tools.working": "चल रहा है",
472
482
  "tools.resultOk": "सफल",
473
483
  "tools.resultFail": "विफल",
484
+ "tools.installing": "इंस्टॉल हो रहा है…",
485
+ "tools.updating": "अपडेट हो रहा है…",
474
486
  },
475
487
  /* locale: id */
476
488
  "id": {
@@ -537,6 +549,8 @@ window.__ModuleLoader__.load({
537
549
  "tools.working": "Memproses",
538
550
  "tools.resultOk": "berhasil",
539
551
  "tools.resultFail": "gagal",
552
+ "tools.installing": "Memasang…",
553
+ "tools.updating": "Memperbarui…",
540
554
  },
541
555
  /* locale: it */
542
556
  "it": {
@@ -603,6 +617,8 @@ window.__ModuleLoader__.load({
603
617
  "tools.working": "In corso",
604
618
  "tools.resultOk": "riuscito",
605
619
  "tools.resultFail": "non riuscito",
620
+ "tools.installing": "Installazione…",
621
+ "tools.updating": "Aggiornamento…",
606
622
  },
607
623
  /* locale: ja */
608
624
  "ja": {
@@ -669,6 +685,8 @@ window.__ModuleLoader__.load({
669
685
  "tools.working": "処理中",
670
686
  "tools.resultOk": "成功",
671
687
  "tools.resultFail": "失敗",
688
+ "tools.installing": "インストール中…",
689
+ "tools.updating": "更新中…",
672
690
  },
673
691
  /* locale: ko */
674
692
  "ko": {
@@ -735,6 +753,8 @@ window.__ModuleLoader__.load({
735
753
  "tools.working": "처리 중",
736
754
  "tools.resultOk": "성공",
737
755
  "tools.resultFail": "실패",
756
+ "tools.installing": "설치 중…",
757
+ "tools.updating": "업데이트 중…",
738
758
  },
739
759
  /* locale: nl */
740
760
  "nl": {
@@ -801,6 +821,8 @@ window.__ModuleLoader__.load({
801
821
  "tools.working": "Bezig",
802
822
  "tools.resultOk": "geslaagd",
803
823
  "tools.resultFail": "mislukt",
824
+ "tools.installing": "Installeren…",
825
+ "tools.updating": "Bijwerken…",
804
826
  },
805
827
  /* locale: pl */
806
828
  "pl": {
@@ -867,6 +889,8 @@ window.__ModuleLoader__.load({
867
889
  "tools.working": "Przetwarzanie",
868
890
  "tools.resultOk": "sukces",
869
891
  "tools.resultFail": "niepowodzenie",
892
+ "tools.installing": "Instalowanie…",
893
+ "tools.updating": "Aktualizowanie…",
870
894
  },
871
895
  /* locale: pt */
872
896
  "pt": {
@@ -933,6 +957,8 @@ window.__ModuleLoader__.load({
933
957
  "tools.working": "A processar",
934
958
  "tools.resultOk": "com êxito",
935
959
  "tools.resultFail": "falhou",
960
+ "tools.installing": "A instalar…",
961
+ "tools.updating": "A atualizar…",
936
962
  },
937
963
  /* locale: ru */
938
964
  "ru": {
@@ -999,6 +1025,8 @@ window.__ModuleLoader__.load({
999
1025
  "tools.working": "Выполняется",
1000
1026
  "tools.resultOk": "успешно",
1001
1027
  "tools.resultFail": "ошибка",
1028
+ "tools.installing": "Установка…",
1029
+ "tools.updating": "Обновление…",
1002
1030
  },
1003
1031
  /* locale: sv */
1004
1032
  "sv": {
@@ -1065,6 +1093,8 @@ window.__ModuleLoader__.load({
1065
1093
  "tools.working": "Arbetar",
1066
1094
  "tools.resultOk": "lyckades",
1067
1095
  "tools.resultFail": "misslyckades",
1096
+ "tools.installing": "Installerar…",
1097
+ "tools.updating": "Uppdaterar…",
1068
1098
  },
1069
1099
  /* locale: th */
1070
1100
  "th": {
@@ -1131,6 +1161,8 @@ window.__ModuleLoader__.load({
1131
1161
  "tools.working": "กำลังดำเนินการ",
1132
1162
  "tools.resultOk": "สำเร็จ",
1133
1163
  "tools.resultFail": "ล้มเหลว",
1164
+ "tools.installing": "กำลังติดตั้ง…",
1165
+ "tools.updating": "กำลังอัปเกรด…",
1134
1166
  },
1135
1167
  /* locale: tr */
1136
1168
  "tr": {
@@ -1197,6 +1229,8 @@ window.__ModuleLoader__.load({
1197
1229
  "tools.working": "İşleniyor",
1198
1230
  "tools.resultOk": "başarılı",
1199
1231
  "tools.resultFail": "başarısız",
1232
+ "tools.installing": "Kuruluyor…",
1233
+ "tools.updating": "Güncelleniyor…",
1200
1234
  },
1201
1235
  /* locale: vi */
1202
1236
  "vi": {
@@ -1263,6 +1297,8 @@ window.__ModuleLoader__.load({
1263
1297
  "tools.working": "Đang xử lý",
1264
1298
  "tools.resultOk": "thành công",
1265
1299
  "tools.resultFail": "thất bại",
1300
+ "tools.installing": "Đang cài…",
1301
+ "tools.updating": "Đang nâng cấp…",
1266
1302
  },
1267
1303
  /* locale: zh-hk */
1268
1304
  "zh-hk": {
@@ -1329,6 +1365,8 @@ window.__ModuleLoader__.load({
1329
1365
  "tools.working": "處理緊",
1330
1366
  "tools.resultOk": "成功",
1331
1367
  "tools.resultFail": "失敗",
1368
+ "tools.installing": "安裝緊…",
1369
+ "tools.updating": "升級緊…",
1332
1370
  },
1333
1371
  /* locale: zh-mo */
1334
1372
  "zh-mo": {
@@ -1395,6 +1433,8 @@ window.__ModuleLoader__.load({
1395
1433
  "tools.working": "處理緊",
1396
1434
  "tools.resultOk": "成功",
1397
1435
  "tools.resultFail": "失敗",
1436
+ "tools.installing": "安裝緊…",
1437
+ "tools.updating": "升級緊…",
1398
1438
  },
1399
1439
  /* locale: zh-tw */
1400
1440
  "zh-tw": {
@@ -1461,6 +1501,8 @@ window.__ModuleLoader__.load({
1461
1501
  "tools.working": "處理中",
1462
1502
  "tools.resultOk": "成功",
1463
1503
  "tools.resultFail": "失敗",
1504
+ "tools.installing": "安裝中…",
1505
+ "tools.updating": "更新中…",
1464
1506
  },
1465
1507
  };
1466
1508
 
@@ -1581,6 +1623,21 @@ window.__ModuleLoader__.load({
1581
1623
  ".gb-ok{flex:none;color:var(--dsw-alias-state-success-primary,#3fb950)}",
1582
1624
  ".gb-bad{flex:none;color:var(--dsw-alias-status-danger,#e5484d)}",
1583
1625
  ".gb-segBtn:disabled{opacity:.45;cursor:default}",
1626
+ /* in-list progress (v0.30.1): the row being installed/upgraded shows a
1627
+ spinner, its action, and a sweeping bar; finished rows keep their
1628
+ verdict, and a failure prints its reason under the row. */
1629
+ ".gb-toolRow.gb-rowActive{border-radius:6px;background:var(--dsw-alias-bg-layer-2,transparent)}",
1630
+ ".gb-toolState.gb-st-running{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary);display:inline-flex;align-items:center;gap:5px}",
1631
+ ".gb-st-ok{border-color:var(--dsw-alias-state-success-primary,#3fb950);color:var(--dsw-alias-state-success-primary,#3fb950)}",
1632
+ ".gb-st-fail{border-color:var(--dsw-alias-status-danger,#e5484d);color:var(--dsw-alias-status-danger,#e5484d)}",
1633
+ ".gb-spin{flex:none;display:inline-block;width:10px;height:10px;border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-brand-primary);border-radius:50%;animation:gb-spin .8s linear infinite}",
1634
+ ".gb-toolBar{flex:1 1 auto;min-width:32px;height:4px;border-radius:2px;background:var(--dsw-alias-border-l2);overflow:hidden}",
1635
+ ".gb-toolBarFill{display:block;height:100%;width:38%;border-radius:2px;background:var(--dsw-alias-brand-primary);animation:gb-slide 1.15s ease-in-out infinite}",
1636
+ ".gb-jobBar{height:6px;border-radius:3px;background:var(--dsw-alias-border-l2);overflow:hidden}",
1637
+ ".gb-jobBarFill{display:block;height:100%;border-radius:3px;background:var(--dsw-alias-brand-primary);transition:width .3s ease}",
1638
+ ".gb-toolFail{margin:0 0 4px 26px;font-size:11.5px;line-height:1.5;color:var(--dsw-alias-status-danger,#e5484d);overflow-wrap:anywhere}",
1639
+ "@keyframes gb-spin{to{transform:rotate(360deg)}}",
1640
+ "@keyframes gb-slide{0%{margin-left:-38%}100%{margin-left:100%}}",
1584
1641
  ].join("\n");
1585
1642
 
1586
1643
  function ensureStyles() {
@@ -2027,8 +2084,23 @@ window.__ModuleLoader__.load({
2027
2084
  even be ticked, so an upgrade can never touch it. */
2028
2085
  var toolRows = toolsData !== null && Array.isArray(toolsData.tools) ? toolsData.tools : [];
2029
2086
  var wingetOk = !!(toolsData !== null && toolsData.winget && toolsData.winget.ok);
2087
+ /* The job lives on the HOST and keeps running long after the POST has
2088
+ returned, so "busy" must be derived from the JOB, not from the request.
2089
+ Keying the buttons off the POST alone re-enabled them the instant the
2090
+ host answered 202 — which is precisely how a second click could land on
2091
+ an already-running batch. */
2092
+ var jobRunning = toolJob !== null && toolJob.finished !== true;
2093
+ var busyNow = toolBusy || jobRunning;
2094
+ var jobById = {};
2095
+ if (toolJob !== null && Array.isArray(toolJob.results)) {
2096
+ toolJob.results.forEach(function (entry) {
2097
+ if (entry !== null && typeof entry === "object" && typeof entry.id === "string") jobById[entry.id] = entry;
2098
+ });
2099
+ }
2100
+ var activeCmd = jobRunning && typeof toolJob.current === "string" ? toolJob.current : "";
2101
+ var jobPct = jobRunning && toolJob.total > 0 ? Math.round(toolJob.done / toolJob.total * 100) : 0;
2030
2102
  function toolSelectable(row) {
2031
- return wingetOk && !toolBusy && (row.state === "missing" || row.state === "managed");
2103
+ return wingetOk && !busyNow && (row.state === "missing" || row.state === "managed");
2032
2104
  }
2033
2105
  var toolSelCount = toolRows.filter(function (row) { return toolSel[row.id] === true; }).length;
2034
2106
 
@@ -2126,8 +2198,31 @@ window.__ModuleLoader__.load({
2126
2198
  toolErr !== "" ? E("p", { className: "gb-error" }, toolErr) : null,
2127
2199
  toolsData !== null && !wingetOk ? E("p", { className: "gb-error" }, t("tools.nowinget")) : null,
2128
2200
  toolRows.length > 0 ? E("div", { className: "gb-tools" },
2129
- toolRows.map(function (row) {
2130
- return E("label", { key: row.id, className: "gb-toolRow", title: row.publisher + " · " + row.source },
2201
+ /* ONE row per tool, and the row itself carries the progress: the
2202
+ tool being worked on shows a spinner, whether it is being
2203
+ installed or upgraded, and a sweeping bar; a finished tool keeps
2204
+ its verdict; a failure prints its reason directly underneath, so
2205
+ nothing has to be hunted for in a separate log area. */
2206
+ toolRows.reduce(function (acc, row) {
2207
+ var entry = jobById[row.id];
2208
+ var active = activeCmd !== "" && activeCmd === row.cmd;
2209
+ var isUpgrade = row.state === "managed";
2210
+ var badge;
2211
+ if (active) {
2212
+ badge = E("span", { className: "gb-toolState gb-st-running" },
2213
+ E("span", { className: "gb-spin" }),
2214
+ t(isUpgrade ? "tools.updating" : "tools.installing"));
2215
+ } else if (entry !== undefined) {
2216
+ badge = E("span", { className: "gb-toolState " + (entry.ok ? "gb-st-ok" : "gb-st-fail") },
2217
+ (entry.ok ? "✓ " : "✗ ") + t(entry.ok ? "tools.resultOk" : "tools.resultFail"));
2218
+ } else {
2219
+ badge = E("span", { className: "gb-toolState gb-st-" + row.state }, t("tools.state." + row.state));
2220
+ }
2221
+ acc.push(E("label", {
2222
+ key: row.id,
2223
+ className: "gb-toolRow" + (active ? " gb-rowActive" : ""),
2224
+ title: row.publisher + " · " + row.source,
2225
+ },
2131
2226
  E("input", {
2132
2227
  type: "checkbox",
2133
2228
  checked: toolSel[row.id] === true,
@@ -2135,27 +2230,39 @@ window.__ModuleLoader__.load({
2135
2230
  onChange: function () { toggleTool(row.id); },
2136
2231
  }),
2137
2232
  E("span", { className: "gb-toolCmd" }, row.cmd),
2138
- E("span", { className: "gb-toolState gb-st-" + row.state }, t("tools.state." + row.state)),
2233
+ badge,
2234
+ active ? E("span", { className: "gb-toolBar" }, E("span", { className: "gb-toolBarFill" })) : null,
2139
2235
  E("span", { className: "gb-toolSrc" }, (row.version !== "" ? row.version + " · " : "") + (row.provider !== "" ? row.provider : row.source) + (row.admin ? " · " + t("tools.adminHint") : "")),
2140
- );
2141
- }),
2236
+ ));
2237
+ if (entry !== undefined && entry.ok !== true) {
2238
+ acc.push(E("p", { key: row.id + ":fail", className: "gb-toolFail" },
2239
+ t(entry.action === "upgrade" ? "tools.updating" : "tools.installing") + " — " + t("tools.resultFail") + ": " + (entry.detail || "")));
2240
+ }
2241
+ return acc;
2242
+ }, []),
2142
2243
  ) : null,
2143
2244
  toolsData !== null && wingetOk ? E("div", { className: "gb-seg" },
2144
- E("button", { type: "button", className: "gb-segBtn", disabled: toolBusy, onClick: function () { loadTools(); } }, t("tools.refresh")),
2145
- E("button", { type: "button", className: "gb-segBtn", disabled: toolBusy, onClick: selectInstallable }, t("tools.selectMissing")),
2146
- E("button", { type: "button", className: "gb-segBtn" + (toolSelCount > 0 ? " gb-segActive" : ""), disabled: toolBusy || toolSelCount === 0, onClick: runTools }, t("tools.run")),
2245
+ E("button", { type: "button", className: "gb-segBtn", disabled: busyNow, onClick: function () { loadTools(); } }, t("tools.refresh")),
2246
+ E("button", { type: "button", className: "gb-segBtn", disabled: busyNow, onClick: selectInstallable }, t("tools.selectMissing")),
2247
+ /* A running job DISABLES this button and says so — the host keeps
2248
+ working after the POST returns, so re-enabling on the response
2249
+ would invite a second click onto a batch already in flight. */
2250
+ E("button", {
2251
+ type: "button",
2252
+ className: "gb-segBtn" + (toolSelCount > 0 && !busyNow ? " gb-segActive" : ""),
2253
+ disabled: busyNow || toolSelCount === 0,
2254
+ onClick: runTools,
2255
+ }, busyNow ? t("tools.working") : t("tools.run")),
2147
2256
  ) : null,
2148
- toolJob !== null ? E("div", { className: "gb-stack" },
2257
+ jobRunning ? E("div", { className: "gb-stack" },
2149
2258
  E("div", { className: "gb-row" },
2150
- E("span", { className: "gb-rowLabel" }, t("tools.working") + ":"),
2151
- E("span", { className: "gb-rowValue" }, (toolJob.current ? toolJob.current + " " : "") + toolJob.done + " / " + toolJob.total),
2259
+ E("span", { className: "gb-spin" }),
2260
+ E("span", { className: "gb-rowLabel" }, (activeCmd !== "" ? activeCmd + " · " : "") + t("tools.working") + ":"),
2261
+ E("span", { className: "gb-rowValue" }, toolJob.done + " / " + toolJob.total),
2262
+ ),
2263
+ E("div", { className: "gb-jobBar" },
2264
+ E("div", { className: "gb-jobBarFill", style: { width: jobPct + "%" } }),
2152
2265
  ),
2153
- (toolJob.results || []).map(function (item) {
2154
- return E("div", { key: item.id, className: "gb-toolResult" },
2155
- E("span", { className: item.ok ? "gb-ok" : "gb-bad" }, item.cmd + " " + t(item.ok ? "tools.resultOk" : "tools.resultFail")),
2156
- E("span", null, item.detail || ""),
2157
- );
2158
- }),
2159
2266
  ) : null,
2160
2267
  E("p", { className: "gb-hint" }, t("tools.hint")),
2161
2268
  ),