dsh-life-pack 0.3.18 → 0.3.20
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/dist/client.js +83 -84
- package/dist/client.js.map +1 -1
- package/dist/desktop-install.d.ts +29 -0
- package/dist/desktop-install.d.ts.map +1 -0
- package/dist/desktop-install.js +42 -0
- package/dist/desktop-install.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/manager-version.d.ts +1 -7
- package/dist/manager-version.d.ts.map +1 -1
- package/dist/manager-version.js +10 -29
- package/dist/manager-version.js.map +1 -1
- package/dist/nav.d.ts +4 -4
- package/dist/nav.d.ts.map +1 -1
- package/dist/nav.js +4 -4
- package/dist/nav.js.map +1 -1
- package/dist/update-client.d.ts +0 -5
- package/dist/update-client.d.ts.map +1 -1
- package/dist/update-client.js +7 -16
- package/dist/update-client.js.map +1 -1
- package/dist/update-contract.d.ts +4 -12
- package/dist/update-contract.d.ts.map +1 -1
- package/dist/update-contract.js +3 -11
- package/dist/update-contract.js.map +1 -1
- package/dist/update-host.d.ts +87 -2
- package/dist/update-host.d.ts.map +1 -1
- package/dist/update-host.js +167 -40
- package/dist/update-host.js.map +1 -1
- package/dist/update-view.d.ts +20 -0
- package/dist/update-view.d.ts.map +1 -1
- package/dist/update-view.js +26 -0
- package/dist/update-view.js.map +1 -1
- package/package.json +2 -2
package/dist/client.js
CHANGED
|
@@ -174,12 +174,6 @@ window.__ModuleLoader__.load({
|
|
|
174
174
|
* 也不该把名字再写一份(写两份必然走散)。宿主把名字表连同版本行一起交出去,
|
|
175
175
|
* 面板一行字面量都不留。 */
|
|
176
176
|
targets: "ilife-manager.targets",
|
|
177
|
-
/** 总管自述版本(票 #737):入参 `{}`,回包 `{version}`。
|
|
178
|
-
*
|
|
179
|
-
* 宿主读**自己这份已安装包**的 `package.json`(`manager-version.ts`),面板只渲染读到的值。
|
|
180
|
-
* 为什么走电话:面板是浏览器产物,禁 node 内建(`test/client-bundle-48.test.mjs` 看门),
|
|
181
|
-
* 读盘只许在宿主半;与卡路里 #130 同一条路(host 读 → RPC → client 纯渲染)。 */
|
|
182
|
-
version: "ilife-manager.version",
|
|
183
177
|
/** 本机「根」清单(票 #744):入参 `{}`,回包 `{roots: [{path, kind}]}`。
|
|
184
178
|
*
|
|
185
179
|
* 为什么这条能力住在总管:浏览器里没有卷清单接口,而宿主那条目录选择接缝只有
|
|
@@ -188,15 +182,9 @@ window.__ModuleLoader__.load({
|
|
|
188
182
|
* 回包**恒成功**:列不出来是空清单,不是错误码(界面据此只是不画那一行)。 */
|
|
189
183
|
roots: "ilife-manager.roots"
|
|
190
184
|
};
|
|
191
|
-
/** 版本读不到时两侧共用的降级字面量(面板照原样显示,不假装知道版本)。
|
|
192
|
-
*
|
|
193
|
-
* 一处定义、两侧引用:宿主半 `manager-version.ts` 读失败时回它,面板半 `update-client.ts`
|
|
194
|
-
* 归一化时也认它——面板侧不许 import 宿主半(会把 node 内建带进浏览器束)。 */
|
|
195
|
-
const VERSION_UNKNOWN = "unknown";
|
|
196
185
|
/** 挂载取数失败的退避重试表(票 #982,更新目标表用)。
|
|
197
186
|
*
|
|
198
|
-
*
|
|
199
|
-
* (宿主路由尚未就绪)会使错误态常驻整个会话;单次直返是当时的缺口。
|
|
187
|
+
* 挂载时首次传输失败(宿主路由尚未就绪)会使错误态常驻整个会话;单次直返是当时的缺口。
|
|
200
188
|
* 次数有界、调用方负责卸载清理(见 `update-panel.ts` 的取数),不是无界轮询。 */
|
|
201
189
|
const LOAD_RETRY_MS = [
|
|
202
190
|
1e3,
|
|
@@ -237,15 +225,17 @@ window.__ModuleLoader__.load({
|
|
|
237
225
|
}
|
|
238
226
|
//#endregion
|
|
239
227
|
//#region src/update-client.ts
|
|
240
|
-
/**
|
|
228
|
+
/** 面板到宿主的三条流程(纯异步函数:无 DOM、无 react;传输口由调用方注入,便于单测)。
|
|
241
229
|
*
|
|
242
|
-
*
|
|
230
|
+
* 三条流程与更新包 README 的对应关系:
|
|
243
231
|
* - 检查更新:`updateCheck`(第 3 节第 3 步的 `host.call(UPD_CHECK, {})`);
|
|
244
232
|
* - 装上更新:`updateCheck` 拿凭证 → `updateInstall` 提交 → **按间隔轮询 `updateStatus`**
|
|
245
233
|
* 直到任务离开 `installing`/`verifying`(第 3 节第 3 步与第 9 节:安装是后台跑,
|
|
246
234
|
* 调用方不干等;凭证过期 `check-expired` 是正常错误码,重查一次再提交,见第 11 节);
|
|
247
|
-
* - 装上缺席的包:走总管自有的 `ilife-manager.install
|
|
248
|
-
*
|
|
235
|
+
* - 装上缺席的包:走总管自有的 `ilife-manager.install`(更新包的三个电话只管已装的包)。
|
|
236
|
+
*
|
|
237
|
+
* 版本号**不在这三条里**(票 #986):面板那行版本由构建期注入产物(见 `client.ts`),
|
|
238
|
+
* 不再经 `ilife-manager.version` 往返——标签的延迟不依赖宿主可用性。
|
|
249
239
|
*/
|
|
250
240
|
/** 轮询上限:1 秒一次、最多 900 次(覆盖更新包 15 分钟的安装时限)。 */
|
|
251
241
|
const MAX_POLL_TRIES = 900;
|
|
@@ -323,16 +313,6 @@ window.__ModuleLoader__.load({
|
|
|
323
313
|
}
|
|
324
314
|
};
|
|
325
315
|
}
|
|
326
|
-
/** 取总管自述版本(票 #737):宿主读**自己这份已安装包**的 `package.json`,面板只渲染读到的值。
|
|
327
|
-
*
|
|
328
|
-
* 单次、无轮询;宿主读不到会回 `unknown`,传输层失败也回同一个字面量——面板照原样显示,
|
|
329
|
-
* 不假装知道版本(与卡路里 #130 的降级口径一致)。 */
|
|
330
|
-
async function loadManagerVersion(call) {
|
|
331
|
-
const out = await callManager(call, MANAGER_ACTIONS.version, {});
|
|
332
|
-
if (!out.ok) return VERSION_UNKNOWN;
|
|
333
|
-
const raw = out.value?.version;
|
|
334
|
-
return typeof raw === "string" && raw.trim().length > 0 ? raw.trim() : VERSION_UNKNOWN;
|
|
335
|
-
}
|
|
336
316
|
/** 查一家:默认查新版(`updateCheck`,顺带回最新版本与凭证);给 `phoneName` 时查那个电话。 */
|
|
337
317
|
async function checkTarget(call, target, phoneName) {
|
|
338
318
|
const name = phoneName ?? target.phones?.check;
|
|
@@ -555,6 +535,29 @@ window.__ModuleLoader__.load({
|
|
|
555
535
|
if (typeof raw === "string" && raw.length > 0) return failure.code + " detail=" + raw.slice(0, 300);
|
|
556
536
|
return failure.code;
|
|
557
537
|
}
|
|
538
|
+
/** 失败原文那一行(票 #988):宿主回包 `details.detail` 里那句人话,面板把它摊在原因句下面。
|
|
539
|
+
*
|
|
540
|
+
* 为什么要摊:`install-failed` 这句人话对每一种装不上都长一个样,光看它分不出「这个宿主没有安装出口」
|
|
541
|
+
* 与「pnpm 退出码非零」。原文由宿主半取好并回传(`update-host.ts` 的 `installErrorDetail`),
|
|
542
|
+
* 这里只取值与截断(长文本会撑爆那一行)。没有原文回 null——面板不自己编原因。 */
|
|
543
|
+
function failureDetailOf(failure) {
|
|
544
|
+
const raw = failure?.details?.detail;
|
|
545
|
+
if (typeof raw !== "string") return null;
|
|
546
|
+
const text = raw.trim();
|
|
547
|
+
return text.length === 0 ? null : text.slice(0, 300);
|
|
548
|
+
}
|
|
549
|
+
/** 题头两颗按钮的悬停标题(票 #986 第二半:目标表未就绪时说真因)。
|
|
550
|
+
*
|
|
551
|
+
* 住这里(不是面板组件旁边):标题口径只有一个定义地,面板与单测共用同一份;
|
|
552
|
+
* 忙时沿用 update-busy 原句(与禁用判据同源),未就绪且空闲时说「还在读更新目标」,
|
|
553
|
+
* 就绪后回到调用方给的动作说明(本函数不写死那两句动作说明,由调用方传入)。
|
|
554
|
+
*
|
|
555
|
+
* 入参只取判据形状(blocked 与 empty),不 import 面板钩子。 */
|
|
556
|
+
function headerButtonTitle(input) {
|
|
557
|
+
if (input.blocked) return reasonText("update-busy");
|
|
558
|
+
if (input.empty) return "还在读更新目标,稍候再试";
|
|
559
|
+
return input.readyText ?? "";
|
|
560
|
+
}
|
|
558
561
|
//#endregion
|
|
559
562
|
//#region src/update-queue.ts
|
|
560
563
|
/** 任一行 installing 即忙:题头检查更新禁用、行按钮全局互斥、checkAll/act 入口直接返回的同一判据。 */
|
|
@@ -921,6 +924,13 @@ window.__ModuleLoader__.load({
|
|
|
921
924
|
marginTop: 4
|
|
922
925
|
}
|
|
923
926
|
};
|
|
927
|
+
/** 失败原文那一块(票 #988):宿主回来的细节单放一个可复制块(`cmd` 样式带 `userSelect: all`,
|
|
928
|
+
* 点一下全选即拷走),不与可执行的手工命令拼在同一块里——拼一起用户会整块拷去终端敲。
|
|
929
|
+
* 两处失败行(结果行与缺席卡)共用这一块,口径一处。 */
|
|
930
|
+
function failureDetailCode(detail) {
|
|
931
|
+
if (!detail) return null;
|
|
932
|
+
return react.createElement("code", { style: PANEL_STYLE.cmd }, "宿主原话:" + detail);
|
|
933
|
+
}
|
|
924
934
|
const ROW_TONE = {
|
|
925
935
|
update: {
|
|
926
936
|
mark: "↑",
|
|
@@ -1053,6 +1063,10 @@ window.__ModuleLoader__.load({
|
|
|
1053
1063
|
react.useEffect(() => {
|
|
1054
1064
|
reload(true);
|
|
1055
1065
|
}, [reload]);
|
|
1066
|
+
/** 取数失败后的手动重试(票 #986 第二半):不依赖目标表,挂载那次的退避表复用。 */
|
|
1067
|
+
const retry = react.useCallback(() => {
|
|
1068
|
+
reload(true);
|
|
1069
|
+
}, [reload]);
|
|
1056
1070
|
const patch = react.useCallback((key, next) => {
|
|
1057
1071
|
setRows((previous) => ({
|
|
1058
1072
|
...previous,
|
|
@@ -1072,6 +1086,7 @@ window.__ModuleLoader__.load({
|
|
|
1072
1086
|
checking,
|
|
1073
1087
|
updatingAll,
|
|
1074
1088
|
open,
|
|
1089
|
+
retry,
|
|
1075
1090
|
close: () => setOpen(resolveDialogOpen("hide")),
|
|
1076
1091
|
showProgress: () => setOpen(resolveDialogOpen("show")),
|
|
1077
1092
|
checkAll: react.useCallback(() => {
|
|
@@ -1213,6 +1228,21 @@ window.__ModuleLoader__.load({
|
|
|
1213
1228
|
])
|
|
1214
1229
|
};
|
|
1215
1230
|
}
|
|
1231
|
+
/** 取数失败的出口卡(票 #986 第二半:失败必须有出口)。
|
|
1232
|
+
*
|
|
1233
|
+
* 纯组件(无钩子):错误原文+一颗可点的「重试」。重试不依赖目标表——
|
|
1234
|
+
* 目标表为空时两题头按钮仍禁用,但这颗可点;点它重走取数,成功后按钮与行恢复。
|
|
1235
|
+
*/
|
|
1236
|
+
function TargetsLoadError(props) {
|
|
1237
|
+
return react.createElement("div", { style: PANEL_STYLE.reason }, "更新能力没接上:" + props.message, react.createElement("button", {
|
|
1238
|
+
type: "button",
|
|
1239
|
+
style: {
|
|
1240
|
+
...PANEL_STYLE.btn,
|
|
1241
|
+
marginLeft: 8
|
|
1242
|
+
},
|
|
1243
|
+
onClick: props.onRetry
|
|
1244
|
+
}, "重试"));
|
|
1245
|
+
}
|
|
1216
1246
|
/** 标题右侧两件:「检查更新」一次查七家 + 「全部更新」按顺序串行装(吃 `useUpdateRows` 的表)。
|
|
1217
1247
|
*
|
|
1218
1248
|
* 禁用形状(#925 第 2 条 + #980 检查中):任一行 installing、一键串行中或检查轮未收尾时两件都点不得;人话沿用 `update-busy` 原句
|
|
@@ -1225,30 +1255,37 @@ window.__ModuleLoader__.load({
|
|
|
1225
1255
|
updatingAll,
|
|
1226
1256
|
checking
|
|
1227
1257
|
});
|
|
1228
|
-
const
|
|
1229
|
-
const
|
|
1230
|
-
const busyText = reasonText("update-busy");
|
|
1258
|
+
const targetsEmpty = targets.length === 0;
|
|
1259
|
+
const headerDisabled = blocked || targetsEmpty;
|
|
1231
1260
|
const installingNow = hasInstallingRow(rows) || updatingAll;
|
|
1232
1261
|
return react.createElement("span", { style: PANEL_STYLE.actions }, react.createElement("button", {
|
|
1233
1262
|
type: "button",
|
|
1234
|
-
style:
|
|
1263
|
+
style: headerDisabled ? {
|
|
1235
1264
|
...PANEL_STYLE.btn,
|
|
1236
1265
|
opacity: .55,
|
|
1237
1266
|
cursor: "default"
|
|
1238
1267
|
} : PANEL_STYLE.btn,
|
|
1239
|
-
disabled:
|
|
1268
|
+
disabled: headerDisabled,
|
|
1240
1269
|
onClick: checkAll,
|
|
1241
|
-
title:
|
|
1270
|
+
title: headerButtonTitle({
|
|
1271
|
+
blocked,
|
|
1272
|
+
empty: targetsEmpty,
|
|
1273
|
+
readyText: "检查总管与六家插件的版本"
|
|
1274
|
+
})
|
|
1242
1275
|
}, checking ? "检查中…" : "检查更新"), react.createElement("button", {
|
|
1243
1276
|
type: "button",
|
|
1244
|
-
style:
|
|
1277
|
+
style: headerDisabled ? {
|
|
1245
1278
|
...PANEL_STYLE.btn,
|
|
1246
1279
|
opacity: .55,
|
|
1247
1280
|
cursor: "default"
|
|
1248
1281
|
} : PANEL_STYLE.btn,
|
|
1249
|
-
disabled:
|
|
1282
|
+
disabled: headerDisabled,
|
|
1250
1283
|
onClick: updateAll,
|
|
1251
|
-
title:
|
|
1284
|
+
title: headerButtonTitle({
|
|
1285
|
+
blocked,
|
|
1286
|
+
empty: targetsEmpty,
|
|
1287
|
+
readyText: "按顺序逐家装上更新(一家收尾才起下一家)"
|
|
1288
|
+
})
|
|
1252
1289
|
}, installingNow ? "更新中…" : "全部更新"));
|
|
1253
1290
|
}
|
|
1254
1291
|
/** 待重启横幅:一行总账,只点名哪几家要重启(理由与做法写在各家卡片上,见 `restartBannerText`)。 */
|
|
@@ -1272,13 +1309,16 @@ window.__ModuleLoader__.load({
|
|
|
1272
1309
|
* 手工命令只在「装不了」或「装失败」的行显示:正常用户用不到,摊在每行上既吵又误导。
|
|
1273
1310
|
*/
|
|
1274
1311
|
function UpdateResults(props) {
|
|
1275
|
-
const { targets, rows, loadError, checking, updatingAll, open, close, showProgress } = props.face;
|
|
1312
|
+
const { targets, rows, loadError, checking, updatingAll, open, close, showProgress, retry } = props.face;
|
|
1276
1313
|
const dialogRef = react.useRef(null);
|
|
1277
1314
|
react.useEffect(() => {
|
|
1278
1315
|
if (open) dialogRef.current?.focus();
|
|
1279
1316
|
}, [open]);
|
|
1280
1317
|
const shown = targets.filter((target) => rows[target.key] && rows[target.key].phase !== "idle");
|
|
1281
|
-
if (loadError) return react.createElement(
|
|
1318
|
+
if (loadError) return react.createElement(TargetsLoadError, {
|
|
1319
|
+
message: loadError,
|
|
1320
|
+
onRetry: retry
|
|
1321
|
+
});
|
|
1282
1322
|
if (targets.length === 0) return null;
|
|
1283
1323
|
if (shown.length === 0 && !open) return null;
|
|
1284
1324
|
const locked = shouldBlockBatchStart({
|
|
@@ -1337,7 +1377,7 @@ window.__ModuleLoader__.load({
|
|
|
1337
1377
|
onClick: () => {
|
|
1338
1378
|
props.face.act(target, buttonAction);
|
|
1339
1379
|
}
|
|
1340
|
-
}, ACTION_LABEL[buttonAction]) : null, row.failure ? react.createElement("div", { style: PANEL_STYLE.reason }, "装不上:" + row.failure.message) : null, versionLines(target, snapshot).map((line, index) => react.createElement("div", {
|
|
1380
|
+
}, ACTION_LABEL[buttonAction]) : null, row.failure ? react.createElement("div", { style: PANEL_STYLE.reason }, "装不上:" + row.failure.message) : null, failureDetailCode(failureDetailOf(row.failure)), versionLines(target, snapshot).map((line, index) => react.createElement("div", {
|
|
1341
1381
|
key: String(index),
|
|
1342
1382
|
style: PANEL_STYLE.skill
|
|
1343
1383
|
}, line)), showManual ? react.createElement("div", { style: PANEL_STYLE.skill }, "在终端里执行这条命令可以手动完成这一步:") : null, showManual ? react.createElement("code", { style: PANEL_STYLE.cmd }, manual) : null);
|
|
@@ -1441,7 +1481,7 @@ window.__ModuleLoader__.load({
|
|
|
1441
1481
|
disabled: locked,
|
|
1442
1482
|
title: locked ? reasonText("update-busy") : void 0,
|
|
1443
1483
|
onClick: () => props.face.act(target, "recheck")
|
|
1444
|
-
}, ACTION_LABEL.recheck) : null, reason ? react.createElement("div", { style: PANEL_STYLE.reason }, reason) : null, react.createElement("code", { style: PANEL_STYLE.cmd }, manual));
|
|
1484
|
+
}, ACTION_LABEL.recheck) : null, reason ? react.createElement("div", { style: PANEL_STYLE.reason }, reason) : null, failureDetailCode(failureDetailOf(row?.failure)), react.createElement("code", { style: PANEL_STYLE.cmd }, manual));
|
|
1445
1485
|
}
|
|
1446
1486
|
//#endregion
|
|
1447
1487
|
//#region src/health-contract.ts
|
|
@@ -3069,48 +3109,8 @@ window.__ModuleLoader__.load({
|
|
|
3069
3109
|
style: S.moreRow
|
|
3070
3110
|
}, react.createElement("span", { style: S.morePkg }, row.pkg), react.createElement("span", { style: S.moreDesc }, row.desc), react.createElement("span", { style: S.moreIcon }, react.createElement(ExternalIcon, null)))));
|
|
3071
3111
|
}
|
|
3072
|
-
/**
|
|
3073
|
-
|
|
3074
|
-
* 三态(#937):`loading`(首帧就画胶囊占位 `…`)/`ready`(读到,画包名 · 版本)/`missing`(读不到,画「版本未知」)。
|
|
3075
|
-
* **失败要重试**:原先只取一次、一失败就永远停在未知(#937 查出来的真缺陷);这里按 1s/3s/8s 退避重试三次。
|
|
3076
|
-
* 与卡路里 #130 同一条路:面板是浏览器产物、禁 node 内建,读盘只许在宿主半。 */
|
|
3077
|
-
/** 读中 / 读不到 两种胶囊文案(#937:占位符用 `…`,读不到给人话,不把 `unknown` 印给人看)。 */
|
|
3078
|
-
const VERSION_PENDING_TEXT = "…";
|
|
3079
|
-
const VERSION_MISSING_TEXT = "版本未知";
|
|
3080
|
-
/** 重试间隔(#937):三次退避,之后不再打扰宿主。 */
|
|
3081
|
-
const VERSION_RETRY_MS = [
|
|
3082
|
-
1e3,
|
|
3083
|
-
3e3,
|
|
3084
|
-
8e3
|
|
3085
|
-
];
|
|
3086
|
-
function useManagerVersion(getCall) {
|
|
3087
|
-
const [state, setState] = react.useState({ kind: "loading" });
|
|
3088
|
-
react.useEffect(() => {
|
|
3089
|
-
let alive = true;
|
|
3090
|
-
const timers = [];
|
|
3091
|
-
const attempt = (index) => {
|
|
3092
|
-
loadManagerVersion(getCall()).then((next) => {
|
|
3093
|
-
if (!alive) return;
|
|
3094
|
-
if (next !== "unknown") {
|
|
3095
|
-
setState({
|
|
3096
|
-
kind: "ready",
|
|
3097
|
-
version: next
|
|
3098
|
-
});
|
|
3099
|
-
return;
|
|
3100
|
-
}
|
|
3101
|
-
setState({ kind: "missing" });
|
|
3102
|
-
const wait = VERSION_RETRY_MS[index];
|
|
3103
|
-
if (wait !== void 0) timers.push(setTimeout(() => attempt(index + 1), wait));
|
|
3104
|
-
});
|
|
3105
|
-
};
|
|
3106
|
-
attempt(0);
|
|
3107
|
-
return () => {
|
|
3108
|
-
alive = false;
|
|
3109
|
-
for (const id of timers) clearTimeout(id);
|
|
3110
|
-
};
|
|
3111
|
-
}, [getCall]);
|
|
3112
|
-
return state;
|
|
3113
|
-
}
|
|
3112
|
+
/** 版本胶囊那一行字:只在这里拼一次,屏上与用例读的是同一串。 */
|
|
3113
|
+
const MANAGER_VERSION_TEXT = "dsh-life-pack · 0.3.20";
|
|
3114
3114
|
/** 爱生活面板:总设置区 + 检查更新(七家)+ 爱生活页签条(slot 驱动)+ 技能设置页投影/缺席卡。 */
|
|
3115
3115
|
function LifePackSection(props) {
|
|
3116
3116
|
const tabsId = react.useId();
|
|
@@ -3118,7 +3118,6 @@ window.__ModuleLoader__.load({
|
|
|
3118
3118
|
const rows = props.useTabs((value) => value);
|
|
3119
3119
|
const present = new Set(rows.map((r) => r.id));
|
|
3120
3120
|
const face = useUpdateRows(props.getCall);
|
|
3121
|
-
const managerVersion = useManagerVersion(props.getCall);
|
|
3122
3121
|
const health = useHealthPanel(() => props.getCall(), react.useMemo(() => rows.filter((row) => row.channel.length > 0).map((row) => ({
|
|
3123
3122
|
id: row.id,
|
|
3124
3123
|
channel: row.channel
|
|
@@ -3192,7 +3191,7 @@ window.__ModuleLoader__.load({
|
|
|
3192
3191
|
return react.createElement("div", null, react.createElement("div", { style: S.headRow }, react.createElement("div", { style: S.head }, "爱生活"), react.createElement("span", {
|
|
3193
3192
|
style: S.versionCapsule,
|
|
3194
3193
|
"data-ilife-version": "capsule"
|
|
3195
|
-
},
|
|
3194
|
+
}, MANAGER_VERSION_TEXT), react.createElement("div", { style: S.headActions }, react.createElement(CheckUpdateButton, { face }), react.createElement(PanelActions, null))), react.createElement(UpdateResults, { face }), react.createElement(HealthSummaryLine, {
|
|
3196
3195
|
lights,
|
|
3197
3196
|
running: health.running,
|
|
3198
3197
|
error: summaryErrorOf(health),
|