dsh-plugin 1.1.0 → 1.1.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/client/client.js CHANGED
@@ -27,6 +27,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
27
27
  failedDesc: "请稍后重试,或点击右上角按钮在浏览器中打开插件中心。",
28
28
  retry: "重试",
29
29
  install: "安装",
30
+ cliOnlyHint: "此插件可能需命令行辅助,失败时复制上方命令到 dsh 终端",
31
+ failedCopyHint: "安装失败。请复制上方安装命令到 dsh 终端手动执行(原生依赖构建脚本可能需要人工放行,如 pnpm approve-builds)",
30
32
  toastCopied: "安装命令已复制,去 dsh 终端粘贴即可安装",
31
33
  installed: "已安装",
32
34
  notInstalled: "未安装",
@@ -69,6 +71,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
69
71
  restartLater: "稍后重启",
70
72
  restarting: "正在重启…",
71
73
  restartHint: "部分插件(如插件市场、顶层 bundle)需重启后才会生效。",
74
+ done: "完成",
72
75
  restartPendingHint: "安装成功,重启后生效",
73
76
  restartPendingHintUninstall: "卸载成功,重启后移除",
74
77
  sectionPendingRestart: "待重启",
@@ -115,6 +118,21 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
115
118
  update: "可更新",
116
119
  updateAvailable: "有更新",
117
120
  updateAvailableHint: "检测到更新:有版本号的仓库比对版本号,无版本号的仓库比对仓库最近更新时间",
121
+ hubUpdateHint: "检测到 DSH-Plugin Hub 新版本,点击查看更新内容并更新",
122
+ hubUpdateTitle: "DSH-Plugin Hub 有新版本",
123
+ hubUpdateDesc: "v{version} 已发布,点击下方按钮即可更新,完成后需重启宿主生效。",
124
+ hubUpdatePublished: "发布于",
125
+ hubUpdateNotes: "更新记录",
126
+ hubUpdateLater: "稍后再说",
127
+ versionHint: "查看版本信息与更新记录",
128
+ hubCurrentTitle: "当前版本",
129
+ hubCurrentDesc: "你正在使用 v{version},已是最新版本。",
130
+ hubUpToDate: "已是最新版本",
131
+ followUs: "关注我们",
132
+ aboutTitle: "关注我们",
133
+ aboutDesc: "了解 DSH-Plugin Hub 是做什么的,加入用户反馈群随时交流。",
134
+ aboutEmpty: "内容暂未发布,敬请期待。",
135
+ aboutUpdated: "更新于",
118
136
  empty: "该分类暂无插件",
119
137
  dataFrom: "数据源 dsh-plugin.org · 每日人工更新"
120
138
  };
@@ -139,6 +157,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
139
157
  failedDesc: "Please retry, or open the hub in your browser with the button above.",
140
158
  retry: "Retry",
141
159
  install: "Install",
160
+ cliOnlyHint: "This plugin may need command-line help; if it fails, copy the command above and run it in your dsh terminal",
161
+ failedCopyHint: "Install failed. Copy the command above and run it manually in your dsh terminal (native build scripts may need manual approval, e.g. pnpm approve-builds)",
142
162
  toastCopied: "Install command copied — paste it in your dsh terminal",
143
163
  installed: "Installed",
144
164
  notInstalled: "Not installed",
@@ -181,6 +201,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
181
201
  restartLater: "Later",
182
202
  restarting: "Restarting…",
183
203
  restartHint: "Some plugins (such as plugin markets / top-level bundles) only take effect after a restart.",
204
+ done: "Done",
184
205
  restartPendingHint: "Installed — takes effect after restart",
185
206
  restartPendingHintUninstall: "Removed — cleaned up after restart",
186
207
  sectionPendingRestart: "Pending restart",
@@ -227,12 +248,27 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
227
248
  update: "Update",
228
249
  updateAvailable: "Update available",
229
250
  updateAvailableHint: "An update was detected: repos with a release are compared by tag, repos without one by last push time",
251
+ hubUpdateHint: "A new DSH-Plugin Hub version is available — click to view the changelog and update",
252
+ hubUpdateTitle: "A new DSH-Plugin Hub version is available",
253
+ hubUpdateDesc: "v{version} has been released — click below to update, then restart the host to apply it.",
254
+ hubUpdatePublished: "Published",
255
+ hubUpdateNotes: "What's new",
256
+ hubUpdateLater: "Later",
257
+ versionHint: "View version info and changelog",
258
+ hubCurrentTitle: "Current version",
259
+ hubCurrentDesc: "You are on v{version} — this is the latest version.",
260
+ hubUpToDate: "Up to date",
261
+ followUs: "Follow us",
262
+ aboutTitle: "Follow us",
263
+ aboutDesc: "Learn what DSH-Plugin Hub does and join our user feedback group.",
264
+ aboutEmpty: "Content not published yet — stay tuned.",
265
+ aboutUpdated: "Updated",
230
266
  empty: "No plugins in this category yet",
231
267
  dataFrom: "Data from dsh-plugin.org · curated daily"
232
268
  };
233
269
  //#endregion
234
270
  //#region \0dsh-css:src/client/styles/Header.module.css.mjs
235
- const css$4 = ".qikqja_root{min-width:0;height:100%;color:var(--hub-text-primary);flex-direction:column;gap:8px;display:flex}.qikqja_header{flex-direction:column;gap:2px;padding:2px 2px 0;display:flex}.qikqja_headerRight{flex-shrink:0;align-items:center;gap:2px;display:inline-flex}.qikqja_langBtn{height:24px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;padding:0 8px;font-size:12px;font-weight:600;transition:color .15s,background-color .15s;display:inline-flex}.qikqja_langBtn:hover{color:var(--hub-purple-1);background-color:var(--hub-purple-tint)}.qikqja_githubLink{color:var(--hub-text-tertiary);cursor:pointer;border-radius:6px;flex-shrink:0;align-items:center;padding:3px;text-decoration:none;transition:color .15s,background-color .15s;display:inline-flex}.qikqja_githubLink:hover{color:var(--hub-purple-1);background-color:var(--hub-purple-tint)}.qikqja_githubIcon{flex-shrink:0;display:block}.qikqja_headerTitleRow{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}.qikqja_brandTitle{min-width:0;color:inherit;cursor:pointer;align-items:center;gap:10px;text-decoration:none;display:flex}.qikqja_taglineLink{min-width:0;max-width:100%;color:inherit;cursor:pointer;align-self:flex-start;text-decoration:none}.qikqja_title{margin:0;font-size:14px;font-weight:600;line-height:20px}.qikqja_version{color:var(--hub-text-secondary)}.qikqja_logoIcon{flex-shrink:0;display:block}.qikqja_copyIcon{flex-shrink:0}.qikqja_tagline{color:var(--hub-text-tertiary);white-space:nowrap;text-overflow:ellipsis;margin:0;font-size:12px;line-height:18px;overflow:hidden}.qikqja_controls{flex-shrink:0;align-items:center;gap:4px;display:flex}.qikqja_filterResults{color:var(--hub-text-tertiary);white-space:nowrap;flex-shrink:0;align-items:baseline;font-size:12px;line-height:18px;display:inline-flex}.qikqja_resultCount{font-variant-numeric:tabular-nums;text-align:center;min-width:5ch}.qikqja_adBanner{border:1px solid var(--hub-purple-border);background:linear-gradient(90deg, var(--hub-purple-1) 0%, var(--hub-purple-2) 100%);color:#fff;cursor:pointer;-webkit-user-select:none;user-select:none;box-shadow:0 2px 10px var(--hub-purple-shadow);border-radius:8px;align-items:center;gap:8px;padding:7px 12px;text-decoration:none;transition:filter .15s,box-shadow .15s;display:flex}.qikqja_adBanner:hover{filter:brightness(1.1);box-shadow:0 4px 16px var(--hub-purple-shadow-strong)}.qikqja_adBadge{letter-spacing:.04em;color:#fff;white-space:nowrap;background:#ffffff29;border:1px solid #ffffff8c;border-radius:4px;flex-shrink:0;padding:3px 6px;font-size:10px;font-weight:700;line-height:1}.qikqja_adText{text-overflow:ellipsis;white-space:nowrap;color:#fff;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.qikqja_adArrow{color:#fff;flex-shrink:0;margin-left:auto;font-size:13px}.qikqja_searchRow{padding:0 2px;display:flex}.qikqja_search{width:50%;color:inherit;border:1px solid var(--hub-border-2);background:0 0;border-radius:6px;outline:none;padding:4px 9px;font-size:12px;line-height:18px;transition:border-color .12s}.qikqja_search::placeholder{color:var(--hub-text-tertiary)}.qikqja_search:focus{border-color:var(--hub-brand)}.qikqja_installedBtn,.qikqja_installedBtnActive,.qikqja_installedBtnDisabled{cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;flex-shrink:0;align-items:center;gap:5px;height:24px;padding:0 8px;font-size:12px;line-height:22px;transition:color .12s,background .12s;display:inline-flex}.qikqja_installedBtn{color:var(--hub-text-primary);background:0 0}.qikqja_installedBtn:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.qikqja_installedBtnDisabled,.qikqja_installedBtnDisabled:hover{color:var(--hub-text-disabled);cursor:not-allowed;background:0 0}.qikqja_installedBtnDisabled .qikqja_segCount{color:var(--hub-text-disabled);background:#8080800f}.qikqja_installedBtnActive{color:var(--hub-text-on-fill);background:var(--hub-btn-fill)}.qikqja_segCount,.qikqja_segCountActive{text-align:center;border-radius:999px;min-width:14px;padding:0 4px;font-size:10px;line-height:14px}.qikqja_segCount{color:var(--hub-text-tertiary);background:var(--hub-bg-btn)}.qikqja_installedBtnActive .qikqja_segCountActive{color:var(--hub-text-on-fill);background:var(--hub-bg-on-fill)}.qikqja_tabs{border-bottom:1px solid var(--hub-border-1);flex-wrap:wrap;align-items:center;gap:6px;padding:2px 2px 8px;display:flex}.qikqja_tab,.qikqja_tabActive{cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:999px;flex-shrink:0;align-items:center;gap:6px;padding:3px 10px;font-size:12px;line-height:18px;transition:color .12s,background .12s;display:inline-flex}.qikqja_tab{color:var(--hub-text-secondary);background:0 0}.qikqja_tab:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.qikqja_tabActive{color:var(--hub-text-on-fill);background:var(--hub-btn-fill)}.qikqja_tabCount{text-align:center;min-width:16px;color:var(--hub-text-tertiary);background:var(--hub-bg-btn);border-radius:999px;padding:0 5px;font-size:10px;line-height:14px}.qikqja_tabActive .qikqja_tabCount{color:var(--hub-text-on-fill);background:var(--hub-bg-on-fill)}.qikqja_failBtn{box-sizing:border-box;border:1px solid var(--hub-border-2);height:24px;color:var(--hub-text-primary);background:var(--hub-bg-hover);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;flex-shrink:0;align-items:center;margin-left:auto;padding:0 10px;font-size:12px;line-height:22px;transition:color .12s,background .12s;display:inline-flex;position:relative}.qikqja_failBtn:hover{color:var(--hub-text-primary);background:#80808047}.qikqja_failBadge{z-index:1;text-align:center;color:#fff;background:var(--hub-danger);border-radius:999px;min-width:16px;height:16px;padding:0 5px;font-size:10px;font-weight:600;line-height:16px;position:absolute;top:-16px;right:-7px;box-shadow:0 1px 4px #d1242f66}";
271
+ const css$4 = ".qikqja_root{min-width:0;height:100%;color:var(--hub-text-primary);flex-direction:column;gap:8px;display:flex}.qikqja_header{flex-direction:column;gap:2px;padding:2px 2px 0;display:flex}.qikqja_headerRight{flex-shrink:0;align-items:center;gap:2px;margin-left:auto;display:inline-flex}.qikqja_langBtn{height:24px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;padding:0 8px;font-size:12px;font-weight:600;transition:color .15s,background-color .15s;display:inline-flex}.qikqja_langBtn:hover{color:var(--hub-purple-1);background-color:var(--hub-purple-tint)}.qikqja_githubLink{color:var(--hub-text-tertiary);cursor:pointer;border-radius:6px;flex-shrink:0;align-items:center;padding:3px;text-decoration:none;transition:color .15s,background-color .15s;display:inline-flex}.qikqja_githubLink:hover{color:var(--hub-purple-1);background-color:var(--hub-purple-tint)}.qikqja_githubIcon{flex-shrink:0;display:block}.qikqja_aboutBtn{height:24px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;padding:0 8px;font-size:12px;font-weight:600;line-height:1;transition:color .15s,background-color .15s;display:inline-flex}.qikqja_aboutBtn:hover{color:var(--hub-purple-1);background-color:var(--hub-purple-tint)}.qikqja_headerTitleRow{align-items:center;gap:8px;min-width:0;display:flex}.qikqja_brandTitle{min-width:0;color:inherit;cursor:pointer;align-items:center;gap:10px;text-decoration:none;display:flex}.qikqja_taglineLink{min-width:0;max-width:100%;color:inherit;cursor:pointer;align-self:flex-start;text-decoration:none}.qikqja_title{margin:0;font-size:14px;font-weight:600;line-height:20px}.qikqja_version{color:var(--hub-text-secondary)}.qikqja_versionBtn{height:20px;color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:5px;flex-shrink:0;align-items:center;gap:5px;padding:0 6px;font-size:12px;font-weight:600;line-height:1;transition:color .12s;display:inline-flex}.qikqja_versionBtn:hover{color:var(--hub-text-secondary)}.qikqja_hubUpdateBadge{letter-spacing:.02em;color:#fff;background:var(--hub-danger);-webkit-user-select:none;user-select:none;border-radius:999px;flex-shrink:0;align-items:center;height:18px;padding:0 7px;font-size:11px;font-weight:700;line-height:1;transition:background .12s,box-shadow .12s,transform .12s;display:inline-flex;box-shadow:0 1px 4px #d1242f66}.qikqja_hubUpdateBadge:hover{background:var(--hub-danger-hover);transform:translateY(-1px);box-shadow:0 2px 8px #d1242f80}.qikqja_logoIcon{flex-shrink:0;display:block}.qikqja_copyIcon{flex-shrink:0}.qikqja_tagline{color:var(--hub-text-tertiary);white-space:nowrap;text-overflow:ellipsis;margin:0;font-size:12px;line-height:18px;overflow:hidden}.qikqja_controls{flex-shrink:0;align-items:center;gap:4px;display:flex}.qikqja_filterResults{color:var(--hub-text-tertiary);white-space:nowrap;flex-shrink:0;align-items:baseline;font-size:12px;line-height:18px;display:inline-flex}.qikqja_resultCount{font-variant-numeric:tabular-nums;text-align:center;min-width:5ch}.qikqja_adBanner{border:1px solid var(--hub-purple-border);background:linear-gradient(90deg, var(--hub-purple-1) 0%, var(--hub-purple-2) 100%);color:#fff;cursor:pointer;-webkit-user-select:none;user-select:none;box-shadow:0 2px 10px var(--hub-purple-shadow);border-radius:8px;align-items:center;gap:8px;padding:7px 12px;text-decoration:none;transition:filter .15s,box-shadow .15s;display:flex}.qikqja_adBanner:hover{filter:brightness(1.1);box-shadow:0 4px 16px var(--hub-purple-shadow-strong)}.qikqja_adBadge{letter-spacing:.04em;color:#fff;white-space:nowrap;background:#ffffff29;border:1px solid #ffffff8c;border-radius:4px;flex-shrink:0;padding:3px 6px;font-size:10px;font-weight:700;line-height:1}.qikqja_adText{text-overflow:ellipsis;white-space:nowrap;color:#fff;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.qikqja_adArrow{color:#fff;flex-shrink:0;margin-left:auto;font-size:13px}.qikqja_searchRow{padding:0 2px;display:flex}.qikqja_search{width:50%;color:inherit;border:1px solid var(--hub-border-2);background:0 0;border-radius:6px;outline:none;padding:4px 9px;font-size:12px;line-height:18px;transition:border-color .12s}.qikqja_search::placeholder{color:var(--hub-text-tertiary)}.qikqja_search:focus{border-color:var(--hub-brand)}.qikqja_installedBtn,.qikqja_installedBtnActive,.qikqja_installedBtnDisabled{cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;flex-shrink:0;align-items:center;gap:5px;height:24px;padding:0 8px;font-size:12px;line-height:22px;transition:color .12s,background .12s;display:inline-flex}.qikqja_installedBtn{color:var(--hub-text-primary);background:0 0}.qikqja_installedBtn:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.qikqja_installedBtnDisabled,.qikqja_installedBtnDisabled:hover{color:var(--hub-text-disabled);cursor:not-allowed;background:0 0}.qikqja_installedBtnDisabled .qikqja_segCount{color:var(--hub-text-disabled);background:#8080800f}.qikqja_installedBtnActive{color:var(--hub-text-on-fill);background:var(--hub-btn-fill)}.qikqja_segCount,.qikqja_segCountActive{text-align:center;border-radius:999px;min-width:14px;padding:0 4px;font-size:10px;line-height:14px}.qikqja_segCount{color:var(--hub-text-tertiary);background:var(--hub-bg-btn)}.qikqja_installedBtnActive .qikqja_segCountActive{color:var(--hub-text-on-fill);background:var(--hub-bg-on-fill)}.qikqja_tabs{border-bottom:1px solid var(--hub-border-1);flex-wrap:wrap;align-items:center;gap:6px;padding:2px 2px 8px;display:flex}.qikqja_tab,.qikqja_tabActive{cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:999px;flex-shrink:0;align-items:center;gap:6px;padding:3px 10px;font-size:12px;line-height:18px;transition:color .12s,background .12s;display:inline-flex}.qikqja_tab{color:var(--hub-text-secondary);background:0 0}.qikqja_tab:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.qikqja_tabActive{color:var(--hub-text-on-fill);background:var(--hub-btn-fill)}.qikqja_tabCount{text-align:center;min-width:16px;color:var(--hub-text-tertiary);background:var(--hub-bg-btn);border-radius:999px;padding:0 5px;font-size:10px;line-height:14px}.qikqja_tabActive .qikqja_tabCount{color:var(--hub-text-on-fill);background:var(--hub-bg-on-fill)}.qikqja_failBtn{box-sizing:border-box;border:1px solid var(--hub-border-2);height:24px;color:var(--hub-text-primary);background:var(--hub-bg-hover);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;flex-shrink:0;align-items:center;margin-left:auto;padding:0 10px;font-size:12px;line-height:22px;transition:color .12s,background .12s;display:inline-flex;position:relative}.qikqja_failBtn:hover{color:var(--hub-text-primary);background:#80808047}.qikqja_failBadge{z-index:1;text-align:center;color:#fff;background:var(--hub-danger);border-radius:999px;min-width:16px;height:16px;padding:0 5px;font-size:10px;font-weight:600;line-height:16px;position:absolute;top:-16px;right:-7px;box-shadow:0 1px 4px #d1242f66}";
236
272
  const tagId$4 = "dsh-plugin/Header.module.css";
