dsh-composer-ux 0.15.2 → 0.15.4
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 +51 -0
- package/README.md +3 -3
- package/lib/client.js +88 -91
- package/lib/client.js.map +4 -4
- package/lib/index.js +24 -7
- package/lib/index.js.map +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
4
4
|
|
|
5
|
+
## [0.15.4] — 2026-09-30(移除侧边栏那枚重启按钮)
|
|
6
|
+
|
|
7
|
+
起因(用户原话):**「移除这里的重启按钮」**(配图是侧边栏底部,「移动访问」下面那枚)。
|
|
8
|
+
|
|
9
|
+
按问清的结果:**只删这一枚**。现在重启有两个入口 ——
|
|
10
|
+
标题栏条上那枚(`shell.overlay`,随手能点)与设置页抬头那枚(点下去会先说清"现在有几个会话在跑")。
|
|
11
|
+
|
|
12
|
+
- 删掉 `sidebar.footer.action` 的注册与 `RestartFooterAction.tsx`(git 历史里仍在,注释里写了怎么加回来);
|
|
13
|
+
- 槽位清单断言 9 → 8;把"侧边栏那枚在"这条断言改成「它不在了 + 标题栏那枚在」(正反都钉住)。
|
|
14
|
+
|
|
15
|
+
## 验证
|
|
16
|
+
|
|
17
|
+
- `npm test`:**2357 passed / 0 failed**(23 个套件)。
|
|
18
|
+
- 变异:**161/161**(本次是纯删除,没有新增可被变异的代码路径,故不加变异 —— 用两条直接断言钉住)。
|
|
19
|
+
|
|
20
|
+
## [0.15.3] — 2026-09-30(修好重启被 403 挡住的根因 + 按参考插件把按钮摆到标题栏条)
|
|
21
|
+
|
|
22
|
+
起因(用户原话):**「参考一下这个,看这个的重启方式是怎么样的,并把按钮位置调成这个插件的样子
|
|
23
|
+
https://github.com/HHHEEEWWW/dsh-quick-restart」**。
|
|
24
|
+
|
|
25
|
+
### 1. 根因:来源判据太窄,桌面版必然被拒
|
|
26
|
+
|
|
27
|
+
读它的 `lib/index.js` 逐字看到这一行:`if (!origin || origin === 'null' || /^dsh-app:\/\//iu.test(origin)) return ''`
|
|
28
|
+
—— **桌面版壳的页面来源是 `dsh-app://`,它直接放行**,跨站防线交给客户端必须带的自定义头
|
|
29
|
+
(`x-dsh-quick-restart: 1`,跨站页面加不了自定义头)。我们原来的判据要求 `Origin` 与 `Host` 逐字同源,
|
|
30
|
+
于是桌面版**两枚按钮都 403**。现在对齐它的判据:
|
|
31
|
+
|
|
32
|
+
- 放行 `dsh-app://`、没有 Origin、`Origin: null`;
|
|
33
|
+
- http 来源仍要求与 Host 同源,且 Host 必须是回环(新增 `origin-not-loopback`);
|
|
34
|
+
- 转发头多认一个 `x-forwarded-host`;
|
|
35
|
+
- 新增防跨站头 `x-composer-ux-restart: 1`(宿主先卡它、再判来源;客户端两处请求都带上)。
|
|
36
|
+
|
|
37
|
+
### 2. 按钮按它的摆放挪到标题栏条(只改位置,不重做样式)
|
|
38
|
+
|
|
39
|
+
新增一枚挂在 `shell.overlay`:贴顶 + `right: calc(100% - env(titlebar-area-x) - env(titlebar-area-width))`,
|
|
40
|
+
正好落在原生「最小化」按钮左边;高 28px、最小宽 104px;`-webkit-app-region: no-drag`(否则点不着);
|
|
41
|
+
只在 `data-windows-titlebar` 存在时(Windows 桌面壳)渲染。颜色与两步确认仍是我们自己的,
|
|
42
|
+
侧边栏与设置页那两枚**保留**。
|
|
43
|
+
|
|
44
|
+
## 验证
|
|
45
|
+
|
|
46
|
+
- `npm test`:**2356 passed / 0 failed**(23 个套件;守卫断言按新判据重写 + 槽位 8→9)。
|
|
47
|
+
- 变异测试:**161/161 全部被咬住**(新增 FI `dsh-app://` 又被拒 / FJ 转发头少认一个;
|
|
48
|
+
移除旧的 A —— 它挡的是"来源判据",现在由 FI/FJ 直接钉在判据本身上)。
|
|
49
|
+
- `typecheck` 0 错误。
|
|
50
|
+
|
|
51
|
+
## 升级说明
|
|
52
|
+
|
|
53
|
+
- 装完**需要手动重启一次 DSH**(界面上的按钮在旧版本里还是 403):
|
|
54
|
+
`C:\Users\fangwen\.dsh\launcher\restart-webui.bat`。
|
|
55
|
+
|
|
5
56
|
## [0.15.2] — 2026-09-30(重启被挡时,现在会说清是哪一条不满足)
|
|
6
57
|
|
|
7
58
|
起因(用户截图):**侧边栏与设置页两枚「重启」都报** `restart is limited to same-origin loopback requests`。
|
package/README.md
CHANGED
|
@@ -506,7 +506,7 @@ Windows 上 DSH 给模型的终端工具是 **PowerShell**(工具名 `pwsh`)
|
|
|
506
506
|
| 工具循环的消息形状 / 轮次封顶 / 异常必须降级 | 同上第 6 节(假 llm 驱动整条循环,逐条检查 `role:'tool'` 与 `toolCallId`) |
|
|
507
507
|
| 工具路径:默认关、开了才派、**查完吐散文必须回落**、拿不到工作目录就不派 | `test/quick-commands.mjs` 5g 节(13 条,真路由 + 假 llm) |
|
|
508
508
|
| 工具读到的内容不进台账 | 同 5g 节:断言台账里只有工具名与次数、没有读到的文件内容 |
|
|
509
|
-
| 变异守卫真的会咬人,且**必须是指定的那条测试变红** | `npm run test:mutations`:**
|
|
509
|
+
| 变异守卫真的会咬人,且**必须是指定的那条测试变红** | `npm run test:mutations`:**161 条全部咬住**(判据是 `red.some(line => line.includes(item.expect))`,不是"有红就行") |
|
|
510
510
|
| 发布门禁三条判据 | `npm run gates` 全过;`check:tag` 实测 `v0.12.0` 的 tag 名与所指提交里的版本一致 |
|
|
511
511
|
| 三平台 CI | GitHub Actions:ubuntu / windows / macos × Node 20(`npm ci → typecheck → build → test → check:pack → check:docs`) |
|
|
512
512
|
|
|
@@ -640,9 +640,9 @@ node build.mjs # 产出 lib/index.js + lib/client.js
|
|
|
640
640
|
# ⚠️ 宿主半会**内联** schemastery / cosmokit:
|
|
641
641
|
# 优先用 DSH 检出里的 vendor 副本,检出不在时退到 node_modules
|
|
642
642
|
# 里同版本的 npm 包(两者逐字节相同)——CI 上走的就是退路
|
|
643
|
-
npm test # 23 个套件;当前
|
|
643
|
+
npm test # 23 个套件;当前 2357 passed, 0 failed(2026-09-29 实测;CI 三平台同样全绿)
|
|
644
644
|
# 走 scripts/run-tests.mjs:顺带把"多少套件/多少条"记进 test/.last-run.json
|
|
645
|
-
npm run test:mutations # 手动跑:变异测试,证明那套护栏真的在咬人(
|
|
645
|
+
npm run test:mutations # 手动跑:变异测试,证明那套护栏真的在咬人(161 条,须单独跑)
|
|
646
646
|
# 同样记录结果,供下面的文档门禁核对
|
|
647
647
|
npm run gates # 发版门禁三条一起跑:tag 指向 / 包内容 / 文档数字
|
|
648
648
|
npm run check:tag # ① tag 名里的版本 == 该 tag 所指提交里的 package.json 版本
|
package/lib/client.js
CHANGED
|
@@ -1006,6 +1006,8 @@ var REPO_URL = "https://github.com/fangwen9527/dsh-composer-ux";
|
|
|
1006
1006
|
var RESTART_API_PATH = "/composer-ux/restart";
|
|
1007
1007
|
var USAGE_API_PATH = "/composer-ux/usage";
|
|
1008
1008
|
var MODELS_API_PATH = "/composer-ux/models";
|
|
1009
|
+
var RESTART_CSRF_HEADER = "x-composer-ux-restart";
|
|
1010
|
+
var RESTART_CSRF_VALUE = "1";
|
|
1009
1011
|
var SYNC_API_PATH = "/composer-ux/sync-prices";
|
|
1010
1012
|
var ENABLED_FIELD = "enabled";
|
|
1011
1013
|
var KEYS_ENABLED_FIELD = "keysEnabled";
|
|
@@ -3518,7 +3520,7 @@ function PanelResizeHandles({ useLive, actions }) {
|
|
|
3518
3520
|
);
|
|
3519
3521
|
}
|
|
3520
3522
|
|
|
3521
|
-
// src/client/
|
|
3523
|
+
// src/client/RestartTitlebarButton.tsx
|
|
3522
3524
|
var import_react3 = require("react");
|
|
3523
3525
|
|
|
3524
3526
|
// src/client/restart-screen.ts
|
|
@@ -3808,7 +3810,10 @@ async function requestRestart(fetcher = fetch) {
|
|
|
3808
3810
|
let oldBoot = "";
|
|
3809
3811
|
let logPath = "";
|
|
3810
3812
|
try {
|
|
3811
|
-
const status = await fetcher("/composer-ux/restart", {
|
|
3813
|
+
const status = await fetcher("/composer-ux/restart", {
|
|
3814
|
+
cache: "no-store",
|
|
3815
|
+
headers: { [RESTART_CSRF_HEADER]: RESTART_CSRF_VALUE }
|
|
3816
|
+
});
|
|
3812
3817
|
if (status.ok) {
|
|
3813
3818
|
const facts = await status.json();
|
|
3814
3819
|
oldBoot = typeof facts.boot === "string" ? facts.boot : "";
|
|
@@ -3822,7 +3827,7 @@ async function requestRestart(fetcher = fetch) {
|
|
|
3822
3827
|
try {
|
|
3823
3828
|
const response = await fetcher("/composer-ux/restart", {
|
|
3824
3829
|
method: "POST",
|
|
3825
|
-
headers: { "content-type": "application/json" },
|
|
3830
|
+
headers: { "content-type": "application/json", [RESTART_CSRF_HEADER]: RESTART_CSRF_VALUE },
|
|
3826
3831
|
body: "{}"
|
|
3827
3832
|
});
|
|
3828
3833
|
const parsed = await response.json().catch(() => ({}));
|
|
@@ -3835,108 +3840,97 @@ async function requestRestart(fetcher = fetch) {
|
|
|
3835
3840
|
}
|
|
3836
3841
|
}
|
|
3837
3842
|
|
|
3838
|
-
// src/client/
|
|
3843
|
+
// src/client/RestartTitlebarButton.tsx
|
|
3839
3844
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
3845
|
+
var STYLE_ID = "composer-ux-titlebar-style";
|
|
3840
3846
|
var ARMED_RESET_MS = 4e3;
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3847
|
+
var STYLE = [
|
|
3848
|
+
"@keyframes composer-ux-titlebar-spin{to{transform:rotate(360deg)}}",
|
|
3849
|
+
".composer-ux-titlebar{position:absolute;top:0;z-index:30;-webkit-app-region:no-drag;",
|
|
3850
|
+
"right:calc(100% - env(titlebar-area-x,0px) - env(titlebar-area-width,calc(100% - 138px)));",
|
|
3851
|
+
"height:var(--dsh-windows-titlebar-height,40px);display:flex;align-items:center;padding-right:6px}",
|
|
3852
|
+
".composer-ux-titlebar>button{display:inline-flex;align-items:center;gap:6px;height:28px;min-width:104px;",
|
|
3853
|
+
"padding:0 12px;border:0.5px solid var(--dsw-alias-border-l2,rgba(255,255,255,.16));border-radius:7px;",
|
|
3854
|
+
"background:var(--dsw-alias-bg-layer-1,#0b0b0e);color:var(--dsw-alias-label-primary,#f7f7fa);",
|
|
3855
|
+
"font:inherit;font-size:12px;font-weight:600;line-height:1;cursor:pointer;white-space:nowrap}",
|
|
3856
|
+
".composer-ux-titlebar>button:disabled{cursor:default;opacity:.85}",
|
|
3857
|
+
".composer-ux-titlebar>button[data-error]{border-color:rgba(229,72,77,.6);color:#ffb7b9}"
|
|
3858
|
+
].join("");
|
|
3859
|
+
function ensureStyle() {
|
|
3860
|
+
if (typeof document === "undefined" || document.getElementById(STYLE_ID) !== null) return;
|
|
3861
|
+
const style = document.createElement("style");
|
|
3862
|
+
style.id = STYLE_ID;
|
|
3863
|
+
style.textContent = STYLE;
|
|
3864
|
+
document.head.append(style);
|
|
3865
|
+
}
|
|
3866
|
+
function Icon({ spin }) {
|
|
3867
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3868
|
+
"svg",
|
|
3869
|
+
{
|
|
3870
|
+
width: "14",
|
|
3871
|
+
height: "14",
|
|
3872
|
+
viewBox: "0 0 16 16",
|
|
3873
|
+
"aria-hidden": "true",
|
|
3874
|
+
focusable: "false",
|
|
3875
|
+
style: spin ? { animation: "composer-ux-titlebar-spin 1s linear infinite" } : void 0,
|
|
3876
|
+
children: [
|
|
3877
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 2.5a5.5 5.5 0 1 0 5.2 3.7", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" }),
|
|
3878
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M13.4 2.2v4h-4", fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
3879
|
+
]
|
|
3880
|
+
}
|
|
3881
|
+
);
|
|
3855
3882
|
}
|
|
3856
|
-
function
|
|
3883
|
+
function RestartTitlebarButton() {
|
|
3857
3884
|
const [armed, setArmed] = (0, import_react3.useState)(false);
|
|
3858
3885
|
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
3859
|
-
const [
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
}
|
|
3868
|
-
};
|
|
3869
|
-
|
|
3886
|
+
const [error, setError] = (0, import_react3.useState)("");
|
|
3887
|
+
const [visible, setVisible] = (0, import_react3.useState)(false);
|
|
3888
|
+
(0, import_react3.useEffect)(() => {
|
|
3889
|
+
ensureStyle();
|
|
3890
|
+
try {
|
|
3891
|
+
setVisible(document.documentElement.hasAttribute("data-windows-titlebar"));
|
|
3892
|
+
} catch {
|
|
3893
|
+
setVisible(false);
|
|
3894
|
+
}
|
|
3895
|
+
}, []);
|
|
3896
|
+
if (!visible) return null;
|
|
3897
|
+
const label = busy ? "\u91CD\u542F\u4E2D\u2026" : armed ? "\u786E\u8BA4\u91CD\u542F\uFF1F" : error === "" ? "\u91CD\u542F" : "\u91CD\u8BD5";
|
|
3898
|
+
const click = () => {
|
|
3899
|
+
if (busy) return;
|
|
3900
|
+
if (!armed) {
|
|
3901
|
+
setArmed(true);
|
|
3902
|
+
setError("");
|
|
3903
|
+
window.setTimeout(() => {
|
|
3904
|
+
setArmed(false);
|
|
3905
|
+
}, ARMED_RESET_MS);
|
|
3906
|
+
return;
|
|
3907
|
+
}
|
|
3870
3908
|
setArmed(false);
|
|
3871
3909
|
setBusy(true);
|
|
3872
|
-
|
|
3910
|
+
setError("");
|
|
3873
3911
|
void requestRestart().then((result) => {
|
|
3874
|
-
setBusy(false);
|
|
3875
3912
|
if (!result.ok) {
|
|
3876
|
-
|
|
3913
|
+
setBusy(false);
|
|
3914
|
+
setError(result.error);
|
|
3877
3915
|
return;
|
|
3878
3916
|
}
|
|
3879
3917
|
enterRestartScreen({ oldBoot: result.oldBoot, logPath: result.logPath });
|
|
3880
3918
|
});
|
|
3881
3919
|
};
|
|
3882
|
-
|
|
3883
|
-
const title = note2 !== "" ? `\u91CD\u542F\u5931\u8D25\uFF1A${note2}` : armed ? "\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\u91CD\u542F\uFF08\u4F1A\u628A\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\u6253\u65AD\uFF09" : "\u91CD\u542F DSH \u670D\u52A1\uFF08\u4F1A\u6253\u65AD\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\uFF1B\u786E\u8BA4\u540E\u4F1A\u663E\u793A\u91CD\u542F\u8FDB\u5EA6\u5E76\u81EA\u52A8\u56DE\u5230\u9875\u9762\uFF09";
|
|
3884
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "composer-ux-titlebar", "data-composer-ux": "restart-titlebar", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3885
3921
|
"button",
|
|
3886
3922
|
{
|
|
3887
3923
|
type: "button",
|
|
3888
|
-
"
|
|
3889
|
-
"aria-label": "\u91CD\u542F DSH",
|
|
3890
|
-
title,
|
|
3924
|
+
title: error === "" ? armed ? "\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\u91CD\u542F\uFF08\u4F1A\u6253\u65AD\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\uFF09" : "\u91CD\u542F DSH\uFF08\u66F4\u65B0\u63D2\u4EF6\u540E\u7528\uFF1B\u786E\u8BA4\u540E\u663E\u793A\u91CD\u542F\u8FDB\u5EA6\u5E76\u81EA\u52A8\u56DE\u5230\u9875\u9762\uFF09" : `\u91CD\u542F\u5931\u8D25\uFF1A${error}`,
|
|
3891
3925
|
disabled: busy,
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
event.preventDefault();
|
|
3895
|
-
},
|
|
3896
|
-
onClick: () => {
|
|
3897
|
-
if (armed) go();
|
|
3898
|
-
else arm();
|
|
3899
|
-
},
|
|
3926
|
+
"data-error": error === "" ? void 0 : true,
|
|
3927
|
+
onClick: click,
|
|
3900
3928
|
children: [
|
|
3901
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3902
|
-
|
|
3929
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { spin: busy }),
|
|
3930
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: label })
|
|
3903
3931
|
]
|
|
3904
3932
|
}
|
|
3905
|
-
);
|
|
3906
|
-
}
|
|
3907
|
-
function wideStyle(armed) {
|
|
3908
|
-
return {
|
|
3909
|
-
font: "inherit",
|
|
3910
|
-
cursor: "pointer",
|
|
3911
|
-
display: "inline-flex",
|
|
3912
|
-
alignItems: "center",
|
|
3913
|
-
gap: 6,
|
|
3914
|
-
height: 32,
|
|
3915
|
-
padding: "0 14px",
|
|
3916
|
-
borderRadius: 999,
|
|
3917
|
-
whiteSpace: "nowrap",
|
|
3918
|
-
flexShrink: 0,
|
|
3919
|
-
fontSize: 12,
|
|
3920
|
-
border: `1px solid ${armed ? "var(--dsw-alias-label-primary, #111)" : "var(--dsw-alias-border-l2, #d1d5db)"}`,
|
|
3921
|
-
background: armed ? "var(--dsw-alias-bg-layer-2, rgba(0,0,0,0.06))" : "var(--dsw-alias-bg-layer-1, #fff)",
|
|
3922
|
-
color: "var(--dsw-alias-label-primary, inherit)"
|
|
3923
|
-
};
|
|
3924
|
-
}
|
|
3925
|
-
function railStyle(armed) {
|
|
3926
|
-
return {
|
|
3927
|
-
font: "inherit",
|
|
3928
|
-
cursor: "pointer",
|
|
3929
|
-
display: "inline-flex",
|
|
3930
|
-
alignItems: "center",
|
|
3931
|
-
justifyContent: "center",
|
|
3932
|
-
width: 36,
|
|
3933
|
-
height: 36,
|
|
3934
|
-
borderRadius: 8,
|
|
3935
|
-
flexShrink: 0,
|
|
3936
|
-
border: "none",
|
|
3937
|
-
background: armed ? "var(--dsw-alias-bg-layer-2, rgba(0,0,0,0.06))" : "transparent",
|
|
3938
|
-
color: armed ? "var(--dsw-alias-label-primary, #111)" : "var(--dsw-alias-label-secondary, #4b5563)"
|
|
3939
|
-
};
|
|
3933
|
+
) });
|
|
3940
3934
|
}
|
|
3941
3935
|
|
|
3942
3936
|
// src/client/SettingsSection.tsx
|
|
@@ -5733,7 +5727,10 @@ function useRestart() {
|
|
|
5733
5727
|
const [detail2, setDetail] = (0, import_react7.useState)("");
|
|
5734
5728
|
const [blocked, setBlocked] = (0, import_react7.useState)(null);
|
|
5735
5729
|
const readFacts = async () => {
|
|
5736
|
-
const response = await fetch(RESTART_API_PATH, {
|
|
5730
|
+
const response = await fetch(RESTART_API_PATH, {
|
|
5731
|
+
cache: "no-store",
|
|
5732
|
+
headers: { [RESTART_CSRF_HEADER]: RESTART_CSRF_VALUE }
|
|
5733
|
+
});
|
|
5737
5734
|
if (!response.ok) return { error: `HTTP ${String(response.status)}` };
|
|
5738
5735
|
const parsed = await response.json();
|
|
5739
5736
|
return {
|
|
@@ -5805,7 +5802,7 @@ function useRestart() {
|
|
|
5805
5802
|
try {
|
|
5806
5803
|
const response = await fetch(RESTART_API_PATH, {
|
|
5807
5804
|
method: "POST",
|
|
5808
|
-
headers: { "content-type": "application/json" },
|
|
5805
|
+
headers: { "content-type": "application/json", [RESTART_CSRF_HEADER]: RESTART_CSRF_VALUE },
|
|
5809
5806
|
body: "{}"
|
|
5810
5807
|
});
|
|
5811
5808
|
const parsed = await response.json();
|
|
@@ -8587,12 +8584,12 @@ function apply(ctx) {
|
|
|
8587
8584
|
commitBook(withInsertMode(book.getSnapshot(), promptId, mode));
|
|
8588
8585
|
}
|
|
8589
8586
|
};
|
|
8590
|
-
slots.inject("
|
|
8591
|
-
name: "
|
|
8592
|
-
id: "composer-ux-restart",
|
|
8593
|
-
order:
|
|
8587
|
+
slots.inject("shell.overlay", () => slots.register({
|
|
8588
|
+
name: "shell.overlay",
|
|
8589
|
+
id: "composer-ux-restart-titlebar",
|
|
8590
|
+
order: 12,
|
|
8594
8591
|
label: "\u91CD\u542F"
|
|
8595
|
-
},
|
|
8592
|
+
}, RestartTitlebarButton));
|
|
8596
8593
|
maybeShowRestartDone();
|
|
8597
8594
|
slots.inject("settings.section", () => slots.register({
|
|
8598
8595
|
name: "settings.section",
|