237
273
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
238
274
  const tag = document.createElement("style");
@@ -242,40 +278,43 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
242
278
  document.head.appendChild(tag);
243
279
  }
244
280
  var Header_module_css_default = {
245
- "adText": "qikqja_adText",
246
- "tab": "qikqja_tab",
247
- "copyIcon": "qikqja_copyIcon",
248
- "filterResults": "qikqja_filterResults",
249
- "failBadge": "qikqja_failBadge",
250
- "headerRight": "qikqja_headerRight",
251
- "brandTitle": "qikqja_brandTitle",
281
+ "githubIcon": "qikqja_githubIcon",
282
+ "installedBtnActive": "qikqja_installedBtnActive",
252
283
  "taglineLink": "qikqja_taglineLink",
253
- "search": "qikqja_search",
284
+ "tagline": "qikqja_tagline",
254
285
  "installedBtn": "qikqja_installedBtn",
255
- "tabCount": "qikqja_tabCount",
286
+ "installedBtnDisabled": "qikqja_installedBtnDisabled",
287
+ "searchRow": "qikqja_searchRow",
288
+ "segCount": "qikqja_segCount",
256
289
  "resultCount": "qikqja_resultCount",
290
+ "title": "qikqja_title",
257
291
  "segCountActive": "qikqja_segCountActive",
258
- "adArrow": "qikqja_adArrow",
259
- "controls": "qikqja_controls",
260
- "installedBtnDisabled": "qikqja_installedBtnDisabled",
261
- "root": "qikqja_root",
262
292
  "githubLink": "qikqja_githubLink",
293
+ "tabActive": "qikqja_tabActive",
294
+ "failBadge": "qikqja_failBadge",
263
295
  "header": "qikqja_header",
264
- "logoIcon": "qikqja_logoIcon",
265
- "tabs": "qikqja_tabs",
296
+ "tab": "qikqja_tab",
297
+ "search": "qikqja_search",
298
+ "tabCount": "qikqja_tabCount",
299
+ "headerRight": "qikqja_headerRight",
300
+ "brandTitle": "qikqja_brandTitle",
301
+ "controls": "qikqja_controls",
302
+ "filterResults": "qikqja_filterResults",
303
+ "adArrow": "qikqja_adArrow",
304
+ "root": "qikqja_root",
266
305
  "adBanner": "qikqja_adBanner",
267
- "failBtn": "qikqja_failBtn",
268
- "githubIcon": "qikqja_githubIcon",
269
306
  "adBadge": "qikqja_adBadge",
270
- "headerTitleRow": "qikqja_headerTitleRow",
271
- "tagline": "qikqja_tagline",
272
- "title": "qikqja_title",
273
- "installedBtnActive": "qikqja_installedBtnActive",
274
- "segCount": "qikqja_segCount",
275
- "langBtn": "qikqja_langBtn",
307
+ "logoIcon": "qikqja_logoIcon",
276
308
  "version": "qikqja_version",
277
- "tabActive": "qikqja_tabActive",
278
- "searchRow": "qikqja_searchRow"
309
+ "versionBtn": "qikqja_versionBtn",
310
+ "failBtn": "qikqja_failBtn",
311
+ "adText": "qikqja_adText",
312
+ "aboutBtn": "qikqja_aboutBtn",
313
+ "headerTitleRow": "qikqja_headerTitleRow",
314
+ "hubUpdateBadge": "qikqja_hubUpdateBadge",
315
+ "copyIcon": "qikqja_copyIcon",
316
+ "tabs": "qikqja_tabs",
317
+ "langBtn": "qikqja_langBtn"
279
318
  };
280
319
  //#endregion
281
320
  //#region src/client/lib/failures.ts
@@ -409,11 +448,21 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
409
448
  /** 插件中心源码仓库:头部右上角 GitHub 图标的跳转地址 */
410
449
  const GITHUB_URL = "https://github.com/dshplugin/dsh-plugin-hub";
411
450
  /**
451
+ * Hub 自我更新版本控制中心(Cloudflare Worker:dsh-update)。
452
+ * 发新版后向 Worker 管理接口写入最新版本 + Markdown 变更记录(见
453
+ * dsh-update-worker 的 POST /admin/hub),所有已装用户的「可更新」徽标即时出现,
454
+ * 不再依赖主站目录数据管道(每日刷新 + 重建站点)。
455
+ * 响应:{ version: string | null, publishedAt: string | null, notes: string | {zh,en} | null }
456
+ */
457
+ const HUB_UPDATE_URL = "https://hub.dsh-plugin.org/hub";
458
+ /** Worker「关注我们」内容接口(同款 Worker,key = hub:about,Markdown 推送非写死)。 */
459
+ const HUB_ABOUT_URL = "https://hub.dsh-plugin.org/about";
460
+ /**
412
461
  * 插件当前版本号,供头部标题展示「DSH-Plugin Hub v0.1.1」。
413
462
  * tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;
414
463
  * node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。
415
464
  */
416
- const PLUGIN_VERSION = "1.1.0";
465
+ const PLUGIN_VERSION = "1.1.1";
417
466
  /** dsh-plugin.org 中文页挂在 /zh/ 前缀下,英文在根路径。 */
418
467
  function langPathOf(lang) {
419
468
  return lang === "zh" ? "zh/" : "";
@@ -540,6 +589,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
540
589
  repo: typeof raw.r.repo === "string" ? raw.r.repo : void 0,
541
590
  npmPackage: typeof raw.r.npmPackage === "string" ? raw.r.npmPackage : void 0
542
591
  } : void 0,
592
+ install: raw.wi === false ? { webInstallable: false } : void 0,
543
593
  compatibility: typeof raw.v === "string" ? { status: raw.v } : void 0,
544
594
  dates: {
545
595
  repoUpdatedAt: typeof raw.u === "string" ? raw.u : void 0,
@@ -691,6 +741,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
691
741
  */
692
742
  const PLUGINS_URL = (lang) => `https://dsh-plugin.org/api/plugins.${lang}.json`;
693
743
  const STATS_URL = "https://dsh-plugin.org/api/stats.json";
744
+ /** 插件市场自身仓库:DSH-Plugin Hub 不显示在目录里(自己不进自己的插件列表) */
745
+ const SELF_REPO = "dshplugin/dsh-plugin-hub";
694
746
  function useCatalog(lang) {
695
747
  /** 目录插件(仅保留人工验证通过的条目) */
696
748
  const [plugins, setPlugins] = (0, react.useState)(null);
@@ -708,6 +760,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
708
760
  /** 安装时记录的目录信号:repo(小写) -> { version, updatedAt }(来自宿主本地路由);
709
761
  * npmPackage 为 npm 优先通道反查命中的包名映射(目录数据未下发时客户端靠它把依赖 key 匹配回仓库) */
710
762
  const [versions, setVersions] = (0, react.useState)({});
763
+ /** Hub 自我更新信息:来自 CF Worker 版本控制中心(hub.dsh-plugin.org),与目录数据解耦 */
764
+ const [hubUpdateInfo, setHubUpdateInfo] = (0, react.useState)(null);
765
+ /** 头部「关注我们」弹窗内容(平台介绍 + 反馈群二维码):来自同款 Worker /about,Markdown 推送非写死 */
766
+ const [hubAboutInfo, setHubAboutInfo] = (0, react.useState)(null);
711
767
  (0, react.useEffect)(() => {
712
768
  let cancelled = false;
713
769
  setPlugins(null);
@@ -717,20 +773,23 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
717
773
  if (!res.ok) throw new Error(String(res.status));
718
774
  return res.json();
719
775
  });
720
- fetchData(PLUGINS_URL(lang)).then((data) => {
776
+ const load = () => Promise.all([fetchData(PLUGINS_URL(lang)), fetchData(STATS_URL)]);
777
+ load().then(([data, s]) => {
721
778
  if (cancelled) return;
722
779
  const list = (Array.isArray(data) ? data : []).map((item) => normalize(item));
723
- setPlugins(list.filter((p) => p.compatibility?.status === "verified"));
724
- }).catch(() => {
725
- if (!cancelled) setFailed(true);
726
- });
727
- fetchData(STATS_URL).then((s) => {
780
+ const hadSelf = list.some((p) => p.source?.repo === SELF_REPO);
781
+ setPlugins(list.filter((p) => p.compatibility?.status === "verified" && p.source?.repo !== SELF_REPO));
728
782
  const stats = s;
729
- if (!cancelled && stats && typeof stats.total === "number" && typeof stats.verified === "number") setStats({
783
+ if (stats && typeof stats.total === "number" && typeof stats.verified === "number") setStats(hadSelf ? {
784
+ total: stats.total - 1,
785
+ verified: stats.verified - 1
786
+ } : {
730
787
  total: stats.total,
731
788
  verified: stats.verified
732
789
  });
733
- }).catch(() => {});
790
+ }).catch(() => {
791
+ if (!cancelled) setFailed(true);
792
+ });
734
793
  return () => {
735
794
  cancelled = true;
736
795
  };
@@ -748,6 +807,46 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
748
807
  (0, react.useEffect)(() => {
749
808
  refreshInstalled();
750
809
  }, []);
810
+ (0, react.useEffect)(() => {
811
+ let cancelled = false;
812
+ fetch(HUB_UPDATE_URL, { cache: "no-store" }).then((res) => res.ok ? res.json() : Promise.resolve(null)).then((data) => {
813
+ if (cancelled || !data) {
814
+ if (!cancelled) setHubUpdateInfo(null);
815
+ return;
816
+ }
817
+ const version = typeof data.version === "string" && data.version.length > 0 ? data.version : null;
818
+ setHubUpdateInfo(version === null ? null : {
819
+ version,
820
+ publishedAt: data.publishedAt ?? null,
821
+ notes: data.notes ?? null
822
+ });
823
+ }).catch(() => {
824
+ if (!cancelled) setHubUpdateInfo(null);
825
+ });
826
+ return () => {
827
+ cancelled = true;
828
+ };
829
+ }, [reloadKey]);
830
+ (0, react.useEffect)(() => {
831
+ let cancelled = false;
832
+ fetch(HUB_ABOUT_URL, { cache: "no-store" }).then((res) => res.ok ? res.json() : Promise.resolve(null)).then((data) => {
833
+ if (cancelled) return;
834
+ if (!data || data.content === null || data.content === void 0) {
835
+ setHubAboutInfo(null);
836
+ return;
837
+ }
838
+ const content = typeof data.content === "string" || typeof data.content === "object" ? data.content : null;
839
+ setHubAboutInfo(content === null ? null : {
840
+ content,
841
+ updatedAt: data.updatedAt ?? null
842
+ });
843
+ }).catch(() => {
844
+ if (!cancelled) setHubAboutInfo(null);
845
+ });
846
+ return () => {
847
+ cancelled = true;
848
+ };
849
+ }, [reloadKey]);
751
850
  /** 插件是否已安装:匹配 installed spec 中的 `github:<owner>/<repo>`,或 npm 通道安装的依赖包名;命中返回 npm 包名。 */
752
851
  const installedName = (p) => {
753
852
  const repo = p.source?.repo;
@@ -781,6 +880,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
781
880
  const current = p.dates?.repoUpdatedAt;
782
881
  return Boolean(current && rec.updatedAt && current > rec.updatedAt);
783
882
  };
883
+ /**
884
+ * Hub 自身是否有可用更新:Hub 就是当前运行的应用(始终已安装,无需 installedName 命中)。
885
+ * 以 Worker 版本控制中心返回的「最新版本」为准,与当前运行的版本号比对——
886
+ * 构建时注入的 PLUGIN_VERSION 是运行 bundle 的真实版本;测试/异常场景缺失时
887
+ * 回退到安装时记录的版本。版本号不等即新版(版本号只在发版时变更,绝无降级场景)。
888
+ */
889
+ const hubHasUpdate = (() => {
890
+ if (!hubUpdateInfo) return false;
891
+ return hubUpdateInfo.version !== "1.1.1";
892
+ })();
784
893
  /** 当前分类下的插件(「全部」时为整个目录)。 */
785
894
  const categoryPlugins = (0, react.useMemo)(() => {
786
895
  if (!plugins) return [];
@@ -839,6 +948,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
839
948
  installedName,
840
949
  installedVersion,
841
950
  hasUpdate,
951
+ hubHasUpdate,
952
+ hubUpdateInfo,
953
+ hubAboutInfo,
842
954
  refreshInstalled,
843
955
  category,
844
956
  setCategory,
@@ -967,14 +1079,14 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
967
1079
  refreshInstalled();
968
1080
  if (q.kind === "uninstall") {
969
1081
  syncInstalledVersion(q.repo, void 0, void 0);
970
- onUninstallDone(modalTaskRef.current === q.id, q.repo);
1082
+ onUninstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart);
971
1083
  } else {
972
1084
  syncInstalledVersion(q.repo, q.version, q.updatedAt);
973
1085
  pendingInfoRef.current.set(q.target, {
974
1086
  desc: q.desc,
975
1087
  version: q.version
976
1088
  });
977
- onInstallDone(modalTaskRef.current === q.id, q.repo);
1089
+ onInstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart);
978
1090
  }
979
1091
  } else {
980
1092
  const detail = lines.length > 0 ? [...lines].reverse().join("\n") : q.kind === "uninstall" ? t("uninstallFail") : t("installFail");
@@ -1017,23 +1129,33 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1017
1129
  try {
1018
1130
  const res = await fetch(`/dsh-plugin-hub/status?task=${q.id}`, { cache: "no-store" });
1019
1131
  if (res.ok) {
1020
- const data = await res.json();
1021
- status = data.task?.status ?? "failed";
1022
- lines = data.task?.lines ?? [];
1023
- attempts = Array.isArray(data.task?.attempts) ? data.task.attempts : void 0;
1132
+ const task = (await res.json()).task;
1133
+ if (task !== void 0) {
1134
+ status = task.status ?? "failed";
1135
+ lines = task.lines ?? [];
1136
+ attempts = Array.isArray(task.attempts) ? task.attempts : void 0;
1137
+ const needsRestart = typeof task.needsRestart === "boolean" ? task.needsRestart : q.needsRestart;
1138
+ if (status === "done") {
1139
+ const settled = {
1140
+ ...q,
1141
+ needsRestart
1142
+ };
1143
+ if (q.kind === "uninstall") settleDone(settled, lines);
1144
+ else finishQueueTask(true, settled, lines);
1145
+ return;
1146
+ }
1147
+ if (status === "failed") {
1148
+ finishQueueTask(false, {
1149
+ ...q,
1150
+ attempts
1151
+ }, lines);
1152
+ return;
1153
+ }
1154
+ }
1024
1155
  }
1025
1156
  } catch {}
1026
- if (status === "done") {
1027
- if (q.kind === "uninstall") settleDone(q, lines);
1028
- else finishQueueTask(true, q, lines);
1029
- } else if (status === "failed") finishQueueTask(false, {
1030
- ...q,
1031
- attempts
1032
- }, lines);
1033
- else {
1034
- applyQueue((prev) => prev.filter((x) => x.id !== q.id));
1035
- maybeStopPoll();
1036
- }
1157
+ applyQueue((prev) => prev.filter((x) => x.id !== q.id));
1158
+ maybeStopPoll();
1037
1159
  };
1038
1160
  /** 轮询整个队列:合并服务端 /active(running 在前、pending 在后),
1039
1161
  * 消失的任务查终态收尾;队列清空即停止轮询。 */
@@ -1065,7 +1187,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1065
1187
  status: a.status === "running" ? "running" : "pending",
1066
1188
  progress: typeof a.progress === "number" ? a.progress : prevTask?.progress ?? 0,
1067
1189
  lines: Array.isArray(a.lines) ? a.lines : prevTask?.lines ?? [],
1068
- attempts: Array.isArray(a.attempts) ? a.attempts : prevTask?.attempts ?? []
1190
+ attempts: Array.isArray(a.attempts) ? a.attempts : prevTask?.attempts ?? [],
1191
+ needsRestart: typeof a.needsRestart === "boolean" ? a.needsRestart : prevTask?.needsRestart ?? true
1069
1192
  });
1070
1193
  }
1071
1194
  const keepOpt = prev.filter((q) => q.optimistic && !next.some((x) => x.id === q.id));
@@ -1108,7 +1231,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1108
1231
  status: a.status === "running" ? "running" : "pending",
1109
1232
  progress: typeof a.progress === "number" ? a.progress : 0,
1110
1233
  lines: Array.isArray(a.lines) ? a.lines : [],
1111
- attempts: Array.isArray(a.attempts) ? a.attempts : []
1234
+ attempts: Array.isArray(a.attempts) ? a.attempts : [],
1235
+ needsRestart: typeof a.needsRestart === "boolean" ? a.needsRestart : true
1112
1236
  };
1113
1237
  });
1114
1238
  if (items.length > 0 || pendingRef.current.length > 0) {
@@ -1147,7 +1271,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1147
1271
  lines: [],
1148
1272
  optimistic: true,
1149
1273
  command: installCommandOf(p, true),
1150
- attempts: []
1274
+ attempts: [],
1275
+ needsRestart: true
1151
1276
  }]);
1152
1277
  setSubmitting(true);
1153
1278
  try {
@@ -1219,7 +1344,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1219
1344
  repo,
1220
1345
  status: "pending",
1221
1346
  progress: 0,
1222
- lines: []
1347
+ lines: [],
1348
+ needsRestart: true
1223
1349
  }]);
1224
1350
  pollQueue();
1225
1351
  } catch {
@@ -1266,7 +1392,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1266
1392
  }
1267
1393
  //#endregion
1268
1394
  //#region \0dsh-css:src/client/styles/Modal.module.css.mjs
1269
- const css$3 = ".BiQ1zG_overlay{z-index:998;-webkit-user-select:none;user-select:none;background:#00000061;justify-content:center;align-items:center;animation:.16s ease-out BiQ1zG_overlayIn;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}.BiQ1zG_modal,.BiQ1zG_errorModal{background:var(--hub-bg-1);border:1px solid var(--hub-border-2);border-radius:10px;flex-direction:column;gap:10px;width:420px;max-width:calc(100vw - 32px);max-height:calc(100vh - 64px);padding:14px 16px;animation:.18s ease-out BiQ1zG_modalIn;display:flex;box-shadow:0 12px 40px #0000003d}.BiQ1zG_errorModal{width:640px;max-width:calc(100vw - 48px)}.BiQ1zG_modalHead{flex-shrink:0;justify-content:space-between;align-items:center;gap:8px;display:flex}.BiQ1zG_modalTitle{color:var(--hub-text-primary);font-size:14px;font-weight:600;line-height:20px}.BiQ1zG_modalTitleBusy{color:var(--hub-brand)}.BiQ1zG_modalTitleQueued{color:var(--hub-warning)}.BiQ1zG_modalClose{width:24px;height:24px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;font-size:16px;line-height:1;display:inline-flex}.BiQ1zG_modalClose:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.BiQ1zG_modalCloseIcon{flex-shrink:0;width:14px;height:14px}.BiQ1zG_modalDesc{color:var(--hub-text-secondary);font-size:12px;line-height:18px}.BiQ1zG_trustHint{color:var(--hub-danger-text);background:var(--hub-danger-tint);border:1px solid var(--hub-danger-border-soft);border-radius:6px;padding:6px 10px;font-size:12px;font-weight:500;line-height:18px}.BiQ1zG_modalRow{align-items:baseline;gap:8px;min-width:0;font-size:12px;line-height:18px;display:flex}.BiQ1zG_modalLabel{min-width:64px;color:var(--hub-text-tertiary);flex-shrink:0}.BiQ1zG_modalValue{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-text-primary);font-weight:500;overflow:hidden}.BiQ1zG_modalLink{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:4px;font-weight:500;text-decoration:none;transition:color .12s;display:inline-flex;overflow:hidden}.BiQ1zG_modalLink:hover{color:var(--hub-brand-hover);text-decoration:underline}.BiQ1zG_linkIcon{flex-shrink:0}.BiQ1zG_modalCmd{color:var(--hub-text-primary);background:var(--hub-bg-2);border:1px solid var(--hub-border-2);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;justify-content:space-between;align-items:center;gap:8px;padding:6px 6px 6px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:18px;transition:border-color .12s,background .12s;display:flex}.BiQ1zG_modalCmd:hover{border-color:var(--hub-border-ghost);background:var(--hub-bg-3)}.BiQ1zG_modalCmdText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.BiQ1zG_modalCmdCopy{color:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:4px;flex-shrink:0;align-items:center;gap:3px;padding:1px 7px;font-family:inherit;font-size:11px;line-height:16px;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_modalCmdCopy:hover{color:var(--hub-brand-hover);background:var(--hub-bg-2)}.BiQ1zG_modalActions{justify-content:flex-end;align-items:center;gap:8px;margin-top:2px;display:flex}.BiQ1zG_modalBody{flex-direction:column;flex:auto;gap:10px;min-height:0;display:flex;overflow-y:auto}.BiQ1zG_toast{z-index:1000;background:var(--hub-btn-fill);color:var(--hub-text-on-fill);pointer-events:none;white-space:nowrap;border:none;border-radius:8px;padding:10px 16px;font-size:12px;font-weight:500;line-height:18px;animation:.22s ease-out BiQ1zG_toastIn;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 6px 24px #00000047}@keyframes BiQ1zG_toastIn{0%{opacity:0;transform:translate(-50%,-44%)}to{opacity:1;transform:translate(-50%,-50%)}}.BiQ1zG_toastFail{background:var(--hub-danger);color:#fff;border-color:#ffffff3d}.BiQ1zG_queueSection{flex-direction:column;gap:6px;display:flex}.BiQ1zG_queueSectionTitle{color:var(--hub-text-secondary);padding:4px 2px 0;font-size:12px;font-weight:600;line-height:18px}.BiQ1zG_pendingRowStatus{color:var(--hub-warn);flex-shrink:0;font-weight:500}.BiQ1zG_pendingRowActions{flex-shrink:0;gap:8px;margin-left:auto;display:flex}.BiQ1zG_queueRow{border:1px solid var(--hub-border-2);background:var(--hub-bg-2);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:8px;flex-direction:column;gap:5px;padding:8px 10px;font-size:12px;line-height:18px;transition:background .12s;display:flex}.BiQ1zG_queueRow:hover{background:var(--hub-brand-tint)}.BiQ1zG_queueRowHead{align-items:center;gap:10px;display:flex}.BiQ1zG_queueRowTarget{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-text-primary);flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow:hidden}.BiQ1zG_queueRowDesc{color:var(--hub-text-tertiary);-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.BiQ1zG_queueRowBody{align-items:center;gap:8px;display:flex}.BiQ1zG_queueRowStatus{color:var(--hub-brand);flex-shrink:0;font-weight:500}.BiQ1zG_queueRowTrack{flex:1;min-width:0}.BiQ1zG_queueRowPct{color:var(--hub-text-tertiary);font-variant-numeric:tabular-nums;flex-shrink:0}.BiQ1zG_stripCancel{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;padding:2px 10px;font-size:12px;line-height:18px;transition:background .12s,color .12s}.BiQ1zG_stripCancel:hover{background:var(--hub-danger-tint);color:var(--hub-danger-text)}.BiQ1zG_stripCancel:disabled{opacity:.45;cursor:default}.BiQ1zG_queuedHint{color:var(--hub-brand);background:var(--hub-brand-tint);border:1px solid var(--hub-brand-border-soft);border-radius:6px;padding:5px 10px;font-size:12px;line-height:18px}.BiQ1zG_errorTitle{color:var(--hub-danger-text);font-size:14px;font-weight:600;line-height:20px}.BiQ1zG_errorBox{border:1px solid var(--hub-danger-border);background:var(--hub-danger-tint-weak);max-height:240px;color:var(--hub-text-primary);white-space:pre-wrap;word-break:break-word;-webkit-user-select:none;user-select:none;border-radius:6px;margin:0;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:17px;overflow:auto}.BiQ1zG_errorCopySoft{color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:4px;flex-shrink:0;align-items:center;padding:2px 8px;font-size:11px;line-height:16px;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_errorCopySoft:hover{color:var(--hub-text-secondary);background:var(--hub-bg-2)}.BiQ1zG_errorHint{color:var(--hub-text-tertiary);font-size:12px;line-height:18px}.BiQ1zG_modalCancel,.BiQ1zG_modalCopy{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;padding:5px 14px;font-size:12px;line-height:18px;transition:color .12s,background .12s}.BiQ1zG_modalCancel:hover,.BiQ1zG_modalCopy:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.BiQ1zG_modalInstall{color:var(--hub-text-on-fill);background:var(--hub-btn-fill);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;padding:5px 14px;font-size:12px;font-weight:600;line-height:18px;transition:background .12s}.BiQ1zG_modalInstall:hover{background:var(--hub-btn-hover)}.BiQ1zG_modalCopy:disabled,.BiQ1zG_modalInstall:disabled,.BiQ1zG_modalCancel:disabled,.BiQ1zG_modalClose:disabled,.BiQ1zG_uninstallConfirm:disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.BiQ1zG_uninstallConfirm{color:#fff;background:var(--hub-danger);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;padding:5px 14px;font-size:12px;font-weight:600;line-height:18px;transition:background .12s}.BiQ1zG_uninstallConfirm:hover{background:var(--hub-danger-hover)}.BiQ1zG_result{text-align:center;flex-direction:column;align-items:center;gap:5px;padding:10px 0 2px;display:flex}.BiQ1zG_resultCheck{background:var(--hub-success-tint);width:40px;height:40px;color:var(--hub-success);border-radius:50%;justify-content:center;align-items:center;margin-bottom:3px;display:inline-flex}.BiQ1zG_resultCheckIcon{flex-shrink:0;width:20px;height:20px}.BiQ1zG_resultTitle{color:var(--hub-text-primary);font-size:13px;font-weight:600;line-height:20px}.BiQ1zG_resultDesc{color:var(--hub-text-secondary);font-size:12px;line-height:18px}.BiQ1zG_resultRestarting{color:var(--hub-text-tertiary);padding:12px 0 6px;font-size:12px;line-height:18px}.BiQ1zG_restartLater{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;padding:5px 14px;font-size:12px;line-height:18px;transition:color .12s,background .12s}.BiQ1zG_restartLater:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.BiQ1zG_restartNow{color:var(--hub-text-on-fill);background:var(--hub-btn-fill);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;padding:5px 14px;font-size:12px;font-weight:600;line-height:18px;transition:background .12s}.BiQ1zG_restartNow:hover{background:var(--hub-btn-hover)}.BiQ1zG_restartNow:disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.BiQ1zG_result .BiQ1zG_modalActions{justify-content:center;gap:10px;margin-top:0;padding:6px 0 2px}.BiQ1zG_result .BiQ1zG_modalActions .BiQ1zG_restartLater,.BiQ1zG_result .BiQ1zG_modalActions .BiQ1zG_restartNow{min-width:100px}.BiQ1zG_progress{margin:10px 0 2px}.BiQ1zG_progressHead{justify-content:flex-end;align-items:center;margin-bottom:3px;display:flex}.BiQ1zG_progressText{color:var(--hub-text-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:14px}.BiQ1zG_progressTrack{background:var(--hub-border-2);border-radius:2px;height:4px;overflow:hidden}.BiQ1zG_progressFill{background:var(--hub-brand);border-radius:2px;height:100%;transition:width .32s}.BiQ1zG_progressFillFail{background:var(--hub-danger)}@keyframes BiQ1zG_overlayIn{0%{opacity:0}to{opacity:1}}@keyframes BiQ1zG_modalIn{0%{opacity:0;transform:translateY(6px)scale(.98)}to{opacity:1;transform:translateY(0)scale(1)}}.BiQ1zG_noticeList{flex-direction:column;gap:10px;padding-right:2px;display:flex}.BiQ1zG_noticeRow{border:1px solid var(--hub-border-2);background:var(--hub-bg-2);border-radius:8px;flex-direction:column;align-items:stretch;gap:6px;padding:10px 12px;display:flex}.BiQ1zG_noticeRowMain{align-items:center;gap:10px;width:100%;min-width:0;display:flex}.BiQ1zG_noticeBadgeOk,.BiQ1zG_noticeBadgeFail{border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:28px;height:28px;display:inline-flex;box-shadow:0 2px 6px #0000002e}.BiQ1zG_noticeBadgeOk{background:var(--hub-success)}.BiQ1zG_noticeBadgeFail{background:var(--hub-danger)}.BiQ1zG_noticeBadgeIcon{flex-shrink:0;width:12px;height:12px}.BiQ1zG_noticeMain{flex-direction:column;flex:1;gap:8px;min-width:0;display:flex}.BiQ1zG_noticeHead{align-items:center;gap:8px;min-width:0;display:flex}.BiQ1zG_noticeTextOk{color:var(--hub-success);flex-shrink:0;font-size:12px;font-weight:600;line-height:18px}.BiQ1zG_noticeTextFail{color:var(--hub-danger-text);flex-shrink:0;font-size:12px;font-weight:600;line-height:18px}.BiQ1zG_failList{flex-direction:column;gap:12px;padding-right:2px;display:flex}.BiQ1zG_failRow{border:1px solid var(--hub-border-2);background:var(--hub-bg-2);border-radius:8px;flex-direction:column;gap:8px;padding:10px 12px;display:flex}.BiQ1zG_failHead{align-items:center;gap:8px;min-width:0;display:flex}.BiQ1zG_failKind{border:1px solid #0000;border-radius:4px;flex-shrink:0;padding:0 6px;font-size:10px;font-weight:500;line-height:16px}.BiQ1zG_failKindInstall{color:var(--hub-danger-text);border-color:var(--hub-danger-border);background:var(--hub-danger-tint)}.BiQ1zG_failKindUninstall{color:var(--hub-warn);border-color:var(--hub-warn-border);background:var(--hub-warn-tint)}.BiQ1zG_failRepo{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:18px;text-decoration:none;overflow:hidden}.BiQ1zG_failRepo:hover{text-decoration:underline}.BiQ1zG_noticeFoot{justify-content:flex-end;align-items:center;display:flex}.BiQ1zG_noticeTime{color:var(--hub-text-tertiary);font-variant-numeric:tabular-nums;flex-shrink:0;font-size:11px;line-height:16px}.BiQ1zG_noticeRemove{width:22px;height:22px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:5px;flex-shrink:0;justify-content:center;align-items:center;margin-left:auto;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_noticeRemove:hover{color:var(--hub-danger-text);background:var(--hub-danger-tint)}.BiQ1zG_failCopy{color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:4px;flex-shrink:0;align-items:center;padding:2px 8px;font-size:11px;line-height:16px;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_failCopy:hover{color:var(--hub-text-secondary);background:var(--hub-bg-2)}.BiQ1zG_failEmpty{text-align:center;color:var(--hub-text-tertiary);padding:24px 0;font-size:12px;line-height:18px}.BiQ1zG_failClear{color:var(--hub-danger);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;padding:5px 14px;font-size:12px;line-height:18px;transition:color .12s,background .12s}.BiQ1zG_failClear:hover{color:#fff;background:var(--hub-danger)}.BiQ1zG_failBigIssue{box-sizing:border-box;text-align:center;color:#fff;background:var(--hub-danger);border:1px solid var(--hub-danger);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:8px;width:100%;margin-top:4px;padding:3px 16px;font-size:13px;font-weight:600;line-height:18px;text-decoration:none;transition:background .12s,border-color .12s,box-shadow .12s;display:block}.BiQ1zG_failBigIssue:hover{background:var(--hub-danger-hover);border-color:var(--hub-danger-hover);box-shadow:0 3px 10px #d1242f59}.BiQ1zG_failPrepareHint{color:var(--hub-warning);background:var(--hub-warning-tint);border:1px solid var(--hub-warning-border);border-radius:6px;margin-top:6px;padding:8px 12px;font-size:12px;line-height:18px}";
1395
+ const css$3 = ".BiQ1zG_overlay{z-index:998;-webkit-user-select:none;user-select:none;background:#00000061;justify-content:center;align-items:center;animation:.16s ease-out BiQ1zG_overlayIn;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}.BiQ1zG_modal,.BiQ1zG_errorModal{background:var(--hub-bg-1);border:1px solid var(--hub-border-2);border-radius:10px;flex-direction:column;gap:10px;width:420px;max-width:calc(100vw - 32px);max-height:calc(100vh - 64px);padding:14px 16px;animation:.18s ease-out BiQ1zG_modalIn;display:flex;box-shadow:0 12px 40px #0000003d}.BiQ1zG_errorModal{width:640px;max-width:calc(100vw - 48px)}.BiQ1zG_modalHead{flex-shrink:0;justify-content:space-between;align-items:center;gap:8px;display:flex}.BiQ1zG_modalTitle{color:var(--hub-text-primary);font-size:14px;font-weight:600;line-height:20px}.BiQ1zG_modalTitleBusy{color:var(--hub-brand)}.BiQ1zG_modalTitleQueued{color:var(--hub-warning)}.BiQ1zG_modalClose{width:24px;height:24px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;justify-content:center;align-items:center;font-size:16px;line-height:1;display:inline-flex}.BiQ1zG_modalClose:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.BiQ1zG_modalCloseIcon{flex-shrink:0;width:14px;height:14px}.BiQ1zG_modalDesc{color:var(--hub-text-secondary);font-size:12px;line-height:18px}.BiQ1zG_trustHint{color:var(--hub-danger-text);background:var(--hub-danger-tint);border:1px solid var(--hub-danger-border-soft);border-radius:6px;padding:6px 10px;font-size:12px;font-weight:500;line-height:18px}.BiQ1zG_cliOnlyHint{color:var(--hub-text-secondary);background:var(--hub-bg-hover);border-radius:6px;padding:6px 10px;font-size:12px;line-height:18px}.BiQ1zG_failedCopyHint{color:var(--hub-danger-text);background:var(--hub-danger-tint);border:1px solid var(--hub-danger-border-soft);border-radius:6px;padding:6px 10px;font-size:12px;font-weight:500;line-height:18px}.BiQ1zG_modalRow{align-items:baseline;gap:8px;min-width:0;font-size:12px;line-height:18px;display:flex}.BiQ1zG_modalLabel{min-width:64px;color:var(--hub-text-tertiary);flex-shrink:0}.BiQ1zG_modalValue{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-text-primary);font-weight:500;overflow:hidden}.BiQ1zG_modalLink{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:4px;font-weight:500;text-decoration:none;transition:color .12s;display:inline-flex;overflow:hidden}.BiQ1zG_modalLink:hover{color:var(--hub-brand-hover);text-decoration:underline}.BiQ1zG_linkIcon{flex-shrink:0}.BiQ1zG_modalCmd{color:var(--hub-text-primary);background:var(--hub-bg-2);border:1px solid var(--hub-border-2);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;justify-content:space-between;align-items:center;gap:8px;padding:6px 6px 6px 10px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:18px;transition:border-color .12s,background .12s;display:flex}.BiQ1zG_modalCmd:hover{border-color:var(--hub-border-ghost);background:var(--hub-bg-3)}.BiQ1zG_modalCmdText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.BiQ1zG_modalCmdCopy{color:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:4px;flex-shrink:0;align-items:center;gap:3px;padding:1px 7px;font-family:inherit;font-size:11px;line-height:16px;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_modalCmdCopy:hover{color:var(--hub-brand-hover);background:var(--hub-bg-2)}.BiQ1zG_modalActions{justify-content:flex-end;align-items:center;gap:8px;margin-top:2px;display:flex}.BiQ1zG_modalBody{flex-direction:column;flex:auto;gap:10px;min-height:0;display:flex;overflow-y:auto}.BiQ1zG_toast{z-index:1000;background:var(--hub-btn-fill);color:var(--hub-text-on-fill);pointer-events:none;white-space:nowrap;border:none;border-radius:8px;padding:10px 16px;font-size:12px;font-weight:500;line-height:18px;animation:.22s ease-out BiQ1zG_toastIn;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 6px 24px #00000047}@keyframes BiQ1zG_toastIn{0%{opacity:0;transform:translate(-50%,-44%)}to{opacity:1;transform:translate(-50%,-50%)}}.BiQ1zG_toastFail{background:var(--hub-danger);color:#fff;border-color:#ffffff3d}.BiQ1zG_queueSection{flex-direction:column;gap:6px;display:flex}.BiQ1zG_queueSectionTitle{color:var(--hub-text-secondary);padding:4px 2px 0;font-size:12px;font-weight:600;line-height:18px}.BiQ1zG_pendingRowStatus{color:var(--hub-warn);flex-shrink:0;font-weight:500}.BiQ1zG_pendingRowActions{flex-shrink:0;gap:8px;margin-left:auto;display:flex}.BiQ1zG_queueRow{border:1px solid var(--hub-border-2);background:var(--hub-bg-2);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:8px;flex-direction:column;gap:5px;padding:8px 10px;font-size:12px;line-height:18px;transition:background .12s;display:flex}.BiQ1zG_queueRow:hover{background:var(--hub-brand-tint)}.BiQ1zG_queueRowHead{align-items:center;gap:10px;display:flex}.BiQ1zG_queueRowTarget{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-text-primary);flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;overflow:hidden}.BiQ1zG_queueRowDesc{color:var(--hub-text-tertiary);-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.BiQ1zG_queueRowBody{align-items:center;gap:8px;display:flex}.BiQ1zG_queueRowStatus{color:var(--hub-brand);flex-shrink:0;font-weight:500}.BiQ1zG_queueRowTrack{flex:1;min-width:0}.BiQ1zG_queueRowPct{color:var(--hub-text-tertiary);font-variant-numeric:tabular-nums;flex-shrink:0}.BiQ1zG_stripCancel{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;flex-shrink:0;padding:2px 10px;font-size:12px;line-height:18px;transition:background .12s,color .12s}.BiQ1zG_stripCancel:hover{background:var(--hub-danger-tint);color:var(--hub-danger-text)}.BiQ1zG_stripCancel:disabled{opacity:.45;cursor:default}.BiQ1zG_queuedHint{color:var(--hub-brand);background:var(--hub-brand-tint);border:1px solid var(--hub-brand-border-soft);border-radius:6px;padding:5px 10px;font-size:12px;line-height:18px}.BiQ1zG_errorTitle{color:var(--hub-danger-text);font-size:14px;font-weight:600;line-height:20px}.BiQ1zG_errorBox{border:1px solid var(--hub-danger-border);background:var(--hub-danger-tint-weak);max-height:240px;color:var(--hub-text-primary);white-space:pre-wrap;word-break:break-word;-webkit-user-select:none;user-select:none;border-radius:6px;margin:0;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:17px;overflow:auto}.BiQ1zG_errorCopySoft{color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:4px;flex-shrink:0;align-items:center;padding:2px 8px;font-size:11px;line-height:16px;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_errorCopySoft:hover{color:var(--hub-text-secondary);background:var(--hub-bg-2)}.BiQ1zG_errorHint{color:var(--hub-text-tertiary);font-size:12px;line-height:18px}.BiQ1zG_modalCancel,.BiQ1zG_modalCopy{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;padding:5px 14px;font-size:12px;line-height:18px;transition:color .12s,background .12s}.BiQ1zG_modalCancel:hover,.BiQ1zG_modalCopy:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.BiQ1zG_modalInstall{color:var(--hub-text-on-fill);background:var(--hub-btn-fill);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;padding:5px 14px;font-size:12px;font-weight:600;line-height:18px;transition:background .12s}.BiQ1zG_modalInstall:hover{background:var(--hub-btn-hover)}.BiQ1zG_modalCopy:disabled,.BiQ1zG_modalInstall:disabled,.BiQ1zG_modalCancel:disabled,.BiQ1zG_modalClose:disabled,.BiQ1zG_uninstallConfirm:disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.BiQ1zG_uninstallConfirm{color:#fff;background:var(--hub-danger);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;padding:5px 14px;font-size:12px;font-weight:600;line-height:18px;transition:background .12s}.BiQ1zG_uninstallConfirm:hover{background:var(--hub-danger-hover)}.BiQ1zG_result{text-align:center;flex-direction:column;align-items:center;gap:5px;padding:10px 0 2px;display:flex}.BiQ1zG_resultCheck{background:var(--hub-success-tint);width:40px;height:40px;color:var(--hub-success);border-radius:50%;justify-content:center;align-items:center;margin-bottom:3px;display:inline-flex}.BiQ1zG_resultCheckIcon{flex-shrink:0;width:20px;height:20px}.BiQ1zG_resultTitle{color:var(--hub-text-primary);font-size:13px;font-weight:600;line-height:20px}.BiQ1zG_resultDesc{color:var(--hub-text-secondary);font-size:12px;line-height:18px}.BiQ1zG_resultRestarting{color:var(--hub-text-tertiary);padding:12px 0 6px;font-size:12px;line-height:18px}.BiQ1zG_restartLater{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;padding:5px 14px;font-size:12px;line-height:18px;transition:color .12s,background .12s}.BiQ1zG_restartLater:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}.BiQ1zG_restartNow{color:var(--hub-text-on-fill);background:var(--hub-btn-fill);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;padding:5px 14px;font-size:12px;font-weight:600;line-height:18px;transition:background .12s}.BiQ1zG_restartNow:hover{background:var(--hub-btn-hover)}.BiQ1zG_restartNow:disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.BiQ1zG_result .BiQ1zG_modalActions{justify-content:center;gap:10px;margin-top:0;padding:6px 0 2px}.BiQ1zG_result .BiQ1zG_modalActions .BiQ1zG_restartLater,.BiQ1zG_result .BiQ1zG_modalActions .BiQ1zG_restartNow{min-width:100px}.BiQ1zG_progress{margin:10px 0 2px}.BiQ1zG_progressHead{justify-content:flex-end;align-items:center;margin-bottom:3px;display:flex}.BiQ1zG_progressText{color:var(--hub-text-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;line-height:14px}.BiQ1zG_progressTrack{background:var(--hub-border-2);border-radius:2px;height:4px;overflow:hidden}.BiQ1zG_progressFill{background:var(--hub-brand);border-radius:2px;height:100%;transition:width .32s}.BiQ1zG_progressFillFail{background:var(--hub-danger)}@keyframes BiQ1zG_overlayIn{0%{opacity:0}to{opacity:1}}@keyframes BiQ1zG_modalIn{0%{opacity:0;transform:translateY(6px)scale(.98)}to{opacity:1;transform:translateY(0)scale(1)}}.BiQ1zG_noticeList{flex-direction:column;gap:10px;padding-right:2px;display:flex}.BiQ1zG_noticeRow{border:1px solid var(--hub-border-2);background:var(--hub-bg-2);border-radius:8px;flex-direction:column;align-items:stretch;gap:6px;padding:10px 12px;display:flex}.BiQ1zG_noticeRowMain{align-items:center;gap:10px;width:100%;min-width:0;display:flex}.BiQ1zG_noticeBadgeOk,.BiQ1zG_noticeBadgeFail{border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:28px;height:28px;display:inline-flex;box-shadow:0 2px 6px #0000002e}.BiQ1zG_noticeBadgeOk{background:var(--hub-success)}.BiQ1zG_noticeBadgeFail{background:var(--hub-danger)}.BiQ1zG_noticeBadgeIcon{flex-shrink:0;width:12px;height:12px}.BiQ1zG_noticeMain{flex-direction:column;flex:1;gap:8px;min-width:0;display:flex}.BiQ1zG_noticeHead{align-items:center;gap:8px;min-width:0;display:flex}.BiQ1zG_noticeTextOk{color:var(--hub-success);flex-shrink:0;font-size:12px;font-weight:600;line-height:18px}.BiQ1zG_noticeTextFail{color:var(--hub-danger-text);flex-shrink:0;font-size:12px;font-weight:600;line-height:18px}.BiQ1zG_failList{flex-direction:column;gap:12px;padding-right:2px;display:flex}.BiQ1zG_failRow{border:1px solid var(--hub-border-2);background:var(--hub-bg-2);border-radius:8px;flex-direction:column;gap:8px;padding:10px 12px;display:flex}.BiQ1zG_failHead{align-items:center;gap:8px;min-width:0;display:flex}.BiQ1zG_failKind{border:1px solid #0000;border-radius:4px;flex-shrink:0;padding:0 6px;font-size:10px;font-weight:500;line-height:16px}.BiQ1zG_failKindInstall{color:var(--hub-danger-text);border-color:var(--hub-danger-border);background:var(--hub-danger-tint)}.BiQ1zG_failKindUninstall{color:var(--hub-warn);border-color:var(--hub-warn-border);background:var(--hub-warn-tint)}.BiQ1zG_failRepo{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:18px;text-decoration:none;overflow:hidden}.BiQ1zG_failRepo:hover{text-decoration:underline}.BiQ1zG_noticeFoot{justify-content:flex-end;align-items:center;display:flex}.BiQ1zG_noticeTime{color:var(--hub-text-tertiary);font-variant-numeric:tabular-nums;flex-shrink:0;font-size:11px;line-height:16px}.BiQ1zG_noticeRemove{width:22px;height:22px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:5px;flex-shrink:0;justify-content:center;align-items:center;margin-left:auto;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_noticeRemove:hover{color:var(--hub-danger-text);background:var(--hub-danger-tint)}.BiQ1zG_noticeRowOk .BiQ1zG_noticeRemove{margin-left:0}.BiQ1zG_noticeRowOk .BiQ1zG_noticeTime{margin-left:auto}.BiQ1zG_failCopy{color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:4px;flex-shrink:0;align-items:center;padding:2px 8px;font-size:11px;line-height:16px;transition:color .12s,background .12s;display:inline-flex}.BiQ1zG_failCopy:hover{color:var(--hub-text-secondary);background:var(--hub-bg-2)}.BiQ1zG_failEmpty{text-align:center;color:var(--hub-text-tertiary);padding:24px 0;font-size:12px;line-height:18px}.BiQ1zG_failClear{color:var(--hub-danger);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;padding:5px 14px;font-size:12px;line-height:18px;transition:color .12s,background .12s}.BiQ1zG_failClear:hover{color:#fff;background:var(--hub-danger)}.BiQ1zG_failBigIssue{box-sizing:border-box;text-align:center;color:#fff;background:var(--hub-danger);border:1px solid var(--hub-danger);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:8px;width:100%;margin-top:4px;padding:3px 16px;font-size:13px;font-weight:600;line-height:18px;text-decoration:none;transition:background .12s,border-color .12s,box-shadow .12s;display:block}.BiQ1zG_failBigIssue:hover{background:var(--hub-danger-hover);border-color:var(--hub-danger-hover);box-shadow:0 3px 10px #d1242f59}.BiQ1zG_failPrepareHint{color:var(--hub-warning);background:var(--hub-warning-tint);border:1px solid var(--hub-warning-border);border-radius:6px;margin-top:6px;padding:8px 12px;font-size:12px;line-height:18px}.BiQ1zG_aboutModal{width:460px;max-width:calc(100vw - 48px)}.BiQ1zG_aboutContent{min-height:0;max-height:340px;color:var(--hub-text-secondary);background:var(--hub-bg-2);border:1px solid var(--hub-border-2);border-radius:8px;flex:auto;padding:10px 12px;font-size:12px;line-height:18px;overflow-y:auto}.BiQ1zG_aboutContent>:first-child{margin-top:0}.BiQ1zG_aboutContent>:last-child{margin-bottom:0}.BiQ1zG_aboutContent h2,.BiQ1zG_aboutContent h3,.BiQ1zG_aboutContent h4,.BiQ1zG_aboutContent h5{color:var(--hub-text-primary);margin:10px 0 4px;font-size:13px;font-weight:600;line-height:20px}.BiQ1zG_aboutContent h2{font-size:14px}.BiQ1zG_aboutContent p{margin:4px 0}.BiQ1zG_aboutContent ul,.BiQ1zG_aboutContent ol{margin:4px 0;padding-left:18px}.BiQ1zG_aboutContent li{margin:2px 0}.BiQ1zG_aboutContent code{background:var(--hub-bg-hover);color:var(--hub-text-primary);border-radius:4px;padding:1px 4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.BiQ1zG_aboutContent pre{background:var(--hub-bg-1);border:1px solid var(--hub-border-2);border-radius:6px;margin:6px 0;padding:8px 10px;overflow-x:auto}.BiQ1zG_aboutContent pre code{background:0 0;border-radius:0;padding:0}.BiQ1zG_aboutContent blockquote{border-left:3px solid var(--hub-brand);background:var(--hub-bg-hover);color:var(--hub-text-tertiary);border-radius:0 6px 6px 0;margin:6px 0;padding:2px 10px}.BiQ1zG_aboutContent a{color:var(--hub-brand);text-decoration:none}.BiQ1zG_aboutContent a:hover{color:var(--hub-brand-hover);text-decoration:underline}.BiQ1zG_aboutContent img{border-radius:8px;max-width:100%;max-height:220px;margin:8px auto;display:block;box-shadow:0 2px 8px #0000001f}.BiQ1zG_aboutMeta{color:var(--hub-text-tertiary);font-size:11px;line-height:16px}.BiQ1zG_hubUpdateModal{width:520px;max-width:calc(100vw - 48px)}.BiQ1zG_hubUpdateMeta{flex-wrap:wrap;align-items:center;gap:4px 14px;font-size:12px;line-height:18px;display:flex}.BiQ1zG_hubUpdateMetaItem{color:var(--hub-text-tertiary)}.BiQ1zG_hubUpdateNotes{min-height:0;max-height:300px;color:var(--hub-text-secondary);background:var(--hub-bg-2);border:1px solid var(--hub-border-2);border-radius:8px;flex:auto;padding:10px 12px;font-size:12px;line-height:18px;overflow-y:auto}.BiQ1zG_hubUpdateNotes>:first-child{margin-top:0}.BiQ1zG_hubUpdateNotes>:last-child{margin-bottom:0}.BiQ1zG_hubUpdateNotes h2,.BiQ1zG_hubUpdateNotes h3,.BiQ1zG_hubUpdateNotes h4,.BiQ1zG_hubUpdateNotes h5{color:var(--hub-text-primary);margin:10px 0 4px;font-size:13px;font-weight:600;line-height:20px}.BiQ1zG_hubUpdateNotes h2{font-size:14px}.BiQ1zG_hubUpdateNotes p{margin:4px 0}.BiQ1zG_hubUpdateNotes ul,.BiQ1zG_hubUpdateNotes ol{margin:4px 0;padding-left:18px}.BiQ1zG_hubUpdateNotes li{margin:2px 0}.BiQ1zG_hubUpdateNotes code{background:var(--hub-bg-hover);color:var(--hub-text-primary);border-radius:4px;padding:1px 4px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.BiQ1zG_hubUpdateNotes pre{background:var(--hub-bg-1);border:1px solid var(--hub-border-2);border-radius:6px;margin:6px 0;padding:8px 10px;overflow-x:auto}.BiQ1zG_hubUpdateNotes pre code{background:0 0;border-radius:0;padding:0}.BiQ1zG_hubUpdateNotes blockquote{border-left:3px solid var(--hub-brand);background:var(--hub-bg-hover);color:var(--hub-text-tertiary);border-radius:0 6px 6px 0;margin:6px 0;padding:2px 10px}.BiQ1zG_hubUpdateNotes a{color:var(--hub-brand);text-decoration:none}.BiQ1zG_hubUpdateNotes a:hover{color:var(--hub-brand-hover);text-decoration:underline}";
1270
1396
  const tagId$3 = "dsh-plugin/Modal.module.css";
1271
1397
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1272
1398
  const tag = document.createElement("style");
@@ -1276,93 +1402,103 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1276
1402
  document.head.appendChild(tag);
1277
1403
  }
1278
1404
  var Modal_module_css_default = {
1279
- "queueRowTarget": "BiQ1zG_queueRowTarget",
1280
- "failClear": "BiQ1zG_failClear",
1281
- "modalValue": "BiQ1zG_modalValue",
1282
- "modalTitleQueued": "BiQ1zG_modalTitleQueued",
1283
- "overlay": "BiQ1zG_overlay",
1284
- "noticeRow": "BiQ1zG_noticeRow",
1285
- "toast": "BiQ1zG_toast",
1286
- "restartLater": "BiQ1zG_restartLater",
1287
- "resultCheckIcon": "BiQ1zG_resultCheckIcon",
1288
- "linkIcon": "BiQ1zG_linkIcon",
1289
- "failKindUninstall": "BiQ1zG_failKindUninstall",
1290
- "failRepo": "BiQ1zG_failRepo",
1291
- "modalCmd": "BiQ1zG_modalCmd",
1292
- "modal": "BiQ1zG_modal",
1293
- "queueRowPct": "BiQ1zG_queueRowPct",
1294
- "failKind": "BiQ1zG_failKind",
1295
1405
  "modalTitle": "BiQ1zG_modalTitle",
1296
- "modalTitleBusy": "BiQ1zG_modalTitleBusy",
1297
- "modalBody": "BiQ1zG_modalBody",
1298
- "modalCloseIcon": "BiQ1zG_modalCloseIcon",
1299
- "errorCopySoft": "BiQ1zG_errorCopySoft",
1300
- "modalCancel": "BiQ1zG_modalCancel",
1301
- "overlayIn": "BiQ1zG_overlayIn",
1302
- "modalClose": "BiQ1zG_modalClose",
1303
- "modalCopy": "BiQ1zG_modalCopy",
1304
- "modalCmdText": "BiQ1zG_modalCmdText",
1305
- "queueSection": "BiQ1zG_queueSection",
1306
- "queueRow": "BiQ1zG_queueRow",
1307
1406
  "errorHint": "BiQ1zG_errorHint",
1308
- "noticeMain": "BiQ1zG_noticeMain",
1309
- "noticeFoot": "BiQ1zG_noticeFoot",
1310
- "failCopy": "BiQ1zG_failCopy",
1311
- "failBigIssue": "BiQ1zG_failBigIssue",
1312
- "modalRow": "BiQ1zG_modalRow",
1313
- "queueRowBody": "BiQ1zG_queueRowBody",
1314
- "queueRowTrack": "BiQ1zG_queueRowTrack",
1315
- "errorBox": "BiQ1zG_errorBox",
1316
- "progressHead": "BiQ1zG_progressHead",
1317
- "noticeHead": "BiQ1zG_noticeHead",
1318
- "progressFillFail": "BiQ1zG_progressFillFail",
1319
- "noticeTextFail": "BiQ1zG_noticeTextFail",
1320
- "noticeRemove": "BiQ1zG_noticeRemove",
1407
+ "resultCheck": "BiQ1zG_resultCheck",
1408
+ "noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
1409
+ "toastIn": "BiQ1zG_toastIn",
1321
1410
  "modalLabel": "BiQ1zG_modalLabel",
1411
+ "resultDesc": "BiQ1zG_resultDesc",
1412
+ "modalDesc": "BiQ1zG_modalDesc",
1322
1413
  "pendingRowActions": "BiQ1zG_pendingRowActions",
1323
- "resultTitle": "BiQ1zG_resultTitle",
1414
+ "errorCopySoft": "BiQ1zG_errorCopySoft",
1415
+ "modalLink": "BiQ1zG_modalLink",
1416
+ "overlay": "BiQ1zG_overlay",
1417
+ "uninstallConfirm": "BiQ1zG_uninstallConfirm",
1418
+ "modalTitleQueued": "BiQ1zG_modalTitleQueued",
1419
+ "failHead": "BiQ1zG_failHead",
1420
+ "cliOnlyHint": "BiQ1zG_cliOnlyHint",
1421
+ "progress": "BiQ1zG_progress",
1422
+ "queuedHint": "BiQ1zG_queuedHint",
1423
+ "modalCancel": "BiQ1zG_modalCancel",
1424
+ "stripCancel": "BiQ1zG_stripCancel",
1324
1425
  "restartNow": "BiQ1zG_restartNow",
1325
- "noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
1326
- "failPrepareHint": "BiQ1zG_failPrepareHint",
1327
- "noticeBadgeOk": "BiQ1zG_noticeBadgeOk",
1328
- "failEmpty": "BiQ1zG_failEmpty",
1329
1426
  "result": "BiQ1zG_result",
1427
+ "modalRow": "BiQ1zG_modalRow",
1428
+ "queueRowBody": "BiQ1zG_queueRowBody",
1330
1429
  "modalInstall": "BiQ1zG_modalInstall",
1331
- "noticeTextOk": "BiQ1zG_noticeTextOk",
1332
- "noticeList": "BiQ1zG_noticeList",
1333
- "queueSectionTitle": "BiQ1zG_queueSectionTitle",
1334
- "stripCancel": "BiQ1zG_stripCancel",
1335
- "progress": "BiQ1zG_progress",
1336
- "modalDesc": "BiQ1zG_modalDesc",
1337
- "modalIn": "BiQ1zG_modalIn",
1338
- "errorTitle": "BiQ1zG_errorTitle",
1339
- "failList": "BiQ1zG_failList",
1430
+ "noticeMain": "BiQ1zG_noticeMain",
1431
+ "linkIcon": "BiQ1zG_linkIcon",
1340
1432
  "noticeTime": "BiQ1zG_noticeTime",
1341
- "queuedHint": "BiQ1zG_queuedHint",
1342
- "resultDesc": "BiQ1zG_resultDesc",
1343
- "trustHint": "BiQ1zG_trustHint",
1344
- "noticeRowMain": "BiQ1zG_noticeRowMain",
1433
+ "queueSection": "BiQ1zG_queueSection",
1434
+ "noticeRowOk": "BiQ1zG_noticeRowOk",
1435
+ "errorModal": "BiQ1zG_errorModal",
1436
+ "aboutMeta": "BiQ1zG_aboutMeta",
1437
+ "hubUpdateNotes": "BiQ1zG_hubUpdateNotes",
1438
+ "noticeRemove": "BiQ1zG_noticeRemove",
1439
+ "modalClose": "BiQ1zG_modalClose",
1440
+ "progressFillFail": "BiQ1zG_progressFillFail",
1441
+ "overlayIn": "BiQ1zG_overlayIn",
1442
+ "aboutContent": "BiQ1zG_aboutContent",
1443
+ "hubUpdateModal": "BiQ1zG_hubUpdateModal",
1444
+ "queueRowPct": "BiQ1zG_queueRowPct",
1345
1445
  "queueRowDesc": "BiQ1zG_queueRowDesc",
1346
- "modalHead": "BiQ1zG_modalHead",
1347
- "queueRowStatus": "BiQ1zG_queueRowStatus",
1348
- "uninstallConfirm": "BiQ1zG_uninstallConfirm",
1349
- "failKindInstall": "BiQ1zG_failKindInstall",
1446
+ "failList": "BiQ1zG_failList",
1350
1447
  "toastFail": "BiQ1zG_toastFail",
1351
- "queueRowHead": "BiQ1zG_queueRowHead",
1448
+ "modalActions": "BiQ1zG_modalActions",
1449
+ "progressText": "BiQ1zG_progressText",
1450
+ "hubUpdateMetaItem": "BiQ1zG_hubUpdateMetaItem",
1451
+ "modalCopy": "BiQ1zG_modalCopy",
1352
1452
  "resultRestarting": "BiQ1zG_resultRestarting",
1353
- "resultCheck": "BiQ1zG_resultCheck",
1354
- "failRow": "BiQ1zG_failRow",
1355
- "pendingRowStatus": "BiQ1zG_pendingRowStatus",
1356
- "failHead": "BiQ1zG_failHead",
1453
+ "queueSectionTitle": "BiQ1zG_queueSectionTitle",
1454
+ "modalBody": "BiQ1zG_modalBody",
1455
+ "failKind": "BiQ1zG_failKind",
1456
+ "queueRowTrack": "BiQ1zG_queueRowTrack",
1457
+ "modalCmd": "BiQ1zG_modalCmd",
1458
+ "noticeRow": "BiQ1zG_noticeRow",
1459
+ "modalCloseIcon": "BiQ1zG_modalCloseIcon",
1460
+ "resultTitle": "BiQ1zG_resultTitle",
1461
+ "failKindUninstall": "BiQ1zG_failKindUninstall",
1462
+ "failCopy": "BiQ1zG_failCopy",
1463
+ "modalTitleBusy": "BiQ1zG_modalTitleBusy",
1464
+ "queueRowHead": "BiQ1zG_queueRowHead",
1465
+ "noticeRowMain": "BiQ1zG_noticeRowMain",
1466
+ "failRepo": "BiQ1zG_failRepo",
1357
1467
  "progressFill": "BiQ1zG_progressFill",
1468
+ "aboutModal": "BiQ1zG_aboutModal",
1469
+ "failedCopyHint": "BiQ1zG_failedCopyHint",
1470
+ "queueRowStatus": "BiQ1zG_queueRowStatus",
1358
1471
  "progressTrack": "BiQ1zG_progressTrack",
1359
- "modalActions": "BiQ1zG_modalActions",
1360
- "noticeBadgeFail": "BiQ1zG_noticeBadgeFail",
1361
- "modalLink": "BiQ1zG_modalLink",
1362
- "errorModal": "BiQ1zG_errorModal",
1363
- "progressText": "BiQ1zG_progressText",
1472
+ "modalHead": "BiQ1zG_modalHead",
1364
1473
  "modalCmdCopy": "BiQ1zG_modalCmdCopy",
1365
- "toastIn": "BiQ1zG_toastIn"
1474
+ "modal": "BiQ1zG_modal",
1475
+ "modalValue": "BiQ1zG_modalValue",
1476
+ "failKindInstall": "BiQ1zG_failKindInstall",
1477
+ "noticeFoot": "BiQ1zG_noticeFoot",
1478
+ "failClear": "BiQ1zG_failClear",
1479
+ "queueRow": "BiQ1zG_queueRow",
1480
+ "toast": "BiQ1zG_toast",
1481
+ "noticeTextOk": "BiQ1zG_noticeTextOk",
1482
+ "noticeTextFail": "BiQ1zG_noticeTextFail",
1483
+ "noticeBadgeOk": "BiQ1zG_noticeBadgeOk",
1484
+ "noticeHead": "BiQ1zG_noticeHead",
1485
+ "failPrepareHint": "BiQ1zG_failPrepareHint",
1486
+ "trustHint": "BiQ1zG_trustHint",
1487
+ "pendingRowStatus": "BiQ1zG_pendingRowStatus",
1488
+ "progressHead": "BiQ1zG_progressHead",
1489
+ "failBigIssue": "BiQ1zG_failBigIssue",
1490
+ "failRow": "BiQ1zG_failRow",
1491
+ "hubUpdateMeta": "BiQ1zG_hubUpdateMeta",
1492
+ "queueRowTarget": "BiQ1zG_queueRowTarget",
1493
+ "restartLater": "BiQ1zG_restartLater",
1494
+ "modalIn": "BiQ1zG_modalIn",
1495
+ "errorBox": "BiQ1zG_errorBox",
1496
+ "resultCheckIcon": "BiQ1zG_resultCheckIcon",
1497
+ "noticeList": "BiQ1zG_noticeList",
1498
+ "errorTitle": "BiQ1zG_errorTitle",
1499
+ "modalCmdText": "BiQ1zG_modalCmdText",
1500
+ "failEmpty": "BiQ1zG_failEmpty",
1501
+ "noticeBadgeFail": "BiQ1zG_noticeBadgeFail"
1366
1502
  };
1367
1503
  //#endregion
1368
1504
  //#region src/client/components/icons.tsx
@@ -1541,8 +1677,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1541
1677
  * or restart is running, then switch to a result view offering an immediate
1542
1678
  * restart or a "later" deferral.
1543
1679
  */
1544
- /** 完成结果视图:绿色对勾 + 标题/描述 + 「稍后重启 / 立即重启」按钮对(部分插件需重启后才会挂载) */
1545
- function ResultView({ title, desc, t, restarting, onRestart, onClose }) {
1680
+ /** 完成结果视图:绿色对勾 + 标题/描述;
1681
+ * needsRestart=true(插件需重启才生效)→ 「稍后重启 / 立即重启」按钮对,点稍后重启后
1682
+ * 通知中心待重启条目常驻(服务端登记,内存态),直到用户点「立即重启」真正重启后才消失;
1683
+ * needsRestart=false(卸载已即时生效)→ 仅「完成」关闭。 */
1684
+ function ResultView({ title, desc, t, restarting, needsRestart, onRestart, onClose }) {
1546
1685
  return (0, react.createElement)("div", { className: Modal_module_css_default.result }, (0, react.createElement)("div", { className: Modal_module_css_default.resultCheck }, (0, react.createElement)("svg", {
1547
1686
  className: Modal_module_css_default.resultCheckIcon,
1548
1687
  viewBox: "0 0 16 16",
@@ -1556,7 +1695,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1556
1695
  strokeWidth: 2,
1557
1696
  strokeLinecap: "round",
1558
1697
  strokeLinejoin: "round"
1559
- }))), (0, react.createElement)("div", { className: Modal_module_css_default.resultTitle }, title), desc ? (0, react.createElement)("div", { className: Modal_module_css_default.resultDesc }, desc) : null, (0, react.createElement)("div", { className: Modal_module_css_default.resultRestarting }, restarting ? t("restarting") : t("restartHint")), (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
1698
+ }))), (0, react.createElement)("div", { className: Modal_module_css_default.resultTitle }, title), desc ? (0, react.createElement)("div", { className: Modal_module_css_default.resultDesc }, desc) : null, needsRestart ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.resultRestarting }, restarting ? t("restarting") : t("restartHint")), (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
1560
1699
  className: Modal_module_css_default.restartLater,
1561
1700
  onClick: onClose,
1562
1701
  disabled: restarting
@@ -1564,14 +1703,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1564
1703
  className: Modal_module_css_default.restartNow,
1565
1704
  onClick: onRestart,
1566
1705
  disabled: restarting
1567
- }, restarting ? t("restarting") : t("restartNow"))));
1706
+ }, restarting ? t("restarting") : t("restartNow")))]) : (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
1707
+ className: Modal_module_css_default.restartNow,
1708
+ onClick: onClose
1709
+ }, t("done"))));
1568
1710
  }
1569
1711
  /**
1570
1712
  * 信任确认弹窗:安装进入后台队列后弹窗仍可关闭(任务继续),
1571
1713
  * 只在本任务执行中展示实时进度;完成后切换为结果视图,与卸载一致。
1572
1714
  */
1573
1715
  function InstallModal(props) {
1574
- const { plugin, done, task, t, langPath, restarting, submitting, update, onClose, onCopy, onInstall, onRestart } = props;
1716
+ const { plugin, done, task, t, langPath, restarting, submitting, update, cliOnly, needsRestart, onClose, onCopy, onInstall, onRestart } = props;
1575
1717
  const busy = submitting || task !== null && (task.status === "pending" || task.status === "running");
1576
1718
  const name = plugin.displayName ?? plugin.slug;
1577
1719
  const busyTitle = (label) => langPath === "zh/" ? `${name} 插件${label}` : `${label} ${name}`;
@@ -1594,6 +1736,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1594
1736
  desc: update ? t("updateResultDesc") : t("installResultDesc"),
1595
1737
  t,
1596
1738
  restarting,
1739
+ needsRestart,
1597
1740
  onRestart,
1598
1741
  onClose
1599
1742
  }) : (0, react.createElement)("div", { className: Modal_module_css_default.modalBody }, (0, react.createElement)("div", { className: Modal_module_css_default.trustHint }, t("confirmDesc")), (0, react.createElement)("div", { className: Modal_module_css_default.modalRow }, (0, react.createElement)("span", { className: Modal_module_css_default.modalLabel }, t("confirmPlugin")), (0, react.createElement)("span", {
@@ -1611,7 +1754,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1611
1754
  title: t("copyInstallCommand"),
1612
1755
  role: "button",
1613
1756
  tabIndex: 0
1614
- }, (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdText }, installCommandOf(plugin)), (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdCopy }, (0, react.createElement)(CopyIcon), t("copyCmdLabel"))), task && task.status === "pending" ? (0, react.createElement)("div", { className: Modal_module_css_default.queuedHint }, t("queuedHint")) : null, task ? (0, react.createElement)(ProgressView, { task }) : null, (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
1757
+ }, (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdText }, installCommandOf(plugin)), (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdCopy }, (0, react.createElement)(CopyIcon), t("copyCmdLabel"))), cliOnly ? (0, react.createElement)("div", { className: Modal_module_css_default.cliOnlyHint }, t("cliOnlyHint")) : null, task && task.status === "pending" ? (0, react.createElement)("div", { className: Modal_module_css_default.queuedHint }, t("queuedHint")) : null, task ? (0, react.createElement)(ProgressView, { task }) : null, task && task.status === "failed" ? (0, react.createElement)("div", { className: Modal_module_css_default.failedCopyHint }, t("failedCopyHint")) : null, (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
1615
1758
  className: Modal_module_css_default.modalCopy,
1616
1759
  disabled: busy,
1617
1760
  onClick: onCopy
@@ -1623,7 +1766,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1623
1766
  }
1624
1767
  /** 卸载确认弹窗:确认/进行中(后台队列,可关闭);完成后切换为结果视图(成功即生效,仅「完成」关闭)。 */
1625
1768
  function UninstallModal(props) {
1626
- const { plugin, done, task, t, langPath, restarting, submitting, onClose, onCancel, onCopyCommand, onConfirm, onRestart } = props;
1769
+ const { plugin, done, task, t, langPath, restarting, submitting, needsRestart, onClose, onCancel, onCopyCommand, onConfirm, onRestart } = props;
1627
1770
  const busy = submitting || task !== null && (task.status === "pending" || task.status === "running");
1628
1771
  const name = plugin.displayName ?? plugin.slug;
1629
1772
  const busyTitle = (label) => langPath === "zh/" ? `${name} 插件${label}` : `${label} ${name}`;
@@ -1646,6 +1789,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1646
1789
  desc: t("uninstallResultDesc"),
1647
1790
  t,
1648
1791
  restarting,
1792
+ needsRestart,
1649
1793
  onRestart,
1650
1794
  onClose
1651
1795
  }) : (0, react.createElement)("div", { className: Modal_module_css_default.modalBody }, (0, react.createElement)("div", { className: Modal_module_css_default.modalDesc }, t("uninstallDesc")), (0, react.createElement)("div", { className: Modal_module_css_default.modalRow }, (0, react.createElement)("span", { className: Modal_module_css_default.modalLabel }, t("confirmPlugin")), (0, react.createElement)("span", {
@@ -1723,6 +1867,175 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1723
1867
  }, text);
1724
1868
  }
1725
1869
  //#endregion
1870
+ //#region src/client/lib/renderMarkdown.ts
1871
+ /**
1872
+ * 轻量 Markdown 渲染器:仅用于 Hub 自我更新的变更记录(Worker 下发的 notes)。
1873
+ *
1874
+ * 内容由插件作者自己编写、属可信内容,但渲染端仍先整体 HTML 转义,再按
1875
+ * Markdown 语法输出结构,杜绝任何未转义的原始 HTML 注入;链接仅放行 http(s)。
1876
+ *
1877
+ * 支持:标题(#~####)、有序/无序列表、代码块(```)、行内代码、加粗、斜体、
1878
+ * 链接、图片(![alt](url),如反馈群二维码)、引用(>)、段落;其余语法一律按
1879
+ * 纯文本处理,不引入外部依赖。图片仅放行 http(s),限定最大宽度不撑破弹窗。
1880
+ */
1881
+ /** HTML 转义:所有文本先进这里,再进入结构变换,保证输出里没有未转义的用户输入。 */
1882
+ function escapeHtml(s) {
1883
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1884
+ }
1885
+ /** 行内变换:链接 / 加粗 / 斜体 / 行内代码(代码先占位保护,最后还原)。 */
1886
+ function inline(s) {
1887
+ let out = escapeHtml(s);
1888
+ const codeSpans = [];
1889
+ out = out.replace(/`([^`]+)`/g, (_m, code) => {
1890
+ codeSpans.push(String(code));
1891
+ return `\u0000${codeSpans.length - 1}\u0000`;
1892
+ });
1893
+ out = out.replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g, (m, alt, url) => /^https?:\/\//i.test(String(url)) && !/[\u0000]/.test(String(url)) ? `<img src="${String(url)}" alt="${String(alt)}" loading="lazy">` : m);
1894
+ out = out.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (m, text, url) => /^https?:\/\//i.test(String(url)) && !/[\u0000]/.test(String(url)) ? `<a href="${String(url)}" target="_blank" rel="noopener noreferrer">${String(text)}</a>` : m);
1895
+ out = out.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
1896
+ out = out.replace(/(^|[^*])\*([^*]+)\*/g, "$1<em>$2</em>");
1897
+ return out.replace(/\u0000(\d+)\u0000/g, (_m, idx) => `<code>${codeSpans[Number(idx)]}</code>`);
1898
+ }
1899
+ /** 把变更记录 Markdown 渲染为安全的 HTML 字符串(由弹窗用 dangerouslySetInnerHTML 注入)。 */
1900
+ function renderMarkdown(md) {
1901
+ const lines = md.replace(/\r\n?/g, "\n").split("\n");
1902
+ const blocks = [];
1903
+ let i = 0;
1904
+ while (i < lines.length) {
1905
+ const line = lines[i];
1906
+ if (/^\s*```/.test(line)) {
1907
+ const buf = [];
1908
+ i++;
1909
+ while (i < lines.length && !/^\s*```/.test(lines[i])) {
1910
+ buf.push(lines[i]);
1911
+ i++;
1912
+ }
1913
+ i++;
1914
+ blocks.push(`<pre><code>${escapeHtml(buf.join("\n"))}</code></pre>`);
1915
+ continue;
1916
+ }
1917
+ if (line.trim() === "") {
1918
+ i++;
1919
+ continue;
1920
+ }
1921
+ const heading = line.match(/^(#{1,4})\s+(.*)/);
1922
+ if (heading) {
1923
+ const level = heading[1].length + 1;
1924
+ blocks.push(`<h${level}>${inline(heading[2])}</h${level}>`);
1925
+ i++;
1926
+ continue;
1927
+ }
1928
+ if (/^\s*[-*+]\s+/.test(line) || /^\s*\d+[.)]\s+/.test(line)) {
1929
+ const ordered = /^\s*\d+[.)]\s+/.test(line);
1930
+ const items = [];
1931
+ while (i < lines.length && (/^\s*[-*+]\s+/.test(lines[i]) || /^\s*\d+[.)]\s+/.test(lines[i]))) {
1932
+ items.push(`<li>${inline(lines[i].replace(/^\s*[-*+]|\s*\d+[.)]\s*/, "").trim())}</li>`);
1933
+ i++;
1934
+ }
1935
+ blocks.push(`<${ordered ? "ol" : "ul"}>${items.join("")}</${ordered ? "ol" : "ul"}>`);
1936
+ continue;
1937
+ }
1938
+ if (/^\s*>\s?/.test(line)) {
1939
+ const buf = [];
1940
+ while (i < lines.length && /^\s*>\s?/.test(lines[i])) {
1941
+ buf.push(inline(lines[i].replace(/^\s*>\s?/, "")));
1942
+ i++;
1943
+ }
1944
+ blocks.push(`<blockquote>${buf.join("<br>")}</blockquote>`);
1945
+ continue;
1946
+ }
1947
+ const buf = [];
1948
+ while (i < lines.length && lines[i].trim() !== "" && !/^\s*```/.test(lines[i]) && !/^#{1,4}\s+/.test(lines[i]) && !/^\s*([-*+]|\d+[.)])\s+/.test(lines[i])) {
1949
+ buf.push(inline(lines[i]));
1950
+ i++;
1951
+ }
1952
+ blocks.push(`<p>${buf.join("<br>")}</p>`);
1953
+ }
1954
+ return blocks.join("");
1955
+ }
1956
+ //#endregion
1957
+ //#region src/client/components/AboutModal.tsx
1958
+ /**
1959
+ * 头部「关注我们」弹窗:介绍 DSH-Plugin Hub 是干什么的 + 用户反馈群二维码。
1960
+ * 内容以 Markdown 形式由 dsh-update Worker 的 /about 接口下发(key = hub:about),
1961
+ * 作者想怎么写就怎么写、随写随推,客户端只负责渲染 —— 非写死。
1962
+ * 图片(反馈群二维码)经 renderMarkdown 的 ![](url) 语法嵌入,居中、最大高度受控。
1963
+ */
1964
+ function AboutModal({ info, lang, t, onClose }) {
1965
+ const contentRaw = info ? typeof info.content === "string" ? info.content : info.content && typeof info.content === "object" ? lang === "en" ? info.content.en ?? info.content.zh ?? "" : info.content.zh ?? info.content.en ?? "" : "" : "";
1966
+ const contentHtml = contentRaw.trim() ? renderMarkdown(contentRaw) : null;
1967
+ let updated = null;
1968
+ if (info?.updatedAt) {
1969
+ const d = new Date(info.updatedAt);
1970
+ if (!Number.isNaN(d.getTime())) updated = d.toLocaleString(lang === "en" ? "en-US" : "zh-CN");
1971
+ }
1972
+ return (0, react.createElement)("div", {
1973
+ className: Modal_module_css_default.overlay,
1974
+ onClick: (e) => {
1975
+ if (e.target === e.currentTarget) onClose();
1976
+ }
1977
+ }, (0, react.createElement)("div", {
1978
+ className: `${Modal_module_css_default.modal} ${Modal_module_css_default.aboutModal}`,
1979
+ role: "dialog",
1980
+ "aria-modal": "true"
1981
+ }, (0, react.createElement)("div", { className: Modal_module_css_default.modalHead }, (0, react.createElement)("div", { className: Modal_module_css_default.modalTitle }, t("aboutTitle")), (0, react.createElement)("button", {
1982
+ className: Modal_module_css_default.modalClose,
1983
+ "aria-label": t("confirmCancel"),
1984
+ onClick: () => onClose()
1985
+ }, (0, react.createElement)(CloseIcon))), (0, react.createElement)("div", { className: Modal_module_css_default.modalDesc }, t("aboutDesc")), contentHtml ? (0, react.createElement)("div", {
1986
+ className: Modal_module_css_default.aboutContent,
1987
+ dangerouslySetInnerHTML: { __html: contentHtml }
1988
+ }) : (0, react.createElement)("div", { className: Modal_module_css_default.aboutContent }, t("aboutEmpty")), updated ? (0, react.createElement)("div", { className: Modal_module_css_default.aboutMeta }, `${t("aboutUpdated")} ${updated}`) : null, (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, (0, react.createElement)("button", {
1989
+ className: Modal_module_css_default.modalInstall,
1990
+ onClick: onClose
1991
+ }, t("doneBtn")))));
1992
+ }
1993
+ //#endregion
1994
+ //#region src/client/components/HubUpdateModal.tsx
1995
+ /**
1996
+ * Hub 版本信息 / 自我更新说明弹窗:
1997
+ * - 有更新(hasUpdate=true):标题「有新版本」,展示新版本号、发布时间与 Worker 下发的
1998
+ * Markdown 变更记录(renderMarkdown 渲染,双语言按界面语言取 {zh,en} 对象),
1999
+ * 按钮「稍后再说 / 直接更新」,确认后进入安装弹窗执行覆盖重装。
2000
+ * - 无更新(hasUpdate=false):标题「当前版本」,展示当前版本信息与更新记录,已是最新。
2001
+ * 点击头部版本号(或「可更新」徽标)打开 —— 无论有无更新都能看到更新内容。
2002
+ */
2003
+ function HubUpdateModal({ info, lang, t, hasUpdate, onProceed, onClose }) {
2004
+ const notesRaw = typeof info.notes === "string" ? info.notes : info.notes && typeof info.notes === "object" ? lang === "en" ? info.notes.en ?? info.notes.zh ?? "" : info.notes.zh ?? info.notes.en ?? "" : "";
2005
+ const notesHtml = notesRaw.trim() ? renderMarkdown(notesRaw) : null;
2006
+ let published = null;
2007
+ if (info.publishedAt) {
2008
+ const d = new Date(info.publishedAt);
2009
+ if (!Number.isNaN(d.getTime())) published = d.toLocaleString(lang === "en" ? "en-US" : "zh-CN");
2010
+ }
2011
+ return (0, react.createElement)("div", {
2012
+ className: Modal_module_css_default.overlay,
2013
+ onClick: (e) => {
2014
+ if (e.target === e.currentTarget) onClose();
2015
+ }
2016
+ }, (0, react.createElement)("div", {
2017
+ className: `${Modal_module_css_default.modal} ${Modal_module_css_default.hubUpdateModal}`,
2018
+ role: "dialog",
2019
+ "aria-modal": "true"
2020
+ }, (0, react.createElement)("div", { className: Modal_module_css_default.modalHead }, (0, react.createElement)("div", { className: Modal_module_css_default.modalTitle }, t(hasUpdate ? "hubUpdateTitle" : "hubCurrentTitle")), (0, react.createElement)("button", {
2021
+ className: Modal_module_css_default.modalClose,
2022
+ "aria-label": t("confirmCancel"),
2023
+ onClick: () => onClose()
2024
+ }, (0, react.createElement)(CloseIcon))), (0, react.createElement)("div", { className: Modal_module_css_default.modalDesc }, t(hasUpdate ? "hubUpdateDesc" : "hubCurrentDesc", { version: info.version })), (0, react.createElement)("div", { className: Modal_module_css_default.hubUpdateMeta }, (0, react.createElement)("span", { className: Modal_module_css_default.hubUpdateMetaItem }, `${t("version")} ${info.version}`), published ? (0, react.createElement)("span", { className: Modal_module_css_default.hubUpdateMetaItem }, `${t("hubUpdatePublished")} ${published}`) : null), notesHtml ? (0, react.createElement)("div", {
2025
+ className: Modal_module_css_default.hubUpdateNotes,
2026
+ dangerouslySetInnerHTML: { __html: notesHtml }
2027
+ }) : null, (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, hasUpdate ? [(0, react.createElement)("button", {
2028
+ className: Modal_module_css_default.restartLater,
2029
+ onClick: onClose
2030
+ }, t("hubUpdateLater")), (0, react.createElement)("button", {
2031
+ className: Modal_module_css_default.modalInstall,
2032
+ onClick: onProceed
2033
+ }, t("updateNow"))] : (0, react.createElement)("button", {
2034
+ className: Modal_module_css_default.modalInstall,
2035
+ onClick: onClose
2036
+ }, t("hubUpToDate")))));
2037
+ }
2038
+ //#endregion
1726
2039
  //#region src/client/components/NotificationsModal.tsx
1727
2040
  /**
1728
2041
  * Notification-center dialog: a persistent log of every settled install /
@@ -1816,7 +2129,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1816
2129
  })), (0, react.createElement)("span", { className: Modal_module_css_default.queueRowPct }, `${q.progress}%`))))) : null]) : null, records.length === 0 ? (0, react.createElement)("div", { className: Modal_module_css_default.failEmpty }, t("notificationsEmpty")) : (0, react.createElement)("div", { className: Modal_module_css_default.noticeList }, records.map((r) => {
1817
2130
  return (0, react.createElement)("div", {
1818
2131
  key: r.id,
1819
- className: Modal_module_css_default.noticeRow
2132
+ className: r.ok ? `${Modal_module_css_default.noticeRow} ${Modal_module_css_default.noticeRowOk}` : Modal_module_css_default.noticeRow
1820
2133
  }, (0, react.createElement)("div", { className: Modal_module_css_default.noticeRowMain }, (0, react.createElement)("div", { className: r.ok ? Modal_module_css_default.noticeBadgeOk : Modal_module_css_default.noticeBadgeFail }, (0, react.createElement)(BadgeGlyph, { ok: r.ok })), (0, react.createElement)("div", { className: Modal_module_css_default.noticeMain }, (0, react.createElement)("div", { className: Modal_module_css_default.noticeHead }, (0, react.createElement)("span", { className: r.ok ? Modal_module_css_default.noticeTextOk : Modal_module_css_default.noticeTextFail }, r.ok ? r.kind === "install" ? t("installDone") : t("uninstallDone") : r.kind === "install" ? t("errorTitleInstall") : t("errorTitleUninstall")), r.repo ? (0, react.createElement)("a", {
1821
2134
  className: Modal_module_css_default.failRepo,
1822
2135
  href: pluginSiteUrl(r.repo),
@@ -1826,7 +2139,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1826
2139
  }, r.repo) : null, !r.ok && (0, react.createElement)("button", {
1827
2140
  className: Modal_module_css_default.failCopy,
1828
2141
  onClick: () => onCopy(r.message)
1829
- }, t("failCopy")), (0, react.createElement)("button", {
2142
+ }, t("failCopy")), r.ok ? (0, react.createElement)("span", {
2143
+ className: Modal_module_css_default.noticeTime,
2144
+ title: new Date(r.at).toLocaleString()
2145
+ }, fmtTime(r.at)) : null, (0, react.createElement)("button", {
1830
2146
  className: Modal_module_css_default.noticeRemove,
1831
2147
  "aria-label": t("removeNotification"),
1832
2148
  title: t("removeNotification"),
@@ -1850,10 +2166,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1850
2166
  rel: "noopener noreferrer",
1851
2167
  title: t("failIssueHint")
1852
2168
  }, t("failIssueBig")) : null;
1853
- })())), (0, react.createElement)("div", { className: Modal_module_css_default.noticeFoot }, (0, react.createElement)("span", {
2169
+ })())), !r.ok ? (0, react.createElement)("div", { className: Modal_module_css_default.noticeFoot }, (0, react.createElement)("span", {
1854
2170
  className: Modal_module_css_default.noticeTime,
1855
2171
  title: new Date(r.at).toLocaleString()
1856
- }, fmtTime(r.at))));
2172
+ }, fmtTime(r.at))) : null);
1857
2173
  })), (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, records.length > 0 ? (0, react.createElement)("button", {
1858
2174
  className: Modal_module_css_default.failClear,
1859
2175
  onClick: onClear
@@ -1868,7 +2184,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1868
2184
  * Section header: brand title row (H1 + open-site button) + tagline, followed
1869
2185
  * by the purple ad banner that promotes the catalog stats.
1870
2186
  */
1871
- function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang }) {
2187
+ function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang, hubUpdate, onVersionClick, onAboutClick }) {
1872
2188
  return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("div", { className: Header_module_css_default.header }, (0, react.createElement)("div", { className: Header_module_css_default.headerTitleRow }, (0, react.createElement)("a", {
1873
2189
  className: Header_module_css_default.brandTitle,
1874
2190
  href: `${SITE_URL}${langPath}`,
@@ -1876,13 +2192,25 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1876
2192
  rel: "noopener noreferrer",
1877
2193
  title: t("openHint"),
1878
2194
  "aria-label": t("openHint")
1879
- }, (0, react.createElement)(LogoIcon), (0, react.createElement)("h1", { className: Header_module_css_default.title }, t("title"), (0, react.createElement)("span", { className: Header_module_css_default.version }, ` v${PLUGIN_VERSION}`))), (0, react.createElement)("div", { className: Header_module_css_default.headerRight }, (0, react.createElement)("button", {
2195
+ }, (0, react.createElement)(LogoIcon), (0, react.createElement)("h1", { className: Header_module_css_default.title }, t("title"))), (0, react.createElement)("button", {
2196
+ className: Header_module_css_default.versionBtn,
2197
+ type: "button",
2198
+ onClick: onVersionClick,
2199
+ title: t(hubUpdate ? "hubUpdateHint" : "versionHint"),
2200
+ "aria-label": t(hubUpdate ? "hubUpdateHint" : "versionHint")
2201
+ }, `v${PLUGIN_VERSION}`, hubUpdate && (0, react.createElement)("span", { className: Header_module_css_default.hubUpdateBadge }, t("update"))), (0, react.createElement)("div", { className: Header_module_css_default.headerRight }, (0, react.createElement)("button", {
1880
2202
  className: Header_module_css_default.langBtn,
1881
2203
  type: "button",
1882
2204
  onClick: onToggleLang,
1883
2205
  title: t("toggleLangHint"),
1884
2206
  "aria-label": t("toggleLangHint")
1885
- }, langPath === "zh/" ? "EN" : "中文"), (0, react.createElement)("a", {
2207
+ }, langPath === "zh/" ? "EN" : "中文"), (0, react.createElement)("button", {
2208
+ className: Header_module_css_default.aboutBtn,
2209
+ type: "button",
2210
+ onClick: onAboutClick,
2211
+ title: t("aboutDesc"),
2212
+ "aria-label": t("aboutTitle")
2213
+ }, t("followUs")), (0, react.createElement)("a", {
1886
2214
  className: Header_module_css_default.githubLink,
1887
2215
  href: GITHUB_URL,
1888
2216
  target: "_blank",
@@ -1938,17 +2266,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
1938
2266
  document.head.appendChild(tag);
1939
2267
  }
1940
2268
  var Dropdown_module_css_default = {
2269
+ "dropdownItemLabel": "B_Gxsq_dropdownItemLabel",
2270
+ "dropdownCount": "B_Gxsq_dropdownCount",
2271
+ "dropdownBtn": "B_Gxsq_dropdownBtn",
2272
+ "dropdownArrow": "B_Gxsq_dropdownArrow",
1941
2273
  "dropdownPanel": "B_Gxsq_dropdownPanel",
2274
+ "dropdownItem": "B_Gxsq_dropdownItem",
2275
+ "dropdownCountActive": "B_Gxsq_dropdownCountActive",
1942
2276
  "dropdownArrowOpen": "B_Gxsq_dropdownArrowOpen",
1943
2277
  "dropdownItemActive": "B_Gxsq_dropdownItemActive",
1944
- "dropdownCountActive": "B_Gxsq_dropdownCountActive",
1945
2278
  "dropdownLabel": "B_Gxsq_dropdownLabel",
1946
- "dropdown": "B_Gxsq_dropdown",
1947
- "dropdownArrow": "B_Gxsq_dropdownArrow",
1948
- "dropdownBtn": "B_Gxsq_dropdownBtn",
1949
- "dropdownItem": "B_Gxsq_dropdownItem",
1950
- "dropdownItemLabel": "B_Gxsq_dropdownItemLabel",
1951
- "dropdownCount": "B_Gxsq_dropdownCount"
2279
+ "dropdown": "B_Gxsq_dropdown"
1952
2280
  };
1953
2281
  //#endregion
1954
2282
  //#region src/client/components/Dropdown.tsx
@@ -2063,37 +2391,37 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2063
2391
  document.head.appendChild(tag);
2064
2392
  }
2065
2393
  var List_module_css_default = {
2066
- "topic": "_3XaZHa_topic",
2067
- "verified": "_3XaZHa_verified",
2068
- "uninstallBtn": "_3XaZHa_uninstallBtn",
2394
+ "star": "_3XaZHa_star",
2395
+ "cardTitle": "_3XaZHa_cardTitle",
2069
2396
  "actions": "_3XaZHa_actions",
2070
2397
  "stateTitle": "_3XaZHa_stateTitle",
2071
- "cardMain": "_3XaZHa_cardMain",
2398
+ "body": "_3XaZHa_body",
2072
2399
  "installBtn": "_3XaZHa_installBtn",
2073
- "cardTitle": "_3XaZHa_cardTitle",
2074
- "star": "_3XaZHa_star",
2075
- "card": "_3XaZHa_card",
2076
- "categoryBadge": "_3XaZHa_categoryBadge",
2077
- "fork": "_3XaZHa_fork",
2078
- "stateDesc": "_3XaZHa_stateDesc",
2079
- "retryBtn": "_3XaZHa_retryBtn",
2080
- "updateBadge": "_3XaZHa_updateBadge",
2081
- "detailBtn": "_3XaZHa_detailBtn",
2400
+ "desc": "_3XaZHa_desc",
2401
+ "footer": "_3XaZHa_footer",
2402
+ "topic": "_3XaZHa_topic",
2403
+ "installBtnCopied": "_3XaZHa_installBtnCopied",
2404
+ "verified": "_3XaZHa_verified",
2082
2405
  "versionBadge": "_3XaZHa_versionBadge",
2406
+ "installBtnInstalled": "_3XaZHa_installBtnInstalled",
2407
+ "stateDesc": "_3XaZHa_stateDesc",
2083
2408
  "state": "_3XaZHa_state",
2084
- "date": "_3XaZHa_date",
2085
2409
  "stats": "_3XaZHa_stats",
2086
- "body": "_3XaZHa_body",
2087
- "cardHead": "_3XaZHa_cardHead",
2088
- "list": "_3XaZHa_list",
2089
- "installBtnCopied": "_3XaZHa_installBtnCopied",
2090
- "cardSide": "_3XaZHa_cardSide",
2410
+ "categoryBadge": "_3XaZHa_categoryBadge",
2411
+ "updateBadge": "_3XaZHa_updateBadge",
2091
2412
  "footLink": "_3XaZHa_footLink",
2413
+ "retryBtn": "_3XaZHa_retryBtn",
2414
+ "uninstallBtn": "_3XaZHa_uninstallBtn",
2415
+ "detailBtn": "_3XaZHa_detailBtn",
2416
+ "date": "_3XaZHa_date",
2417
+ "cardMain": "_3XaZHa_cardMain",
2092
2418
  "topics": "_3XaZHa_topics",
2093
- "installBtnInstalled": "_3XaZHa_installBtnInstalled",
2094
- "desc": "_3XaZHa_desc",
2419
+ "list": "_3XaZHa_list",
2420
+ "fork": "_3XaZHa_fork",
2421
+ "cardHead": "_3XaZHa_cardHead",
2095
2422
  "installBtnUpdate": "_3XaZHa_installBtnUpdate",
2096
- "footer": "_3XaZHa_footer"
2423
+ "cardSide": "_3XaZHa_cardSide",
2424
+ "card": "_3XaZHa_card"
2097
2425
  };
2098
2426
  //#endregion
2099
2427
  //#region src/client/lib/format.ts
@@ -2227,11 +2555,19 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2227
2555
  const [confirmPlugin, setConfirmPlugin] = (0, react.useState)(null);
2228
2556
  /** 弹窗动作是否为「更新」:已安装插件点「更新」→ 走同一条 add 命令原位覆盖重装,文案区分安装/更新 */
2229
2557
  const [confirmIsUpdate, setConfirmIsUpdate] = (0, react.useState)(false);
2558
+ /** Hub 自我更新说明弹窗:点「可更新」徽标先展示版本 + Markdown 变更记录,确认后再进安装弹窗 */
2559
+ const [showHubUpdate, setShowHubUpdate] = (0, react.useState)(false);
2560
+ /** 「关注我们」弹窗:GitHub 图标后按钮点击打开,展示平台介绍 + 用户反馈群二维码(Worker /about 推送) */
2561
+ const [showAbout, setShowAbout] = (0, react.useState)(false);
2230
2562
  /** 卸载确认弹窗:记录待卸载的插件 */
2231
2563
  const [uninstallPlugin, setUninstallPlugin] = (0, react.useState)(null);
2232
2564
  /** 安装/卸载完成后的结果视图:停留弹窗内,点「完成」关闭 */
2233
2565
  const [installDone, setInstallDone] = (0, react.useState)(false);
2234
2566
  const [uninstallDone, setUninstallDone] = (0, react.useState)(false);
2567
+ /** 结果视图是否给「立即重启」:服务端任务终态带出(卸载时 loader 已即时移除 → false 只给「完成」;
2568
+ * true 时通知中心待重启条目同步常驻,直到用户点「立即重启」真正重启后才消失) */
2569
+ const [installNeedsRestart, setInstallNeedsRestart] = (0, react.useState)(true);
2570
+ const [uninstallNeedsRestart, setUninstallNeedsRestart] = (0, react.useState)(true);
2235
2571
  /** 结果视图「立即重启」:请求宿主重启后进入等待,服务回来后整页刷新 */
2236
2572
  const [restarting, setRestarting] = (0, react.useState)(false);
2237
2573
  /** 操作失败完整信息 + 所属插件仓库 + 失败类型(决定弹窗标题「安装失败/卸载失败」)+ 实际执行的安装命令 + 尝试过的安装方式(issue 预填用) */
@@ -2253,7 +2589,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2253
2589
  const queue = useTaskQueue({
2254
2590
  t,
2255
2591
  refreshInstalled: catalog.refreshInstalled,
2256
- onInstallDone: (viaModal, repo) => {
2592
+ onInstallDone: (viaModal, repo, needsRestart) => {
2593
+ setInstallNeedsRestart(needsRestart);
2257
2594
  if (viaModal) setInstallDone(true);
2258
2595
  else setToast({
2259
2596
  id: Date.now(),
@@ -2264,7 +2601,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2264
2601
  repo: repo ?? ""
2265
2602
  }));
2266
2603
  },
2267
- onUninstallDone: (viaModal, repo) => {
2604
+ onUninstallDone: (viaModal, repo, needsRestart) => {
2605
+ setUninstallNeedsRestart(needsRestart);
2268
2606
  if (viaModal) setUninstallDone(true);
2269
2607
  else setToast({
2270
2608
  id: Date.now(),
@@ -2303,12 +2641,14 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2303
2641
  }
2304
2642
  });
2305
2643
  (0, react.useEffect)(() => {
2306
- if (!confirmPlugin && !uninstallPlugin && !showNotifications) return;
2644
+ if (!confirmPlugin && !uninstallPlugin && !showNotifications && !showHubUpdate && !showAbout) return;
2307
2645
  const onKey = (e) => {
2308
2646
  if (e.key === "Escape") {
2309
2647
  setConfirmPlugin(null);
2310
2648
  setUninstallPlugin(null);
2311
2649
  setUninstallDone(false);
2650
+ setShowHubUpdate(false);
2651
+ setShowAbout(false);
2312
2652
  setShowNotifications(false);
2313
2653
  }
2314
2654
  };
@@ -2317,7 +2657,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2317
2657
  }, [
2318
2658
  confirmPlugin,
2319
2659
  uninstallPlugin,
2320
- showNotifications
2660
+ showNotifications,
2661
+ showHubUpdate,
2662
+ showAbout
2321
2663
  ]);
2322
2664
  (0, react.useEffect)(() => {
2323
2665
  if (!toast) return;
@@ -2402,12 +2744,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2402
2744
  const statsTotal = catalog.stats?.total ?? total;
2403
2745
  const statsVerified = catalog.stats?.verified ?? 0;
2404
2746
  const count = catalog.visible.length;
2747
+ const hubEntry = catalog.plugins?.find((p) => p.source?.repo === "dshplugin/dsh-plugin-hub") ?? null;
2405
2748
  return (0, react.createElement)("div", { className: Header_module_css_default.root }, (0, react.createElement)(CatalogHeader, {
2406
2749
  t,
2407
2750
  langPath,
2408
2751
  statsTotal,
2409
2752
  statsVerified,
2410
- onToggleLang: () => setManualLang(lang === "en" ? "zh" : "en")
2753
+ onToggleLang: () => setManualLang(lang === "en" ? "zh" : "en"),
2754
+ hubUpdate: catalog.hubHasUpdate,
2755
+ onVersionClick: () => setShowHubUpdate(true),
2756
+ onAboutClick: () => setShowAbout(true)
2411
2757
  }), (0, react.createElement)(CategoryTabs, {
2412
2758
  category: catalog.category,
2413
2759
  setCategory: catalog.setCategory,
@@ -2453,6 +2799,26 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2453
2799
  queue.clearModalTask();
2454
2800
  setUninstallPlugin(p);
2455
2801
  }
2802
+ }), showHubUpdate && (0, react.createElement)(HubUpdateModal, {
2803
+ info: catalog.hubUpdateInfo ?? { version: "1.1.1" },
2804
+ lang,
2805
+ t,
2806
+ hasUpdate: catalog.hubHasUpdate,
2807
+ onClose: () => setShowHubUpdate(false),
2808
+ onProceed: () => {
2809
+ setShowHubUpdate(false);
2810
+ if (hubEntry) {
2811
+ setInstallDone(false);
2812
+ setConfirmIsUpdate(true);
2813
+ queue.clearModalTask();
2814
+ setConfirmPlugin(hubEntry);
2815
+ }
2816
+ }
2817
+ }), showAbout && (0, react.createElement)(AboutModal, {
2818
+ info: catalog.hubAboutInfo ?? null,
2819
+ lang,
2820
+ t,
2821
+ onClose: () => setShowAbout(false)
2456
2822
  }), confirmPlugin && (0, react.createElement)(InstallModal, {
2457
2823
  plugin: confirmPlugin,
2458
2824
  done: installDone,
@@ -2461,7 +2827,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2461
2827
  langPath,
2462
2828
  restarting,
2463
2829
  update: confirmIsUpdate,
2830
+ cliOnly: confirmPlugin.install?.webInstallable === false,
2464
2831
  submitting: queue.submitting,
2832
+ needsRestart: installNeedsRestart,
2465
2833
  onClose: () => setConfirmPlugin(null),
2466
2834
  onCopy: () => copyCommand(confirmPlugin),
2467
2835
  onInstall: () => queue.installNow(confirmPlugin, confirmIsUpdate ? { update: true } : void 0),
@@ -2476,6 +2844,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
2476
2844
  langPath,
2477
2845
  restarting,
2478
2846
  submitting: queue.submitting,
2847
+ needsRestart: uninstallNeedsRestart,
2479
2848
  onClose: () => {
2480
2849
  setUninstallDone(false);
2481
2850
  setUninstallPlugin(null);