dsh-plugin 1.0.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/README.en.md +12 -7
- package/README.md +12 -7
- package/client/client.js +725 -223
- package/client/client.js.map +1 -1
- package/lib/http/routes.js +43 -7
- package/lib/services/installed-versions.js +16 -1
- package/lib/services/loader.js +12 -5
- package/lib/services/npm-resolve.js +67 -0
- package/lib/services/task-queue.js +55 -10
- package/lib/types/services/install-types.d.ts +8 -0
- package/lib/types/services/installed-versions.d.ts +10 -0
- package/lib/types/services/loader.d.ts +6 -4
- package/lib/types/services/npm-resolve.d.ts +6 -0
- package/lib/types/services/task-queue.d.ts +11 -5
- package/package.json +1 -1
- package/src/client/components/AboutModal.tsx +72 -0
- package/src/client/components/CatalogHeader.tsx +30 -5
- package/src/client/components/HubUpdateModal.tsx +84 -0
- package/src/client/components/NotificationsModal.tsx +84 -58
- package/src/client/components/PluginCard.tsx +3 -0
- package/src/client/components/PluginHubSection.tsx +73 -14
- package/src/client/components/modals.tsx +42 -18
- package/src/client/hooks/useCatalog.ts +96 -18
- package/src/client/hooks/useTaskQueue.ts +164 -54
- package/src/client/lib/catalog.ts +81 -13
- package/src/client/lib/failures.ts +14 -2
- package/src/client/lib/renderMarkdown.ts +116 -0
- package/src/client/locales.ts +47 -4
- package/src/client/styles/Header.module.css +83 -3
- package/src/client/styles/List.module.css +4 -4
- package/src/client/styles/Modal.module.css +320 -5
- package/src/client/styles/tokens.module.css +8 -3
- package/src/client/types.ts +3 -1
- package/src/server/http/routes.ts +42 -7
- package/src/server/services/install-types.ts +8 -0
- package/src/server/services/installed-versions.ts +20 -1
- package/src/server/services/loader.ts +12 -5
- package/src/server/services/npm-resolve.ts +67 -0
- package/src/server/services/task-queue.ts +57 -10
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: "未安装",
|
|
@@ -54,8 +56,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
54
56
|
installNow: "直接安装",
|
|
55
57
|
installing: "安装中…",
|
|
56
58
|
installDone: "安装成功",
|
|
57
|
-
installResultTitle: "
|
|
58
|
-
installResultDesc: "
|
|
59
|
+
installResultTitle: "插件安装成功",
|
|
60
|
+
installResultDesc: "",
|
|
59
61
|
confirmUpdateTitle: "确认更新",
|
|
60
62
|
updateNow: "直接更新",
|
|
61
63
|
updating: "更新中…",
|
|
@@ -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: "待重启",
|
|
@@ -91,6 +94,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
91
94
|
notificationsDesc: "安装、卸载任务的成败都会记录在这里,即使错过提示也能随时回来查看。",
|
|
92
95
|
notificationsEmpty: "暂无通知记录",
|
|
93
96
|
notificationsClear: "清空通知",
|
|
97
|
+
removeNotification: "删除这条通知",
|
|
94
98
|
failCopy: "复制完整错误信息",
|
|
95
99
|
failIssueHint: "带着错误日志去作者仓库一键提交 Issue(正文含官网收录链接)",
|
|
96
100
|
failIssueBig: "一键提交 BUG 到 GitHub Issue 为开源作贡献",
|
|
@@ -114,6 +118,21 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
114
118
|
update: "可更新",
|
|
115
119
|
updateAvailable: "有更新",
|
|
116
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: "更新于",
|
|
117
136
|
empty: "该分类暂无插件",
|
|
118
137
|
dataFrom: "数据源 dsh-plugin.org · 每日人工更新"
|
|
119
138
|
};
|
|
@@ -138,6 +157,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
138
157
|
failedDesc: "Please retry, or open the hub in your browser with the button above.",
|
|
139
158
|
retry: "Retry",
|
|
140
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)",
|
|
141
162
|
toastCopied: "Install command copied — paste it in your dsh terminal",
|
|
142
163
|
installed: "Installed",
|
|
143
164
|
notInstalled: "Not installed",
|
|
@@ -165,8 +186,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
165
186
|
installNow: "Install",
|
|
166
187
|
installing: "Installing…",
|
|
167
188
|
installDone: "Installed",
|
|
168
|
-
installResultTitle: "
|
|
169
|
-
installResultDesc: "
|
|
189
|
+
installResultTitle: "Plugin installed successfully",
|
|
190
|
+
installResultDesc: "",
|
|
170
191
|
confirmUpdateTitle: "Confirm update",
|
|
171
192
|
updateNow: "Update",
|
|
172
193
|
updating: "Updating…",
|
|
@@ -180,6 +201,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
180
201
|
restartLater: "Later",
|
|
181
202
|
restarting: "Restarting…",
|
|
182
203
|
restartHint: "Some plugins (such as plugin markets / top-level bundles) only take effect after a restart.",
|
|
204
|
+
done: "Done",
|
|
183
205
|
restartPendingHint: "Installed — takes effect after restart",
|
|
184
206
|
restartPendingHintUninstall: "Removed — cleaned up after restart",
|
|
185
207
|
sectionPendingRestart: "Pending restart",
|
|
@@ -202,6 +224,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
202
224
|
notificationsDesc: "Every install and remove result is logged here — even if you missed the prompt, you can always check back.",
|
|
203
225
|
notificationsEmpty: "No notifications yet",
|
|
204
226
|
notificationsClear: "Clear notifications",
|
|
227
|
+
removeNotification: "Remove this notification",
|
|
205
228
|
failCopy: "Copy full log",
|
|
206
229
|
failIssueHint: "Open a pre-filled issue on the author repo with this error log (includes catalog links)",
|
|
207
230
|
failIssueBig: "Report this bug to GitHub — contribute to open source",
|
|
@@ -225,12 +248,27 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
225
248
|
update: "Update",
|
|
226
249
|
updateAvailable: "Update available",
|
|
227
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",
|
|
228
266
|
empty: "No plugins in this category yet",
|
|
229
267
|
dataFrom: "Data from dsh-plugin.org · curated daily"
|
|
230
268
|
};
|
|
231
269
|
//#endregion
|
|
232
270
|
//#region \0dsh-css:src/client/styles/Header.module.css.mjs
|
|
233
|
-
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}.
|
|
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}";
|
|
234
272
|
const tagId$4 = "dsh-plugin/Header.module.css";
|
|
235
273
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
236
274
|
const tag = document.createElement("style");
|
|
@@ -240,40 +278,43 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
240
278
|
document.head.appendChild(tag);
|
|
241
279
|
}
|
|
242
280
|
var Header_module_css_default = {
|
|
243
|
-
"tab": "qikqja_tab",
|
|
244
|
-
"adText": "qikqja_adText",
|
|
245
|
-
"failBtn": "qikqja_failBtn",
|
|
246
|
-
"root": "qikqja_root",
|
|
247
|
-
"header": "qikqja_header",
|
|
248
281
|
"githubIcon": "qikqja_githubIcon",
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
"
|
|
282
|
+
"installedBtnActive": "qikqja_installedBtnActive",
|
|
283
|
+
"taglineLink": "qikqja_taglineLink",
|
|
284
|
+
"tagline": "qikqja_tagline",
|
|
285
|
+
"installedBtn": "qikqja_installedBtn",
|
|
253
286
|
"installedBtnDisabled": "qikqja_installedBtnDisabled",
|
|
287
|
+
"searchRow": "qikqja_searchRow",
|
|
288
|
+
"segCount": "qikqja_segCount",
|
|
289
|
+
"resultCount": "qikqja_resultCount",
|
|
290
|
+
"title": "qikqja_title",
|
|
291
|
+
"segCountActive": "qikqja_segCountActive",
|
|
292
|
+
"githubLink": "qikqja_githubLink",
|
|
293
|
+
"tabActive": "qikqja_tabActive",
|
|
254
294
|
"failBadge": "qikqja_failBadge",
|
|
255
|
-
"
|
|
256
|
-
"
|
|
257
|
-
"
|
|
295
|
+
"header": "qikqja_header",
|
|
296
|
+
"tab": "qikqja_tab",
|
|
297
|
+
"search": "qikqja_search",
|
|
298
|
+
"tabCount": "qikqja_tabCount",
|
|
258
299
|
"headerRight": "qikqja_headerRight",
|
|
300
|
+
"brandTitle": "qikqja_brandTitle",
|
|
259
301
|
"controls": "qikqja_controls",
|
|
260
|
-
"
|
|
261
|
-
"copyIcon": "qikqja_copyIcon",
|
|
302
|
+
"filterResults": "qikqja_filterResults",
|
|
262
303
|
"adArrow": "qikqja_adArrow",
|
|
263
|
-
"
|
|
304
|
+
"root": "qikqja_root",
|
|
305
|
+
"adBanner": "qikqja_adBanner",
|
|
264
306
|
"adBadge": "qikqja_adBadge",
|
|
307
|
+
"logoIcon": "qikqja_logoIcon",
|
|
308
|
+
"version": "qikqja_version",
|
|
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",
|
|
265
316
|
"tabs": "qikqja_tabs",
|
|
266
|
-
"
|
|
267
|
-
"brandTitle": "qikqja_brandTitle",
|
|
268
|
-
"adBanner": "qikqja_adBanner",
|
|
269
|
-
"filterResults": "qikqja_filterResults",
|
|
270
|
-
"resultCount": "qikqja_resultCount",
|
|
271
|
-
"searchRow": "qikqja_searchRow",
|
|
272
|
-
"segCountActive": "qikqja_segCountActive",
|
|
273
|
-
"installedBtn": "qikqja_installedBtn",
|
|
274
|
-
"langBtn": "qikqja_langBtn",
|
|
275
|
-
"tabActive": "qikqja_tabActive",
|
|
276
|
-
"tabCount": "qikqja_tabCount"
|
|
317
|
+
"langBtn": "qikqja_langBtn"
|
|
277
318
|
};
|
|
278
319
|
//#endregion
|
|
279
320
|
//#region src/client/lib/failures.ts
|
|
@@ -281,7 +322,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
281
322
|
const MAX = 50;
|
|
282
323
|
/**
|
|
283
324
|
* 失败归类,三态。无论底层机制如何(pnpm 白名单拦截 / 构建脚本被忽略 / prepare 失败),
|
|
284
|
-
* 对用户而言结果都一样 ——
|
|
325
|
+
* 对用户而言结果都一样 —— 当前安装通道(npm 或 git)装不上,就是插件分发/依赖的问题,
|
|
326
|
+
* 一律引导提 Issue:
|
|
285
327
|
* - pnpmIgnoredBuild:插件依赖里的原生模块构建脚本被 pnpm 默认拦截(如 node-pty,
|
|
286
328
|
* `ERR_PNPM_IGNORED_BUILDS`)。只影响带原生模块的插件,其他插件不受影响 —— 差异在
|
|
287
329
|
* 插件的依赖选择,属插件依赖/打包问题 → 引导去仓库提 Issue(建议改用预编译版本)
|
|
@@ -393,6 +435,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
393
435
|
save([]);
|
|
394
436
|
return [];
|
|
395
437
|
}
|
|
438
|
+
/** 按 id 删除单条通知记录,返回更新后的列表(仅移除该条,不影响其余记录)。 */
|
|
439
|
+
function removeNotification(id) {
|
|
440
|
+
const next = loadNotifications().filter((r) => r.id !== id);
|
|
441
|
+
save(next);
|
|
442
|
+
return next;
|
|
443
|
+
}
|
|
396
444
|
//#endregion
|
|
397
445
|
//#region src/client/lib/catalog.ts
|
|
398
446
|
/** 插件中心官网地址。 */
|
|
@@ -400,11 +448,21 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
400
448
|
/** 插件中心源码仓库:头部右上角 GitHub 图标的跳转地址 */
|
|
401
449
|
const GITHUB_URL = "https://github.com/dshplugin/dsh-plugin-hub";
|
|
402
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
|
+
/**
|
|
403
461
|
* 插件当前版本号,供头部标题展示「DSH-Plugin Hub v0.1.1」。
|
|
404
462
|
* tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;
|
|
405
463
|
* node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。
|
|
406
464
|
*/
|
|
407
|
-
const PLUGIN_VERSION = "1.
|
|
465
|
+
const PLUGIN_VERSION = "1.1.1";
|
|
408
466
|
/** dsh-plugin.org 中文页挂在 /zh/ 前缀下,英文在根路径。 */
|
|
409
467
|
function langPathOf(lang) {
|
|
410
468
|
return lang === "zh" ? "zh/" : "";
|
|
@@ -426,15 +484,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
426
484
|
}
|
|
427
485
|
/**
|
|
428
486
|
* 一键反馈 GitHub Issue 的预填链接:标题带「来自 dsh-plugin.org」标识,正文只带
|
|
429
|
-
* 核心信息 —— 原因判定 + 关键错误代码 + 宿主机器环境快照 +
|
|
430
|
-
*
|
|
431
|
-
*
|
|
487
|
+
* 核心信息 —— 原因判定 + 关键错误代码 + 尝试过的安装方式 + 宿主机器环境快照 +
|
|
488
|
+
* 错误核心摘要(完整日志太长,塞进 URL 会被 GitHub 以「request URL too long」拒绝,
|
|
489
|
+
* 故只收集重点)。错误弹窗、失败记录共用此逻辑。
|
|
432
490
|
* env 取不到时为 null,链接照常生成、只是少环境段。
|
|
491
|
+
* attempts(尝试过的安装方式,npm 反查 + 实际执行命令):作者看到我们查过/试过的命令,
|
|
492
|
+
* 组织 scope 与 GitHub 用户名不一致时也能直接指认正确的 npm 包名。
|
|
433
493
|
*/
|
|
434
|
-
function pluginIssueUrl(repo, message, env) {
|
|
494
|
+
function pluginIssueUrl(repo, message, env, command, attempts) {
|
|
435
495
|
const title = `[dsh-plugin.org | dsh-plugin-hub] Install/Remove failed: ${repo}`;
|
|
436
496
|
const kind = classifyFailure(message);
|
|
437
|
-
const reason = /\[packaging\]/i.test(message) ? "plugin
|
|
497
|
+
const reason = /\[packaging\]/i.test(message) ? "plugin distribution is incomplete — the entry file declared in package.json is missing from the published package (github tarball or npm package); please commit build output or publish a complete package" : kind === "pluginPrepare" ? "plugin prepare/build script failed during install (packaging/distribution issue)" : kind === "pnpmIgnoredBuild" ? "plugin depends on a native module whose build script pnpm blocks by default (use a prebuilt variant)" : "plugin-side install failure";
|
|
438
498
|
const code = coreErrorCode(message);
|
|
439
499
|
const build = (coreChars) => {
|
|
440
500
|
const body = [
|
|
@@ -444,12 +504,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
444
504
|
"",
|
|
445
505
|
`## [DSH-Plugin 插件中心](${SITE_URL}) · 安装 Plugin 失败错误信息`,
|
|
446
506
|
`本错误信息由 [dsh-plugin-hub](${GITHUB_URL}) 插件中心的安装程序自动生成,随本次安装失败一并提交。`,
|
|
447
|
-
`-
|
|
507
|
+
`- 实际执行的安装命令:\`${command ?? `dsh plugin${env?.profile ? ` --profile ${env.profile}` : ""} add github:${repo}`}\``,
|
|
448
508
|
`- 执行结果:安装失败,未能安装该插件。`,
|
|
509
|
+
...attempts && attempts.length > 0 ? [
|
|
510
|
+
"",
|
|
511
|
+
"## Attempted install channels(已尝试的安装方式)",
|
|
512
|
+
...attempts.map((a) => `- ${a}`)
|
|
513
|
+
] : [],
|
|
449
514
|
.../\[packaging\]/i.test(message) ? [
|
|
450
515
|
"",
|
|
451
|
-
"##
|
|
452
|
-
"DSH
|
|
516
|
+
"## 安装方式说明",
|
|
517
|
+
"DSH 插件支持两种官方安装通道:`dsh plugin add <npm-package>`(npm 分发,需发布完整构建产物)与 `dsh plugin add github:owner/repo`(git 直装,仓库需提交构建产物或在 package.json 提供 `prepare` 脚本)。当前插件的分发物缺少 package.json 声明的入口文件,请按所用通道补齐后重新发布。"
|
|
453
518
|
] : [],
|
|
454
519
|
"",
|
|
455
520
|
"## Environment",
|
|
@@ -520,7 +585,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
520
585
|
topics: Array.isArray(raw.t) ? raw.t : void 0,
|
|
521
586
|
features: Array.isArray(raw.f) ? raw.f : void 0,
|
|
522
587
|
description: typeof raw.d === "string" ? raw.d : void 0,
|
|
523
|
-
source: typeof raw.r === "string" ? { repo: raw.r } :
|
|
588
|
+
source: typeof raw.r === "string" ? { repo: raw.r } : raw.r !== null && typeof raw.r === "object" ? {
|
|
589
|
+
repo: typeof raw.r.repo === "string" ? raw.r.repo : void 0,
|
|
590
|
+
npmPackage: typeof raw.r.npmPackage === "string" ? raw.r.npmPackage : void 0
|
|
591
|
+
} : void 0,
|
|
592
|
+
install: raw.wi === false ? { webInstallable: false } : void 0,
|
|
524
593
|
compatibility: typeof raw.v === "string" ? { status: raw.v } : void 0,
|
|
525
594
|
dates: {
|
|
526
595
|
repoUpdatedAt: typeof raw.u === "string" ? raw.u : void 0,
|
|
@@ -533,6 +602,28 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
533
602
|
};
|
|
534
603
|
return raw;
|
|
535
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* 安装通道决策(用户无感知):目录探测到 npm 包名 → 用 npm 包名安装
|
|
607
|
+
* (走 npm registry tarball,更快、与 GitHub 网络无关);无 npm 包名 → git 直装。
|
|
608
|
+
* 返回值 target 即传给后端 /install 的安装目标(npm 包名 或 owner/repo)。
|
|
609
|
+
*/
|
|
610
|
+
function installTargetOf(p) {
|
|
611
|
+
const pkg = (p.source?.npmPackage ?? "").trim();
|
|
612
|
+
const repo = (p.source?.repo ?? "").trim();
|
|
613
|
+
if (pkg && repo) return {
|
|
614
|
+
target: pkg,
|
|
615
|
+
via: "npm"
|
|
616
|
+
};
|
|
617
|
+
return {
|
|
618
|
+
target: repo,
|
|
619
|
+
via: "github"
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
/** 展示用安装命令(复制/弹窗):npm 通道显示包名,git 通道显示 github: 源。 */
|
|
623
|
+
function installCommandOf(p, withProfile = false) {
|
|
624
|
+
const { target, via } = installTargetOf(p);
|
|
625
|
+
return via === "npm" ? `dsh plugin${withProfile ? " --profile web" : ""} add ${target}` : `dsh plugin${withProfile ? " --profile web" : ""} add github:${target}`;
|
|
626
|
+
}
|
|
536
627
|
const CATEGORY_LABELS = {
|
|
537
628
|
interface: {
|
|
538
629
|
zh: "界面与体验",
|
|
@@ -650,6 +741,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
650
741
|
*/
|
|
651
742
|
const PLUGINS_URL = (lang) => `https://dsh-plugin.org/api/plugins.${lang}.json`;
|
|
652
743
|
const STATS_URL = "https://dsh-plugin.org/api/stats.json";
|
|
744
|
+
/** 插件市场自身仓库:DSH-Plugin Hub 不显示在目录里(自己不进自己的插件列表) */
|
|
745
|
+
const SELF_REPO = "dshplugin/dsh-plugin-hub";
|
|
653
746
|
function useCatalog(lang) {
|
|
654
747
|
/** 目录插件(仅保留人工验证通过的条目) */
|
|
655
748
|
const [plugins, setPlugins] = (0, react.useState)(null);
|
|
@@ -664,8 +757,13 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
664
757
|
const [installedFilter, setInstalledFilter] = (0, react.useState)("all");
|
|
665
758
|
/** 当前 profile 已安装插件:npm 包名 -> manifest spec(来自宿主本地路由) */
|
|
666
759
|
const [installed, setInstalled] = (0, react.useState)({});
|
|
667
|
-
/** 安装时记录的目录信号:repo(小写) -> { version, updatedAt }
|
|
760
|
+
/** 安装时记录的目录信号:repo(小写) -> { version, updatedAt }(来自宿主本地路由);
|
|
761
|
+
* npmPackage 为 npm 优先通道反查命中的包名映射(目录数据未下发时客户端靠它把依赖 key 匹配回仓库) */
|
|
668
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);
|
|
669
767
|
(0, react.useEffect)(() => {
|
|
670
768
|
let cancelled = false;
|
|
671
769
|
setPlugins(null);
|
|
@@ -675,20 +773,23 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
675
773
|
if (!res.ok) throw new Error(String(res.status));
|
|
676
774
|
return res.json();
|
|
677
775
|
});
|
|
678
|
-
fetchData(PLUGINS_URL(lang))
|
|
776
|
+
const load = () => Promise.all([fetchData(PLUGINS_URL(lang)), fetchData(STATS_URL)]);
|
|
777
|
+
load().then(([data, s]) => {
|
|
679
778
|
if (cancelled) return;
|
|
680
779
|
const list = (Array.isArray(data) ? data : []).map((item) => normalize(item));
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
if (!cancelled) setFailed(true);
|
|
684
|
-
});
|
|
685
|
-
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));
|
|
686
782
|
const stats = s;
|
|
687
|
-
if (
|
|
783
|
+
if (stats && typeof stats.total === "number" && typeof stats.verified === "number") setStats(hadSelf ? {
|
|
784
|
+
total: stats.total - 1,
|
|
785
|
+
verified: stats.verified - 1
|
|
786
|
+
} : {
|
|
688
787
|
total: stats.total,
|
|
689
788
|
verified: stats.verified
|
|
690
789
|
});
|
|
691
|
-
}).catch(() => {
|
|
790
|
+
}).catch(() => {
|
|
791
|
+
if (!cancelled) setFailed(true);
|
|
792
|
+
});
|
|
692
793
|
return () => {
|
|
693
794
|
cancelled = true;
|
|
694
795
|
};
|
|
@@ -706,12 +807,56 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
706
807
|
(0, react.useEffect)(() => {
|
|
707
808
|
refreshInstalled();
|
|
708
809
|
}, []);
|
|
709
|
-
|
|
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]);
|
|
850
|
+
/** 插件是否已安装:匹配 installed spec 中的 `github:<owner>/<repo>`,或 npm 通道安装的依赖包名;命中返回 npm 包名。 */
|
|
710
851
|
const installedName = (p) => {
|
|
711
852
|
const repo = p.source?.repo;
|
|
712
853
|
if (!repo) return null;
|
|
713
854
|
const needle = `github:${repo.toLowerCase()}`;
|
|
714
855
|
for (const [name, spec] of Object.entries(installed)) if (spec.toLowerCase().includes(needle)) return name;
|
|
856
|
+
const pkg = ((p.source?.npmPackage || versions[repo.toLowerCase()]?.npmPackage) ?? "").toLowerCase();
|
|
857
|
+
if (pkg) {
|
|
858
|
+
for (const name of Object.keys(installed)) if (name.toLowerCase() === pkg) return name;
|
|
859
|
+
}
|
|
715
860
|
return null;
|
|
716
861
|
};
|
|
717
862
|
/** 该插件安装时记录的目录版本(无记录/未安装 → null)。 */
|
|
@@ -735,6 +880,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
735
880
|
const current = p.dates?.repoUpdatedAt;
|
|
736
881
|
return Boolean(current && rec.updatedAt && current > rec.updatedAt);
|
|
737
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
|
+
})();
|
|
738
893
|
/** 当前分类下的插件(「全部」时为整个目录)。 */
|
|
739
894
|
const categoryPlugins = (0, react.useMemo)(() => {
|
|
740
895
|
if (!plugins) return [];
|
|
@@ -793,6 +948,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
793
948
|
installedName,
|
|
794
949
|
installedVersion,
|
|
795
950
|
hasUpdate,
|
|
951
|
+
hubHasUpdate,
|
|
952
|
+
hubUpdateInfo,
|
|
953
|
+
hubAboutInfo,
|
|
796
954
|
refreshInstalled,
|
|
797
955
|
category,
|
|
798
956
|
setCategory,
|
|
@@ -832,11 +990,15 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
832
990
|
resolvePendingRef.current = resolvePending;
|
|
833
991
|
/** 当前打开弹窗所对应的任务 id:该任务完成时弹窗切换为结果视图 */
|
|
834
992
|
const modalTaskRef = (0, react.useRef)(null);
|
|
993
|
+
/** 已开始收尾但尚未结束的任务 id(服务端 /active 已消失 → 查 /status 中):并发轮询时跳过,避免重复收尾 */
|
|
994
|
+
const settlingRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
835
995
|
/** 轮询定时器句柄(队列清空/组件卸载时清理) */
|
|
836
996
|
const pollRef = (0, react.useRef)(null);
|
|
837
997
|
/** 请求在途的目标集合(同步防重):双击安装/卸载时第二击直接忽略。
|
|
838
998
|
* 本地队列任务要等 fetch 返回后才入队,仅靠 queueRef 检查拦不住请求窗口内的重复点击。 */
|
|
839
999
|
const submittingRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
1000
|
+
/** 乐观入队临时 id 计数器:递减产生唯一负数,与服务端自增正数 id 永不冲突。 */
|
|
1001
|
+
const tempIdRef = (0, react.useRef)(0);
|
|
840
1002
|
/** 请求在途标记:弹窗据此禁用确认按钮,避免等待响应期间被再次点击。 */
|
|
841
1003
|
const [submitting, setSubmitting] = (0, react.useState)(false);
|
|
842
1004
|
/** 停止后台任务轮询(任务结束或组件卸载时清理)。 */
|
|
@@ -917,39 +1079,83 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
917
1079
|
refreshInstalled();
|
|
918
1080
|
if (q.kind === "uninstall") {
|
|
919
1081
|
syncInstalledVersion(q.repo, void 0, void 0);
|
|
920
|
-
onUninstallDone(modalTaskRef.current === q.id, q.repo);
|
|
1082
|
+
onUninstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart);
|
|
921
1083
|
} else {
|
|
922
1084
|
syncInstalledVersion(q.repo, q.version, q.updatedAt);
|
|
923
1085
|
pendingInfoRef.current.set(q.target, {
|
|
924
1086
|
desc: q.desc,
|
|
925
1087
|
version: q.version
|
|
926
1088
|
});
|
|
927
|
-
onInstallDone(modalTaskRef.current === q.id, q.repo);
|
|
1089
|
+
onInstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart);
|
|
928
1090
|
}
|
|
929
1091
|
} else {
|
|
930
1092
|
const detail = lines.length > 0 ? [...lines].reverse().join("\n") : q.kind === "uninstall" ? t("uninstallFail") : t("installFail");
|
|
931
|
-
onError(detail, q.repo, q.kind);
|
|
1093
|
+
onError(detail, q.repo, q.kind, q.command, q.attempts);
|
|
932
1094
|
}
|
|
933
1095
|
maybeStopPoll();
|
|
934
1096
|
};
|
|
1097
|
+
/** 卸载成功收尾前的进度过渡:任务已在服务端结束,但保留本地展示,
|
|
1098
|
+
* 让进度条在 ~2.4s 内缓缓跑到 100% 再切结果/Toast,给用户一个交互过程,
|
|
1099
|
+
* 而不是命令一执行进度条就一闪消失。 */
|
|
1100
|
+
const settleDone = (q, lines) => {
|
|
1101
|
+
stopPoll();
|
|
1102
|
+
const from = Math.min(q.progress, 90);
|
|
1103
|
+
const steps = 20;
|
|
1104
|
+
const stepMs = 120;
|
|
1105
|
+
let step = 0;
|
|
1106
|
+
applyQueue((prev) => prev.map((x) => x.id === q.id ? {
|
|
1107
|
+
...x,
|
|
1108
|
+
status: "running"
|
|
1109
|
+
} : x));
|
|
1110
|
+
const timer = window.setInterval(() => {
|
|
1111
|
+
step += 1;
|
|
1112
|
+
const progress = Math.round(from + (100 - from) * (step / steps));
|
|
1113
|
+
applyQueue((prev) => prev.map((x) => x.id === q.id ? {
|
|
1114
|
+
...x,
|
|
1115
|
+
progress
|
|
1116
|
+
} : x));
|
|
1117
|
+
if (step >= steps) {
|
|
1118
|
+
window.clearInterval(timer);
|
|
1119
|
+
finishQueueTask(true, q, lines);
|
|
1120
|
+
if (queueRef.current.length > 0) pollQueue();
|
|
1121
|
+
}
|
|
1122
|
+
}, stepMs);
|
|
1123
|
+
};
|
|
935
1124
|
/** 任务在 /active 中消失 = 已结束:查 /status 拿终态并收尾(cancelled 静默移除)。 */
|
|
936
1125
|
const settleTask = async (q) => {
|
|
937
1126
|
let status = "failed";
|
|
938
1127
|
let lines = [];
|
|
1128
|
+
let attempts;
|
|
939
1129
|
try {
|
|
940
1130
|
const res = await fetch(`/dsh-plugin-hub/status?task=${q.id}`, { cache: "no-store" });
|
|
941
1131
|
if (res.ok) {
|
|
942
|
-
const
|
|
943
|
-
|
|
944
|
-
|
|
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
|
+
}
|
|
945
1155
|
}
|
|
946
1156
|
} catch {}
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
else {
|
|
950
|
-
applyQueue((prev) => prev.filter((x) => x.id !== q.id));
|
|
951
|
-
maybeStopPoll();
|
|
952
|
-
}
|
|
1157
|
+
applyQueue((prev) => prev.filter((x) => x.id !== q.id));
|
|
1158
|
+
maybeStopPoll();
|
|
953
1159
|
};
|
|
954
1160
|
/** 轮询整个队列:合并服务端 /active(running 在前、pending 在后),
|
|
955
1161
|
* 消失的任务查终态收尾;队列清空即停止轮询。 */
|
|
@@ -980,13 +1186,27 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
980
1186
|
updatedAt: prevTask?.updatedAt,
|
|
981
1187
|
status: a.status === "running" ? "running" : "pending",
|
|
982
1188
|
progress: typeof a.progress === "number" ? a.progress : prevTask?.progress ?? 0,
|
|
983
|
-
lines: Array.isArray(a.lines) ? a.lines : prevTask?.lines ?? []
|
|
1189
|
+
lines: Array.isArray(a.lines) ? a.lines : prevTask?.lines ?? [],
|
|
1190
|
+
attempts: Array.isArray(a.attempts) ? a.attempts : prevTask?.attempts ?? [],
|
|
1191
|
+
needsRestart: typeof a.needsRestart === "boolean" ? a.needsRestart : prevTask?.needsRestart ?? true
|
|
984
1192
|
});
|
|
985
1193
|
}
|
|
1194
|
+
const keepOpt = prev.filter((q) => q.optimistic && !next.some((x) => x.id === q.id));
|
|
1195
|
+
if (keepOpt.length > 0) next.push(...keepOpt);
|
|
1196
|
+
const keepGone = prev.filter((q) => !byId.has(q.id) && !next.some((x) => x.id === q.id) && q.status !== "cancelling" && !q.optimistic);
|
|
1197
|
+
if (keepGone.length > 0) next.push(...keepGone);
|
|
986
1198
|
return next;
|
|
987
1199
|
});
|
|
988
|
-
const gone = prevQueue.filter((q) => !byId.has(q.id) && q.status !== "cancelling");
|
|
989
|
-
for (const q of gone)
|
|
1200
|
+
const gone = prevQueue.filter((q) => !byId.has(q.id) && q.status !== "cancelling" && !q.optimistic && !settlingRef.current.has(q.id));
|
|
1201
|
+
for (const q of gone) {
|
|
1202
|
+
if (!queueRef.current.some((x) => x.id === q.id)) continue;
|
|
1203
|
+
settlingRef.current.add(q.id);
|
|
1204
|
+
try {
|
|
1205
|
+
await settleTask(q);
|
|
1206
|
+
} finally {
|
|
1207
|
+
settlingRef.current.delete(q.id);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
990
1210
|
} catch {}
|
|
991
1211
|
}, 600);
|
|
992
1212
|
};
|
|
@@ -1001,14 +1221,18 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1001
1221
|
applyPending(parsePendingRestarts(data.pendingRestarts));
|
|
1002
1222
|
const items = (data.tasks ?? []).filter((a) => typeof a.id === "number").map((a) => {
|
|
1003
1223
|
const isRemove = a.action === "remove";
|
|
1224
|
+
const display = typeof a.displayTarget === "string" ? a.displayTarget.replace(/^github:/, "") : "";
|
|
1225
|
+
const fallback = typeof a.target === "string" ? a.target.replace(/^github:/, "") : "";
|
|
1004
1226
|
return {
|
|
1005
1227
|
id: a.id,
|
|
1006
1228
|
kind: isRemove ? "uninstall" : "install",
|
|
1007
|
-
target:
|
|
1008
|
-
repo: isRemove ? null :
|
|
1229
|
+
target: isRemove ? fallback : display || fallback,
|
|
1230
|
+
repo: isRemove ? null : display || fallback,
|
|
1009
1231
|
status: a.status === "running" ? "running" : "pending",
|
|
1010
1232
|
progress: typeof a.progress === "number" ? a.progress : 0,
|
|
1011
|
-
lines: Array.isArray(a.lines) ? a.lines : []
|
|
1233
|
+
lines: Array.isArray(a.lines) ? a.lines : [],
|
|
1234
|
+
attempts: Array.isArray(a.attempts) ? a.attempts : [],
|
|
1235
|
+
needsRestart: typeof a.needsRestart === "boolean" ? a.needsRestart : true
|
|
1012
1236
|
};
|
|
1013
1237
|
});
|
|
1014
1238
|
if (items.length > 0 || pendingRef.current.length > 0) {
|
|
@@ -1026,45 +1250,62 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1026
1250
|
const installNow = async (p, opts) => {
|
|
1027
1251
|
const repo = p.source?.repo ?? "";
|
|
1028
1252
|
if (!repo) return;
|
|
1253
|
+
const { target } = installTargetOf(p);
|
|
1254
|
+
if (!target) return;
|
|
1029
1255
|
if (queueRef.current.some((q) => q.kind === "install" && q.target === repo)) return;
|
|
1030
1256
|
if (submittingRef.current.has(repo)) return;
|
|
1031
1257
|
submittingRef.current.add(repo);
|
|
1258
|
+
tempIdRef.current -= 1;
|
|
1259
|
+
const tempId = tempIdRef.current;
|
|
1260
|
+
modalTaskRef.current = tempId;
|
|
1261
|
+
applyQueue((prev) => [...prev, {
|
|
1262
|
+
id: tempId,
|
|
1263
|
+
kind: "install",
|
|
1264
|
+
target: repo,
|
|
1265
|
+
repo,
|
|
1266
|
+
desc: p.description,
|
|
1267
|
+
version: p.version,
|
|
1268
|
+
updatedAt: p.dates?.repoUpdatedAt,
|
|
1269
|
+
status: "running",
|
|
1270
|
+
progress: 0,
|
|
1271
|
+
lines: [],
|
|
1272
|
+
optimistic: true,
|
|
1273
|
+
command: installCommandOf(p, true),
|
|
1274
|
+
attempts: [],
|
|
1275
|
+
needsRestart: true
|
|
1276
|
+
}]);
|
|
1032
1277
|
setSubmitting(true);
|
|
1033
1278
|
try {
|
|
1034
1279
|
const res = await fetch("/dsh-plugin-hub/install", {
|
|
1035
1280
|
method: "POST",
|
|
1036
1281
|
headers: { "content-type": "application/json" },
|
|
1037
1282
|
body: JSON.stringify({
|
|
1038
|
-
repo,
|
|
1283
|
+
repo: target,
|
|
1284
|
+
display: repo,
|
|
1039
1285
|
mode: opts?.update ? "update" : void 0
|
|
1040
1286
|
})
|
|
1041
1287
|
});
|
|
1042
1288
|
const data = await res.json();
|
|
1043
1289
|
if (!data.ok || typeof data.task !== "number") {
|
|
1044
|
-
|
|
1290
|
+
applyQueue((prev) => prev.filter((x) => x.id !== tempId));
|
|
1291
|
+
onError(data.error ?? `HTTP ${res.status}`, repo, "install", installCommandOf(p, true), data.attempts);
|
|
1045
1292
|
return;
|
|
1046
1293
|
}
|
|
1047
1294
|
const taskId = data.task;
|
|
1048
1295
|
modalTaskRef.current = taskId;
|
|
1049
|
-
applyQueue((prev) =>
|
|
1296
|
+
applyQueue((prev) => prev.map((x) => x.id === tempId ? {
|
|
1297
|
+
...x,
|
|
1050
1298
|
id: taskId,
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
repo,
|
|
1054
|
-
desc: p.description,
|
|
1055
|
-
version: p.version,
|
|
1056
|
-
updatedAt: p.dates?.repoUpdatedAt,
|
|
1057
|
-
status: "pending",
|
|
1058
|
-
progress: 0,
|
|
1059
|
-
lines: []
|
|
1060
|
-
}]);
|
|
1299
|
+
optimistic: void 0
|
|
1300
|
+
} : x));
|
|
1061
1301
|
pendingInfoRef.current.set(repo, {
|
|
1062
1302
|
desc: p.description,
|
|
1063
1303
|
version: p.version
|
|
1064
1304
|
});
|
|
1065
1305
|
pollQueue();
|
|
1066
1306
|
} catch {
|
|
1067
|
-
|
|
1307
|
+
applyQueue((prev) => prev.filter((x) => x.id !== tempId));
|
|
1308
|
+
onError(t("installFail"), repo, "install", installCommandOf(p, true));
|
|
1068
1309
|
} finally {
|
|
1069
1310
|
submittingRef.current.delete(repo);
|
|
1070
1311
|
setSubmitting(false);
|
|
@@ -1103,7 +1344,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1103
1344
|
repo,
|
|
1104
1345
|
status: "pending",
|
|
1105
1346
|
progress: 0,
|
|
1106
|
-
lines: []
|
|
1347
|
+
lines: [],
|
|
1348
|
+
needsRestart: true
|
|
1107
1349
|
}]);
|
|
1108
1350
|
pollQueue();
|
|
1109
1351
|
} catch {
|
|
@@ -1150,7 +1392,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1150
1392
|
}
|
|
1151
1393
|
//#endregion
|
|
1152
1394
|
//#region \0dsh-css:src/client/styles/Modal.module.css.mjs
|
|
1153
|
-
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;align-items:center;gap:10px;padding:10px 12px;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_failTime{color:var(--hub-text-tertiary);font-variant-numeric:tabular-nums;flex-shrink:0;font-size:11px;line-height:16px}.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}";
|
|
1154
1396
|
const tagId$3 = "dsh-plugin/Modal.module.css";
|
|
1155
1397
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
1156
1398
|
const tag = document.createElement("style");
|
|
@@ -1160,90 +1402,103 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1160
1402
|
document.head.appendChild(tag);
|
|
1161
1403
|
}
|
|
1162
1404
|
var Modal_module_css_default = {
|
|
1163
|
-
"queueRowTrack": "BiQ1zG_queueRowTrack",
|
|
1164
|
-
"pendingRowStatus": "BiQ1zG_pendingRowStatus",
|
|
1165
|
-
"resultRestarting": "BiQ1zG_resultRestarting",
|
|
1166
|
-
"resultTitle": "BiQ1zG_resultTitle",
|
|
1167
|
-
"linkIcon": "BiQ1zG_linkIcon",
|
|
1168
|
-
"errorHint": "BiQ1zG_errorHint",
|
|
1169
|
-
"modalCloseIcon": "BiQ1zG_modalCloseIcon",
|
|
1170
|
-
"modalCmdText": "BiQ1zG_modalCmdText",
|
|
1171
|
-
"failList": "BiQ1zG_failList",
|
|
1172
|
-
"failCopy": "BiQ1zG_failCopy",
|
|
1173
|
-
"pendingRowActions": "BiQ1zG_pendingRowActions",
|
|
1174
1405
|
"modalTitle": "BiQ1zG_modalTitle",
|
|
1175
|
-
"
|
|
1176
|
-
"queueRowTarget": "BiQ1zG_queueRowTarget",
|
|
1177
|
-
"restartLater": "BiQ1zG_restartLater",
|
|
1178
|
-
"progressFillFail": "BiQ1zG_progressFillFail",
|
|
1179
|
-
"toast": "BiQ1zG_toast",
|
|
1180
|
-
"modalTitleQueued": "BiQ1zG_modalTitleQueued",
|
|
1181
|
-
"queueSection": "BiQ1zG_queueSection",
|
|
1406
|
+
"errorHint": "BiQ1zG_errorHint",
|
|
1182
1407
|
"resultCheck": "BiQ1zG_resultCheck",
|
|
1183
|
-
"
|
|
1184
|
-
"
|
|
1185
|
-
"
|
|
1186
|
-
"
|
|
1187
|
-
"
|
|
1188
|
-
"
|
|
1189
|
-
"failEmpty": "BiQ1zG_failEmpty",
|
|
1190
|
-
"overlayIn": "BiQ1zG_overlayIn",
|
|
1408
|
+
"noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
|
|
1409
|
+
"toastIn": "BiQ1zG_toastIn",
|
|
1410
|
+
"modalLabel": "BiQ1zG_modalLabel",
|
|
1411
|
+
"resultDesc": "BiQ1zG_resultDesc",
|
|
1412
|
+
"modalDesc": "BiQ1zG_modalDesc",
|
|
1413
|
+
"pendingRowActions": "BiQ1zG_pendingRowActions",
|
|
1191
1414
|
"errorCopySoft": "BiQ1zG_errorCopySoft",
|
|
1192
|
-
"
|
|
1193
|
-
"failBigIssue": "BiQ1zG_failBigIssue",
|
|
1194
|
-
"modalActions": "BiQ1zG_modalActions",
|
|
1195
|
-
"progressTrack": "BiQ1zG_progressTrack",
|
|
1196
|
-
"modalCmd": "BiQ1zG_modalCmd",
|
|
1197
|
-
"failTime": "BiQ1zG_failTime",
|
|
1415
|
+
"modalLink": "BiQ1zG_modalLink",
|
|
1198
1416
|
"overlay": "BiQ1zG_overlay",
|
|
1199
|
-
"failHead": "BiQ1zG_failHead",
|
|
1200
|
-
"queueRowDesc": "BiQ1zG_queueRowDesc",
|
|
1201
|
-
"failRepo": "BiQ1zG_failRepo",
|
|
1202
|
-
"modalCopy": "BiQ1zG_modalCopy",
|
|
1203
1417
|
"uninstallConfirm": "BiQ1zG_uninstallConfirm",
|
|
1204
|
-
"
|
|
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",
|
|
1205
1425
|
"restartNow": "BiQ1zG_restartNow",
|
|
1206
|
-
"
|
|
1207
|
-
"queueRowHead": "BiQ1zG_queueRowHead",
|
|
1208
|
-
"noticeBadgeOk": "BiQ1zG_noticeBadgeOk",
|
|
1209
|
-
"queueRowPct": "BiQ1zG_queueRowPct",
|
|
1210
|
-
"queueRowBody": "BiQ1zG_queueRowBody",
|
|
1211
|
-
"modalTitleBusy": "BiQ1zG_modalTitleBusy",
|
|
1212
|
-
"failKind": "BiQ1zG_failKind",
|
|
1213
|
-
"errorBox": "BiQ1zG_errorBox",
|
|
1214
|
-
"modalLink": "BiQ1zG_modalLink",
|
|
1215
|
-
"failKindUninstall": "BiQ1zG_failKindUninstall",
|
|
1426
|
+
"result": "BiQ1zG_result",
|
|
1216
1427
|
"modalRow": "BiQ1zG_modalRow",
|
|
1428
|
+
"queueRowBody": "BiQ1zG_queueRowBody",
|
|
1429
|
+
"modalInstall": "BiQ1zG_modalInstall",
|
|
1430
|
+
"noticeMain": "BiQ1zG_noticeMain",
|
|
1431
|
+
"linkIcon": "BiQ1zG_linkIcon",
|
|
1432
|
+
"noticeTime": "BiQ1zG_noticeTime",
|
|
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",
|
|
1445
|
+
"queueRowDesc": "BiQ1zG_queueRowDesc",
|
|
1446
|
+
"failList": "BiQ1zG_failList",
|
|
1217
1447
|
"toastFail": "BiQ1zG_toastFail",
|
|
1218
|
-
"
|
|
1219
|
-
"modalDesc": "BiQ1zG_modalDesc",
|
|
1220
|
-
"failKindInstall": "BiQ1zG_failKindInstall",
|
|
1221
|
-
"modal": "BiQ1zG_modal",
|
|
1222
|
-
"stripCancel": "BiQ1zG_stripCancel",
|
|
1448
|
+
"modalActions": "BiQ1zG_modalActions",
|
|
1223
1449
|
"progressText": "BiQ1zG_progressText",
|
|
1224
|
-
"
|
|
1450
|
+
"hubUpdateMetaItem": "BiQ1zG_hubUpdateMetaItem",
|
|
1451
|
+
"modalCopy": "BiQ1zG_modalCopy",
|
|
1452
|
+
"resultRestarting": "BiQ1zG_resultRestarting",
|
|
1225
1453
|
"queueSectionTitle": "BiQ1zG_queueSectionTitle",
|
|
1226
1454
|
"modalBody": "BiQ1zG_modalBody",
|
|
1227
|
-
"
|
|
1228
|
-
"
|
|
1229
|
-
"
|
|
1230
|
-
"
|
|
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",
|
|
1467
|
+
"progressFill": "BiQ1zG_progressFill",
|
|
1468
|
+
"aboutModal": "BiQ1zG_aboutModal",
|
|
1469
|
+
"failedCopyHint": "BiQ1zG_failedCopyHint",
|
|
1231
1470
|
"queueRowStatus": "BiQ1zG_queueRowStatus",
|
|
1232
|
-
"
|
|
1233
|
-
"
|
|
1234
|
-
"modalIn": "BiQ1zG_modalIn",
|
|
1235
|
-
"noticeHead": "BiQ1zG_noticeHead",
|
|
1471
|
+
"progressTrack": "BiQ1zG_progressTrack",
|
|
1472
|
+
"modalHead": "BiQ1zG_modalHead",
|
|
1236
1473
|
"modalCmdCopy": "BiQ1zG_modalCmdCopy",
|
|
1237
|
-
"
|
|
1238
|
-
"result": "BiQ1zG_result",
|
|
1239
|
-
"errorModal": "BiQ1zG_errorModal",
|
|
1240
|
-
"failPrepareHint": "BiQ1zG_failPrepareHint",
|
|
1241
|
-
"errorTitle": "BiQ1zG_errorTitle",
|
|
1242
|
-
"queuedHint": "BiQ1zG_queuedHint",
|
|
1474
|
+
"modal": "BiQ1zG_modal",
|
|
1243
1475
|
"modalValue": "BiQ1zG_modalValue",
|
|
1244
|
-
"
|
|
1476
|
+
"failKindInstall": "BiQ1zG_failKindInstall",
|
|
1477
|
+
"noticeFoot": "BiQ1zG_noticeFoot",
|
|
1478
|
+
"failClear": "BiQ1zG_failClear",
|
|
1479
|
+
"queueRow": "BiQ1zG_queueRow",
|
|
1480
|
+
"toast": "BiQ1zG_toast",
|
|
1481
|
+
"noticeTextOk": "BiQ1zG_noticeTextOk",
|
|
1245
1482
|
"noticeTextFail": "BiQ1zG_noticeTextFail",
|
|
1246
|
-
"
|
|
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"
|
|
1247
1502
|
};
|
|
1248
1503
|
//#endregion
|
|
1249
1504
|
//#region src/client/components/icons.tsx
|
|
@@ -1422,8 +1677,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1422
1677
|
* or restart is running, then switch to a result view offering an immediate
|
|
1423
1678
|
* restart or a "later" deferral.
|
|
1424
1679
|
*/
|
|
1425
|
-
/** 完成结果视图:绿色对勾 +
|
|
1426
|
-
|
|
1680
|
+
/** 完成结果视图:绿色对勾 + 标题/描述;
|
|
1681
|
+
* needsRestart=true(插件需重启才生效)→ 「稍后重启 / 立即重启」按钮对,点稍后重启后
|
|
1682
|
+
* 通知中心待重启条目常驻(服务端登记,内存态),直到用户点「立即重启」真正重启后才消失;
|
|
1683
|
+
* needsRestart=false(卸载已即时生效)→ 仅「完成」关闭。 */
|
|
1684
|
+
function ResultView({ title, desc, t, restarting, needsRestart, onRestart, onClose }) {
|
|
1427
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", {
|
|
1428
1686
|
className: Modal_module_css_default.resultCheckIcon,
|
|
1429
1687
|
viewBox: "0 0 16 16",
|
|
@@ -1437,7 +1695,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1437
1695
|
strokeWidth: 2,
|
|
1438
1696
|
strokeLinecap: "round",
|
|
1439
1697
|
strokeLinejoin: "round"
|
|
1440
|
-
}))), (0, react.createElement)("div", { className: Modal_module_css_default.resultTitle }, title), (0, react.createElement)("div", { className: Modal_module_css_default.resultDesc }, desc), (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", {
|
|
1441
1699
|
className: Modal_module_css_default.restartLater,
|
|
1442
1700
|
onClick: onClose,
|
|
1443
1701
|
disabled: restarting
|
|
@@ -1445,14 +1703,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1445
1703
|
className: Modal_module_css_default.restartNow,
|
|
1446
1704
|
onClick: onRestart,
|
|
1447
1705
|
disabled: restarting
|
|
1448
|
-
}, 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"))));
|
|
1449
1710
|
}
|
|
1450
1711
|
/**
|
|
1451
1712
|
* 信任确认弹窗:安装进入后台队列后弹窗仍可关闭(任务继续),
|
|
1452
1713
|
* 只在本任务执行中展示实时进度;完成后切换为结果视图,与卸载一致。
|
|
1453
1714
|
*/
|
|
1454
1715
|
function InstallModal(props) {
|
|
1455
|
-
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;
|
|
1456
1717
|
const busy = submitting || task !== null && (task.status === "pending" || task.status === "running");
|
|
1457
1718
|
const name = plugin.displayName ?? plugin.slug;
|
|
1458
1719
|
const busyTitle = (label) => langPath === "zh/" ? `${name} 插件${label}` : `${label} ${name}`;
|
|
@@ -1475,6 +1736,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1475
1736
|
desc: update ? t("updateResultDesc") : t("installResultDesc"),
|
|
1476
1737
|
t,
|
|
1477
1738
|
restarting,
|
|
1739
|
+
needsRestart,
|
|
1478
1740
|
onRestart,
|
|
1479
1741
|
onClose
|
|
1480
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", {
|
|
@@ -1492,7 +1754,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1492
1754
|
title: t("copyInstallCommand"),
|
|
1493
1755
|
role: "button",
|
|
1494
1756
|
tabIndex: 0
|
|
1495
|
-
}, (0, react.createElement)("span", { className: Modal_module_css_default.modalCmdText },
|
|
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", {
|
|
1496
1758
|
className: Modal_module_css_default.modalCopy,
|
|
1497
1759
|
disabled: busy,
|
|
1498
1760
|
onClick: onCopy
|
|
@@ -1504,7 +1766,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1504
1766
|
}
|
|
1505
1767
|
/** 卸载确认弹窗:确认/进行中(后台队列,可关闭);完成后切换为结果视图(成功即生效,仅「完成」关闭)。 */
|
|
1506
1768
|
function UninstallModal(props) {
|
|
1507
|
-
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;
|
|
1508
1770
|
const busy = submitting || task !== null && (task.status === "pending" || task.status === "running");
|
|
1509
1771
|
const name = plugin.displayName ?? plugin.slug;
|
|
1510
1772
|
const busyTitle = (label) => langPath === "zh/" ? `${name} 插件${label}` : `${label} ${name}`;
|
|
@@ -1527,6 +1789,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1527
1789
|
desc: t("uninstallResultDesc"),
|
|
1528
1790
|
t,
|
|
1529
1791
|
restarting,
|
|
1792
|
+
needsRestart,
|
|
1530
1793
|
onRestart,
|
|
1531
1794
|
onClose
|
|
1532
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", {
|
|
@@ -1553,7 +1816,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1553
1816
|
}
|
|
1554
1817
|
/** 预填插件仓库的 GitHub Issue 链接:标题带插件名,正文附完整错误信息,方便用户一键反馈。 */
|
|
1555
1818
|
/** 安装/卸载失败弹窗:布局与失败记录一致(类型徽标 + 仓库超链接 + 隐蔽复制按钮),报错完整展示,底部一键提交 Issue。 */
|
|
1556
|
-
function ErrorModal({ message, repo, kind, t, env, onCopy, onClose }) {
|
|
1819
|
+
function ErrorModal({ message, repo, kind, command, attempts, t, env, onCopy, onClose }) {
|
|
1557
1820
|
const failureKind = classifyFailure(message);
|
|
1558
1821
|
return (0, react.createElement)("div", {
|
|
1559
1822
|
className: Modal_module_css_default.overlay,
|
|
@@ -1579,13 +1842,13 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1579
1842
|
onClick: () => onCopy(message)
|
|
1580
1843
|
}, t("errorCopy"))), (0, react.createElement)("pre", { className: Modal_module_css_default.errorBox }, message), failureKind === "pluginPrepare" || failureKind === "pnpmIgnoredBuild" ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, failureKind === "pnpmIgnoredBuild" ? t("failIgnoredBuild") : /\[packaging\]/i.test(message) ? t("failPackagingHint") : t("failPrepareHint")), repo ? (0, react.createElement)("a", {
|
|
1581
1844
|
className: Modal_module_css_default.failBigIssue,
|
|
1582
|
-
href: pluginIssueUrl(repo, message, env),
|
|
1845
|
+
href: pluginIssueUrl(repo, message, env, command, attempts),
|
|
1583
1846
|
target: "_blank",
|
|
1584
1847
|
rel: "noopener noreferrer",
|
|
1585
1848
|
title: t("failIssueHint")
|
|
1586
1849
|
}, t("failIssueBig")) : null]) : repo ? (0, react.createElement)("a", {
|
|
1587
1850
|
className: Modal_module_css_default.failBigIssue,
|
|
1588
|
-
href: pluginIssueUrl(repo, message, env),
|
|
1851
|
+
href: pluginIssueUrl(repo, message, env, command, attempts),
|
|
1589
1852
|
target: "_blank",
|
|
1590
1853
|
rel: "noopener noreferrer",
|
|
1591
1854
|
title: t("failIssueHint")
|
|
@@ -1604,6 +1867,175 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1604
1867
|
}, text);
|
|
1605
1868
|
}
|
|
1606
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
|
+
* 链接、图片(,如反馈群二维码)、引用(>)、段落;其余语法一律按
|
|
1879
|
+
* 纯文本处理,不引入外部依赖。图片仅放行 http(s),限定最大宽度不撑破弹窗。
|
|
1880
|
+
*/
|
|
1881
|
+
/** HTML 转义:所有文本先进这里,再进入结构变换,保证输出里没有未转义的用户输入。 */
|
|
1882
|
+
function escapeHtml(s) {
|
|
1883
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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 的  语法嵌入,居中、最大高度受控。
|
|
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
|
|
1607
2039
|
//#region src/client/components/NotificationsModal.tsx
|
|
1608
2040
|
/**
|
|
1609
2041
|
* Notification-center dialog: a persistent log of every settled install /
|
|
@@ -1616,12 +2048,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1616
2048
|
* failures keep their copy / fix / file-an-issue actions. Opened from the
|
|
1617
2049
|
* header entry button.
|
|
1618
2050
|
*/
|
|
1619
|
-
/**
|
|
2051
|
+
/** 记录时间完整展示:YYYY-MM-DD HH:mm:ss(每条通知都带精确到秒的时间戳)。 */
|
|
1620
2052
|
function fmtTime(at) {
|
|
1621
2053
|
const d = new Date(at);
|
|
1622
2054
|
const pad = (n) => String(n).padStart(2, "0");
|
|
1623
|
-
|
|
1624
|
-
return d.getFullYear() === (/* @__PURE__ */ new Date()).getFullYear() ? mmdd : `${d.getFullYear()}-${mmdd}`;
|
|
2055
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
1625
2056
|
}
|
|
1626
2057
|
/** 圆形状态徽标内的白色图形:成功为对勾、失败为叉。 */
|
|
1627
2058
|
function BadgeGlyph({ ok }) {
|
|
@@ -1645,7 +2076,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1645
2076
|
strokeLinecap: "round"
|
|
1646
2077
|
}));
|
|
1647
2078
|
}
|
|
1648
|
-
function NotificationsModal({ records, tasks, pendingRestarts, t, env, onClose, onCopy, onClear, cancelTask, restarting, onRestart }) {
|
|
2079
|
+
function NotificationsModal({ records, tasks, pendingRestarts, t, env, onClose, onCopy, onClear, onRemove, cancelTask, restarting, onRestart }) {
|
|
1649
2080
|
return (0, react.createElement)("div", {
|
|
1650
2081
|
className: Modal_module_css_default.overlay,
|
|
1651
2082
|
onClick: (e) => {
|
|
@@ -1698,36 +2129,47 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1698
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) => {
|
|
1699
2130
|
return (0, react.createElement)("div", {
|
|
1700
2131
|
key: r.id,
|
|
1701
|
-
className: Modal_module_css_default.noticeRow
|
|
1702
|
-
}, (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", {
|
|
2132
|
+
className: r.ok ? `${Modal_module_css_default.noticeRow} ${Modal_module_css_default.noticeRowOk}` : Modal_module_css_default.noticeRow
|
|
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", {
|
|
1703
2134
|
className: Modal_module_css_default.failRepo,
|
|
1704
2135
|
href: pluginSiteUrl(r.repo),
|
|
1705
2136
|
target: "_blank",
|
|
1706
2137
|
rel: "noopener noreferrer",
|
|
1707
2138
|
title: r.repo
|
|
1708
|
-
}, r.repo) : null, (0, react.createElement)("
|
|
1709
|
-
className: Modal_module_css_default.failTime,
|
|
1710
|
-
title: new Date(r.at).toLocaleString()
|
|
1711
|
-
}, fmtTime(r.at)), !r.ok && (0, react.createElement)("button", {
|
|
2139
|
+
}, r.repo) : null, !r.ok && (0, react.createElement)("button", {
|
|
1712
2140
|
className: Modal_module_css_default.failCopy,
|
|
1713
2141
|
onClick: () => onCopy(r.message)
|
|
1714
|
-
}, t("failCopy"))
|
|
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", {
|
|
2146
|
+
className: Modal_module_css_default.noticeRemove,
|
|
2147
|
+
"aria-label": t("removeNotification"),
|
|
2148
|
+
title: t("removeNotification"),
|
|
2149
|
+
onClick: (e) => {
|
|
2150
|
+
e.stopPropagation();
|
|
2151
|
+
onRemove(r.id);
|
|
2152
|
+
}
|
|
2153
|
+
}, (0, react.createElement)(CloseIcon))), !r.ok && (() => {
|
|
1715
2154
|
const kind = classifyFailure(r.message);
|
|
1716
2155
|
if (kind === "pluginPrepare" || kind === "pnpmIgnoredBuild") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, kind === "pnpmIgnoredBuild" ? t("failIgnoredBuild") : /\[packaging\]/i.test(r.message) ? t("failPackagingHint") : t("failPrepareHint")), r.repo ? (0, react.createElement)("a", {
|
|
1717
2156
|
className: Modal_module_css_default.failBigIssue,
|
|
1718
|
-
href: pluginIssueUrl(r.repo, r.message, env),
|
|
2157
|
+
href: pluginIssueUrl(r.repo, r.message, env, r.command, r.attempts),
|
|
1719
2158
|
target: "_blank",
|
|
1720
2159
|
rel: "noopener noreferrer",
|
|
1721
2160
|
title: t("failIssueHint")
|
|
1722
2161
|
}, t("failIssueBig")) : null]);
|
|
1723
2162
|
return r.repo ? (0, react.createElement)("a", {
|
|
1724
2163
|
className: Modal_module_css_default.failBigIssue,
|
|
1725
|
-
href: pluginIssueUrl(r.repo, r.message, env),
|
|
2164
|
+
href: pluginIssueUrl(r.repo, r.message, env, r.command, r.attempts),
|
|
1726
2165
|
target: "_blank",
|
|
1727
2166
|
rel: "noopener noreferrer",
|
|
1728
2167
|
title: t("failIssueHint")
|
|
1729
2168
|
}, t("failIssueBig")) : null;
|
|
1730
|
-
})()))
|
|
2169
|
+
})())), !r.ok ? (0, react.createElement)("div", { className: Modal_module_css_default.noticeFoot }, (0, react.createElement)("span", {
|
|
2170
|
+
className: Modal_module_css_default.noticeTime,
|
|
2171
|
+
title: new Date(r.at).toLocaleString()
|
|
2172
|
+
}, fmtTime(r.at))) : null);
|
|
1731
2173
|
})), (0, react.createElement)("div", { className: Modal_module_css_default.modalActions }, records.length > 0 ? (0, react.createElement)("button", {
|
|
1732
2174
|
className: Modal_module_css_default.failClear,
|
|
1733
2175
|
onClick: onClear
|
|
@@ -1742,7 +2184,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1742
2184
|
* Section header: brand title row (H1 + open-site button) + tagline, followed
|
|
1743
2185
|
* by the purple ad banner that promotes the catalog stats.
|
|
1744
2186
|
*/
|
|
1745
|
-
function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang }) {
|
|
2187
|
+
function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang, hubUpdate, onVersionClick, onAboutClick }) {
|
|
1746
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", {
|
|
1747
2189
|
className: Header_module_css_default.brandTitle,
|
|
1748
2190
|
href: `${SITE_URL}${langPath}`,
|
|
@@ -1750,13 +2192,25 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1750
2192
|
rel: "noopener noreferrer",
|
|
1751
2193
|
title: t("openHint"),
|
|
1752
2194
|
"aria-label": t("openHint")
|
|
1753
|
-
}, (0, react.createElement)(LogoIcon), (0, react.createElement)("h1", { className: Header_module_css_default.title }, t("title")
|
|
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", {
|
|
1754
2202
|
className: Header_module_css_default.langBtn,
|
|
1755
2203
|
type: "button",
|
|
1756
2204
|
onClick: onToggleLang,
|
|
1757
2205
|
title: t("toggleLangHint"),
|
|
1758
2206
|
"aria-label": t("toggleLangHint")
|
|
1759
|
-
}, langPath === "zh/" ? "EN" : "中文"), (0, react.createElement)("
|
|
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", {
|
|
1760
2214
|
className: Header_module_css_default.githubLink,
|
|
1761
2215
|
href: GITHUB_URL,
|
|
1762
2216
|
target: "_blank",
|
|
@@ -1812,17 +2266,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1812
2266
|
document.head.appendChild(tag);
|
|
1813
2267
|
}
|
|
1814
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",
|
|
1815
2273
|
"dropdownPanel": "B_Gxsq_dropdownPanel",
|
|
2274
|
+
"dropdownItem": "B_Gxsq_dropdownItem",
|
|
1816
2275
|
"dropdownCountActive": "B_Gxsq_dropdownCountActive",
|
|
1817
|
-
"dropdownCount": "B_Gxsq_dropdownCount",
|
|
1818
|
-
"dropdown": "B_Gxsq_dropdown",
|
|
1819
2276
|
"dropdownArrowOpen": "B_Gxsq_dropdownArrowOpen",
|
|
1820
|
-
"dropdownLabel": "B_Gxsq_dropdownLabel",
|
|
1821
2277
|
"dropdownItemActive": "B_Gxsq_dropdownItemActive",
|
|
1822
|
-
"
|
|
1823
|
-
"
|
|
1824
|
-
"dropdownArrow": "B_Gxsq_dropdownArrow",
|
|
1825
|
-
"dropdownItemLabel": "B_Gxsq_dropdownItemLabel"
|
|
2278
|
+
"dropdownLabel": "B_Gxsq_dropdownLabel",
|
|
2279
|
+
"dropdown": "B_Gxsq_dropdown"
|
|
1826
2280
|
};
|
|
1827
2281
|
//#endregion
|
|
1828
2282
|
//#region src/client/components/Dropdown.tsx
|
|
@@ -1927,7 +2381,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1927
2381
|
}
|
|
1928
2382
|
//#endregion
|
|
1929
2383
|
//#region \0dsh-css:src/client/styles/List.module.css.mjs
|
|
1930
|
-
const css$1 = "._3XaZHa_body{flex-direction:column;flex:1;min-height:0;display:flex}._3XaZHa_list{flex-direction:column;flex:1;gap:6px;min-height:0;padding:2px 4px 4px 2px;display:flex;overflow-y:auto}._3XaZHa_card{border:1px solid var(--hub-border-2);background:var(--hub-bg-1);border-radius:8px;justify-content:space-between;align-items:stretch;gap:12px;padding:9px 12px;transition:border-color .12s,background .12s;display:flex}._3XaZHa_card:hover{border-color:var(--hub-brand);background:var(--hub-bg-2)}._3XaZHa_cardMain{flex-direction:column;gap:4px;min-width:0;display:flex}._3XaZHa_cardHead{align-items:center;gap:6px;min-width:0;display:flex}._3XaZHa_cardTitle{white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:600;line-height:18px;overflow:hidden}._3XaZHa_categoryBadge,._3XaZHa_verified,._3XaZHa_versionBadge,._3XaZHa_updateBadge{border:1px solid #0000;border-radius:4px;flex-shrink:0;padding:0 6px;font-size:10px;line-height:16px}._3XaZHa_categoryBadge{color:var(--hub-brand);border-color:var(--hub-border-ghost)}._3XaZHa_verified{color:var(--hub-success);border-color:var(--hub-success-border)}._3XaZHa_versionBadge{color:var(--hub-text-secondary);border-color:var(--hub-border-input)}._3XaZHa_updateBadge{color:var(--hub-warn);border-color:var(--hub-warn-border);background:var(--hub-warn-tint)}._3XaZHa_desc{color:var(--hub-text-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:0;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}._3XaZHa_topics{flex-wrap:wrap;align-items:center;gap:4px;min-width:0;display:flex}._3XaZHa_topic{color:var(--hub-text-tertiary);background:var(--hub-bg-3);white-space:nowrap;border-radius:4px;flex-shrink:0;padding:0 6px;font-size:10px;line-height:16px}._3XaZHa_cardSide{flex-direction:column;flex-shrink:0;justify-content:space-between;align-items:flex-end;gap:6px;display:flex}._3XaZHa_stats{flex-direction:column;align-items:flex-end;gap:1px;display:flex}._3XaZHa_star{color:var(--hub-warn);white-space:nowrap;font-size:11px;line-height:16px}._3XaZHa_fork{color:var(--hub-text-tertiary);white-space:nowrap;font-size:11px;line-height:16px}._3XaZHa_date{color:var(--hub-text-tertiary);white-space:nowrap;font-size:10px;line-height:14px}._3XaZHa_installBtn,._3XaZHa_installBtnCopied,._3XaZHa_installBtnInstalled,._3XaZHa_installBtnUpdate,._3XaZHa_uninstallBtn,._3XaZHa_detailBtn{cursor:pointer;border-radius:6px;padding:2px 10px;font-size:11px;line-height:18px;transition:color .12s,border-color .12s,background .12s}._3XaZHa_installBtnInstalled{color:var(--hub-success);background:var(--hub-success-tint);cursor:default;-webkit-user-select:none;user-select:none;border:none}._3XaZHa_installBtnUpdate{color:#fff;background:var(--hub-warn);-webkit-user-select:none;user-select:none;border:none;font-weight:500}._3XaZHa_installBtnUpdate:hover{background:var(--hub-warn-strong)}._3XaZHa_uninstallBtn{color:var(--hub-danger);-webkit-user-select:none;user-select:none;
|
|
2384
|
+
const css$1 = "._3XaZHa_body{flex-direction:column;flex:1;min-height:0;display:flex}._3XaZHa_list{flex-direction:column;flex:1;gap:6px;min-height:0;padding:2px 4px 4px 2px;display:flex;overflow-y:auto}._3XaZHa_card{border:1px solid var(--hub-border-2);background:var(--hub-bg-1);border-radius:8px;justify-content:space-between;align-items:stretch;gap:12px;padding:9px 12px;transition:border-color .12s,background .12s;display:flex}._3XaZHa_card:hover{border-color:var(--hub-brand);background:var(--hub-bg-2)}._3XaZHa_cardMain{flex-direction:column;gap:4px;min-width:0;display:flex}._3XaZHa_cardHead{align-items:center;gap:6px;min-width:0;display:flex}._3XaZHa_cardTitle{white-space:nowrap;text-overflow:ellipsis;font-size:13px;font-weight:600;line-height:18px;overflow:hidden}._3XaZHa_categoryBadge,._3XaZHa_verified,._3XaZHa_versionBadge,._3XaZHa_updateBadge{border:1px solid #0000;border-radius:4px;flex-shrink:0;padding:0 6px;font-size:10px;line-height:16px}._3XaZHa_categoryBadge{color:var(--hub-brand);border-color:var(--hub-border-ghost)}._3XaZHa_verified{color:var(--hub-success);border-color:var(--hub-success-border)}._3XaZHa_versionBadge{color:var(--hub-text-secondary);border-color:var(--hub-border-input)}._3XaZHa_updateBadge{color:var(--hub-warn);border-color:var(--hub-warn-border);background:var(--hub-warn-tint)}._3XaZHa_desc{color:var(--hub-text-secondary);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:0;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}._3XaZHa_topics{flex-wrap:wrap;align-items:center;gap:4px;min-width:0;display:flex}._3XaZHa_topic{color:var(--hub-text-tertiary);background:var(--hub-bg-3);white-space:nowrap;border-radius:4px;flex-shrink:0;padding:0 6px;font-size:10px;line-height:16px}._3XaZHa_cardSide{flex-direction:column;flex-shrink:0;justify-content:space-between;align-items:flex-end;gap:6px;display:flex}._3XaZHa_stats{flex-direction:column;align-items:flex-end;gap:1px;display:flex}._3XaZHa_star{color:var(--hub-warn);white-space:nowrap;font-size:11px;line-height:16px}._3XaZHa_fork{color:var(--hub-text-tertiary);white-space:nowrap;font-size:11px;line-height:16px}._3XaZHa_date{color:var(--hub-text-tertiary);white-space:nowrap;font-size:10px;line-height:14px}._3XaZHa_installBtn,._3XaZHa_installBtnCopied,._3XaZHa_installBtnInstalled,._3XaZHa_installBtnUpdate,._3XaZHa_uninstallBtn,._3XaZHa_detailBtn{cursor:pointer;border-radius:6px;padding:2px 10px;font-size:11px;line-height:18px;transition:color .12s,border-color .12s,background .12s}._3XaZHa_installBtnInstalled{color:var(--hub-success);background:var(--hub-success-tint);cursor:default;-webkit-user-select:none;user-select:none;border:none}._3XaZHa_installBtnUpdate{color:#fff;background:var(--hub-warn);-webkit-user-select:none;user-select:none;border:none;font-weight:500}._3XaZHa_installBtnUpdate:hover{background:var(--hub-warn-strong)}._3XaZHa_uninstallBtn{color:var(--hub-danger);background:var(--hub-danger-tint);-webkit-user-select:none;user-select:none;border:none}._3XaZHa_uninstallBtn:hover{color:#fff;background:var(--hub-danger-hover)}._3XaZHa_installBtn{color:var(--hub-text-on-fill);background:var(--hub-btn-fill);-webkit-user-select:none;user-select:none;border:none;font-weight:500}._3XaZHa_installBtn:hover{background:var(--hub-btn-hover)}._3XaZHa_detailBtn{color:var(--hub-text-secondary);-webkit-user-select:none;user-select:none;background:0 0;border:none;align-items:center;text-decoration:none;display:inline-flex}._3XaZHa_detailBtn:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}._3XaZHa_actions{align-items:center;gap:6px;display:flex}._3XaZHa_installBtnCopied{color:var(--hub-success);background:var(--hub-success-tint);-webkit-user-select:none;user-select:none;border:none}._3XaZHa_state{text-align:center;min-height:160px;color:var(--hub-text-tertiary);flex-direction:column;flex:1;justify-content:center;align-items:center;gap:8px;padding:24px;font-size:12px;line-height:18px;display:flex}._3XaZHa_stateTitle{color:var(--hub-text-primary);font-size:13px;font-weight:600}._3XaZHa_stateDesc{max-width:420px}._3XaZHa_retryBtn{color:var(--hub-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;border-radius:6px;margin-top:4px;padding:4px 12px;font-size:12px;line-height:18px}._3XaZHa_retryBtn:hover{color:var(--hub-text-primary);background:var(--hub-bg-hover)}._3XaZHa_footer{border-top:1px solid var(--hub-border-1);flex-shrink:0;justify-content:flex-end;align-items:center;gap:8px;padding:6px 4px 0;display:flex}._3XaZHa_footLink{color:var(--hub-brand);white-space:nowrap;-webkit-user-select:none;user-select:none;font-size:11px;line-height:16px;text-decoration:none}._3XaZHa_footLink:hover{text-decoration:underline}";
|
|
1931
2385
|
const tagId$1 = "dsh-plugin/List.module.css";
|
|
1932
2386
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1933
2387
|
const tag = document.createElement("style");
|
|
@@ -1937,36 +2391,36 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1937
2391
|
document.head.appendChild(tag);
|
|
1938
2392
|
}
|
|
1939
2393
|
var List_module_css_default = {
|
|
1940
|
-
"
|
|
1941
|
-
"
|
|
2394
|
+
"star": "_3XaZHa_star",
|
|
2395
|
+
"cardTitle": "_3XaZHa_cardTitle",
|
|
1942
2396
|
"actions": "_3XaZHa_actions",
|
|
1943
|
-
"
|
|
1944
|
-
"installBtnInstalled": "_3XaZHa_installBtnInstalled",
|
|
1945
|
-
"stateDesc": "_3XaZHa_stateDesc",
|
|
2397
|
+
"stateTitle": "_3XaZHa_stateTitle",
|
|
1946
2398
|
"body": "_3XaZHa_body",
|
|
1947
|
-
"verified": "_3XaZHa_verified",
|
|
1948
|
-
"topics": "_3XaZHa_topics",
|
|
1949
|
-
"desc": "_3XaZHa_desc",
|
|
1950
2399
|
"installBtn": "_3XaZHa_installBtn",
|
|
2400
|
+
"desc": "_3XaZHa_desc",
|
|
2401
|
+
"footer": "_3XaZHa_footer",
|
|
2402
|
+
"topic": "_3XaZHa_topic",
|
|
2403
|
+
"installBtnCopied": "_3XaZHa_installBtnCopied",
|
|
2404
|
+
"verified": "_3XaZHa_verified",
|
|
2405
|
+
"versionBadge": "_3XaZHa_versionBadge",
|
|
2406
|
+
"installBtnInstalled": "_3XaZHa_installBtnInstalled",
|
|
2407
|
+
"stateDesc": "_3XaZHa_stateDesc",
|
|
2408
|
+
"state": "_3XaZHa_state",
|
|
2409
|
+
"stats": "_3XaZHa_stats",
|
|
2410
|
+
"categoryBadge": "_3XaZHa_categoryBadge",
|
|
2411
|
+
"updateBadge": "_3XaZHa_updateBadge",
|
|
2412
|
+
"footLink": "_3XaZHa_footLink",
|
|
2413
|
+
"retryBtn": "_3XaZHa_retryBtn",
|
|
1951
2414
|
"uninstallBtn": "_3XaZHa_uninstallBtn",
|
|
1952
2415
|
"detailBtn": "_3XaZHa_detailBtn",
|
|
2416
|
+
"date": "_3XaZHa_date",
|
|
1953
2417
|
"cardMain": "_3XaZHa_cardMain",
|
|
1954
|
-
"
|
|
1955
|
-
"installBtnCopied": "_3XaZHa_installBtnCopied",
|
|
1956
|
-
"stateTitle": "_3XaZHa_stateTitle",
|
|
2418
|
+
"topics": "_3XaZHa_topics",
|
|
1957
2419
|
"list": "_3XaZHa_list",
|
|
1958
|
-
"footLink": "_3XaZHa_footLink",
|
|
1959
|
-
"versionBadge": "_3XaZHa_versionBadge",
|
|
1960
|
-
"installBtnUpdate": "_3XaZHa_installBtnUpdate",
|
|
1961
|
-
"cardHead": "_3XaZHa_cardHead",
|
|
1962
|
-
"star": "_3XaZHa_star",
|
|
1963
2420
|
"fork": "_3XaZHa_fork",
|
|
2421
|
+
"cardHead": "_3XaZHa_cardHead",
|
|
2422
|
+
"installBtnUpdate": "_3XaZHa_installBtnUpdate",
|
|
1964
2423
|
"cardSide": "_3XaZHa_cardSide",
|
|
1965
|
-
"cardTitle": "_3XaZHa_cardTitle",
|
|
1966
|
-
"date": "_3XaZHa_date",
|
|
1967
|
-
"retryBtn": "_3XaZHa_retryBtn",
|
|
1968
|
-
"topic": "_3XaZHa_topic",
|
|
1969
|
-
"categoryBadge": "_3XaZHa_categoryBadge",
|
|
1970
2424
|
"card": "_3XaZHa_card"
|
|
1971
2425
|
};
|
|
1972
2426
|
//#endregion
|
|
@@ -2101,14 +2555,22 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2101
2555
|
const [confirmPlugin, setConfirmPlugin] = (0, react.useState)(null);
|
|
2102
2556
|
/** 弹窗动作是否为「更新」:已安装插件点「更新」→ 走同一条 add 命令原位覆盖重装,文案区分安装/更新 */
|
|
2103
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);
|
|
2104
2562
|
/** 卸载确认弹窗:记录待卸载的插件 */
|
|
2105
2563
|
const [uninstallPlugin, setUninstallPlugin] = (0, react.useState)(null);
|
|
2106
2564
|
/** 安装/卸载完成后的结果视图:停留弹窗内,点「完成」关闭 */
|
|
2107
2565
|
const [installDone, setInstallDone] = (0, react.useState)(false);
|
|
2108
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);
|
|
2109
2571
|
/** 结果视图「立即重启」:请求宿主重启后进入等待,服务回来后整页刷新 */
|
|
2110
2572
|
const [restarting, setRestarting] = (0, react.useState)(false);
|
|
2111
|
-
/** 操作失败完整信息 + 所属插件仓库 +
|
|
2573
|
+
/** 操作失败完整信息 + 所属插件仓库 + 失败类型(决定弹窗标题「安装失败/卸载失败」)+ 实际执行的安装命令 + 尝试过的安装方式(issue 预填用) */
|
|
2112
2574
|
const [errorMsg, setErrorMsg] = (0, react.useState)(null);
|
|
2113
2575
|
/** 安装/卸载任务通知记录:localStorage 持久化,成败即落盘,即使错过弹窗也能回来查看 */
|
|
2114
2576
|
const [notifications, setNotifications] = (0, react.useState)(() => loadNotifications());
|
|
@@ -2127,7 +2589,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2127
2589
|
const queue = useTaskQueue({
|
|
2128
2590
|
t,
|
|
2129
2591
|
refreshInstalled: catalog.refreshInstalled,
|
|
2130
|
-
onInstallDone: (viaModal, repo) => {
|
|
2592
|
+
onInstallDone: (viaModal, repo, needsRestart) => {
|
|
2593
|
+
setInstallNeedsRestart(needsRestart);
|
|
2131
2594
|
if (viaModal) setInstallDone(true);
|
|
2132
2595
|
else setToast({
|
|
2133
2596
|
id: Date.now(),
|
|
@@ -2138,7 +2601,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2138
2601
|
repo: repo ?? ""
|
|
2139
2602
|
}));
|
|
2140
2603
|
},
|
|
2141
|
-
onUninstallDone: (viaModal, repo) => {
|
|
2604
|
+
onUninstallDone: (viaModal, repo, needsRestart) => {
|
|
2605
|
+
setUninstallNeedsRestart(needsRestart);
|
|
2142
2606
|
if (viaModal) setUninstallDone(true);
|
|
2143
2607
|
else setToast({
|
|
2144
2608
|
id: Date.now(),
|
|
@@ -2149,16 +2613,20 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2149
2613
|
repo: repo ?? ""
|
|
2150
2614
|
}));
|
|
2151
2615
|
},
|
|
2152
|
-
onError: (message, repo, kind) => {
|
|
2616
|
+
onError: (message, repo, kind, command, attempts) => {
|
|
2153
2617
|
setErrorMsg({
|
|
2154
2618
|
message,
|
|
2155
2619
|
repo,
|
|
2156
|
-
kind
|
|
2620
|
+
kind,
|
|
2621
|
+
command,
|
|
2622
|
+
attempts
|
|
2157
2623
|
});
|
|
2158
2624
|
setNotifications(addFailure({
|
|
2159
2625
|
kind,
|
|
2160
2626
|
repo: repo ?? "",
|
|
2161
|
-
message
|
|
2627
|
+
message,
|
|
2628
|
+
command,
|
|
2629
|
+
attempts
|
|
2162
2630
|
}));
|
|
2163
2631
|
},
|
|
2164
2632
|
installPlugin: confirmPlugin,
|
|
@@ -2173,12 +2641,14 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2173
2641
|
}
|
|
2174
2642
|
});
|
|
2175
2643
|
(0, react.useEffect)(() => {
|
|
2176
|
-
if (!confirmPlugin && !uninstallPlugin && !showNotifications) return;
|
|
2644
|
+
if (!confirmPlugin && !uninstallPlugin && !showNotifications && !showHubUpdate && !showAbout) return;
|
|
2177
2645
|
const onKey = (e) => {
|
|
2178
2646
|
if (e.key === "Escape") {
|
|
2179
2647
|
setConfirmPlugin(null);
|
|
2180
2648
|
setUninstallPlugin(null);
|
|
2181
2649
|
setUninstallDone(false);
|
|
2650
|
+
setShowHubUpdate(false);
|
|
2651
|
+
setShowAbout(false);
|
|
2182
2652
|
setShowNotifications(false);
|
|
2183
2653
|
}
|
|
2184
2654
|
};
|
|
@@ -2187,7 +2657,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2187
2657
|
}, [
|
|
2188
2658
|
confirmPlugin,
|
|
2189
2659
|
uninstallPlugin,
|
|
2190
|
-
showNotifications
|
|
2660
|
+
showNotifications,
|
|
2661
|
+
showHubUpdate,
|
|
2662
|
+
showAbout
|
|
2191
2663
|
]);
|
|
2192
2664
|
(0, react.useEffect)(() => {
|
|
2193
2665
|
if (!toast) return;
|
|
@@ -2216,10 +2688,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2216
2688
|
return ok;
|
|
2217
2689
|
}
|
|
2218
2690
|
};
|
|
2219
|
-
/**
|
|
2691
|
+
/** 弹窗动作一:复制安装命令到剪贴板,引导去终端粘贴执行(npm 通道显示包名命令)。 */
|
|
2220
2692
|
const copyCommand = async (p) => {
|
|
2221
2693
|
const repo = p.source?.repo ?? "";
|
|
2222
|
-
if (await doCopy(
|
|
2694
|
+
if (await doCopy(installCommandOf(p))) {
|
|
2223
2695
|
setCopied(repo);
|
|
2224
2696
|
setToast({
|
|
2225
2697
|
id: Date.now(),
|
|
@@ -2272,12 +2744,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2272
2744
|
const statsTotal = catalog.stats?.total ?? total;
|
|
2273
2745
|
const statsVerified = catalog.stats?.verified ?? 0;
|
|
2274
2746
|
const count = catalog.visible.length;
|
|
2747
|
+
const hubEntry = catalog.plugins?.find((p) => p.source?.repo === "dshplugin/dsh-plugin-hub") ?? null;
|
|
2275
2748
|
return (0, react.createElement)("div", { className: Header_module_css_default.root }, (0, react.createElement)(CatalogHeader, {
|
|
2276
2749
|
t,
|
|
2277
2750
|
langPath,
|
|
2278
2751
|
statsTotal,
|
|
2279
2752
|
statsVerified,
|
|
2280
|
-
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)
|
|
2281
2757
|
}), (0, react.createElement)(CategoryTabs, {
|
|
2282
2758
|
category: catalog.category,
|
|
2283
2759
|
setCategory: catalog.setCategory,
|
|
@@ -2323,6 +2799,26 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2323
2799
|
queue.clearModalTask();
|
|
2324
2800
|
setUninstallPlugin(p);
|
|
2325
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)
|
|
2326
2822
|
}), confirmPlugin && (0, react.createElement)(InstallModal, {
|
|
2327
2823
|
plugin: confirmPlugin,
|
|
2328
2824
|
done: installDone,
|
|
@@ -2331,7 +2827,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2331
2827
|
langPath,
|
|
2332
2828
|
restarting,
|
|
2333
2829
|
update: confirmIsUpdate,
|
|
2830
|
+
cliOnly: confirmPlugin.install?.webInstallable === false,
|
|
2334
2831
|
submitting: queue.submitting,
|
|
2832
|
+
needsRestart: installNeedsRestart,
|
|
2335
2833
|
onClose: () => setConfirmPlugin(null),
|
|
2336
2834
|
onCopy: () => copyCommand(confirmPlugin),
|
|
2337
2835
|
onInstall: () => queue.installNow(confirmPlugin, confirmIsUpdate ? { update: true } : void 0),
|
|
@@ -2346,6 +2844,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2346
2844
|
langPath,
|
|
2347
2845
|
restarting,
|
|
2348
2846
|
submitting: queue.submitting,
|
|
2847
|
+
needsRestart: uninstallNeedsRestart,
|
|
2349
2848
|
onClose: () => {
|
|
2350
2849
|
setUninstallDone(false);
|
|
2351
2850
|
setUninstallPlugin(null);
|
|
@@ -2363,6 +2862,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2363
2862
|
message: errorMsg.message,
|
|
2364
2863
|
repo: errorMsg.repo,
|
|
2365
2864
|
kind: errorMsg.kind,
|
|
2865
|
+
command: errorMsg.command,
|
|
2866
|
+
attempts: errorMsg.attempts,
|
|
2366
2867
|
t,
|
|
2367
2868
|
env,
|
|
2368
2869
|
onCopy: (text) => {
|
|
@@ -2388,6 +2889,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2388
2889
|
});
|
|
2389
2890
|
},
|
|
2390
2891
|
onClear: () => setNotifications(clearNotifications()),
|
|
2892
|
+
onRemove: (id) => setNotifications(removeNotification(id)),
|
|
2391
2893
|
cancelTask: queue.cancelTask,
|
|
2392
2894
|
restarting,
|
|
2393
2895
|
onRestart: () => {
|
|
@@ -2397,7 +2899,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2397
2899
|
}
|
|
2398
2900
|
//#endregion
|
|
2399
2901
|
//#region \0dsh-css:src/client/styles/tokens.module.css.mjs
|
|
2400
|
-
const css = ":root,body[data-ds-dark-theme]{--hub-text-primary:var(--dsw-alias-label-primary,#1f2328);--hub-text-secondary:var(--dsw-alias-label-secondary,#6b7280);--hub-text-tertiary:var(--dsw-alias-label-tertiary,#8b93a1);--hub-text-disabled:var(--dsw-alias-label-disabled,#aab1bd);--hub-text-on-fill:var(--dsw-alias-label-primary-foreground,#fff);--hub-bg-1:var(--dsw-alias-bg-layer-1,#fff);--hub-bg-2:var(--dsw-alias-bg-layer-2,#80808014);--hub-bg-3:#8080801a;--hub-bg-btn:#8080801f;--hub-bg-hover:var(--dsw-alias-interactive-bg-hover,#80808029);--hub-bg-on-fill:#80808038;--hub-border-1:var(--dsw-alias-border-l1,#eceef1);--hub-border-2:var(--dsw-alias-border-l2,#e5e7eb);--hub-border-ghost:var(--dsw-alias-button-ghost-active-border,#4f6ef740);--hub-border-input:var(--dsw-alias-input-border,#6b728040);--hub-brand:var(--dsw-alias-state-business-primary,#4f6ef7);--hub-brand-hover:#3b5bdb;--hub-brand-tint:#4f6ef70f;--hub-brand-tint-strong:#4f6ef71f;--hub-brand-border:#4f6ef759;--hub-brand-border-soft:#4f6ef738;--hub-purple-1:#4f46e5;--hub-purple-2:#7c3aed;--hub-purple-border:#8b5cf68c;--hub-purple-tint:#4f46e514;--hub-purple-shadow:#4f46e547;--hub-purple-shadow-strong:#7c3aed6b;--hub-btn-fill:var(--dsw-alias-button-primary-fill,#1f2328);--hub-btn-hover:var(--dsw-alias-button-primary-hover,#43454a);--hub-success
|
|
2902
|
+
const css = ":root,body[data-ds-dark-theme]{--hub-text-primary:var(--dsw-alias-label-primary,#1f2328);--hub-text-secondary:var(--dsw-alias-label-secondary,#6b7280);--hub-text-tertiary:var(--dsw-alias-label-tertiary,#8b93a1);--hub-text-disabled:var(--dsw-alias-label-disabled,#aab1bd);--hub-text-on-fill:var(--dsw-alias-label-primary-foreground,#fff);--hub-bg-1:var(--dsw-alias-bg-layer-1,#fff);--hub-bg-2:var(--dsw-alias-bg-layer-2,#80808014);--hub-bg-3:#8080801a;--hub-bg-btn:#8080801f;--hub-bg-hover:var(--dsw-alias-interactive-bg-hover,#80808029);--hub-bg-on-fill:#80808038;--hub-border-1:var(--dsw-alias-border-l1,#eceef1);--hub-border-2:var(--dsw-alias-border-l2,#e5e7eb);--hub-border-ghost:var(--dsw-alias-button-ghost-active-border,#4f6ef740);--hub-border-input:var(--dsw-alias-input-border,#6b728040);--hub-brand:var(--dsw-alias-state-business-primary,#4f6ef7);--hub-brand-hover:#3b5bdb;--hub-brand-tint:#4f6ef70f;--hub-brand-tint-strong:#4f6ef71f;--hub-brand-border:#4f6ef759;--hub-brand-border-soft:#4f6ef738;--hub-purple-1:#4f46e5;--hub-purple-2:#7c3aed;--hub-purple-border:#8b5cf68c;--hub-purple-tint:#4f46e514;--hub-purple-shadow:#4f46e547;--hub-purple-shadow-strong:#7c3aed6b;--hub-btn-fill:var(--dsw-alias-button-primary-fill,#1f2328);--hub-btn-hover:var(--dsw-alias-button-primary-hover,#43454a);--hub-success:#16a34a;--hub-success-tint:#16a34a1f;--hub-success-border:#16a34a4d;--hub-warn:var(--dsw-alias-state-warn-primary,#b8860b);--hub-warn-tint:#b8860b14;--hub-warn-border:#b8860b59;--hub-warn-strong:#b8860bd9;--hub-warning:var(--dsw-alias-state-warning-primary,#b45309);--hub-warning-tint:#b4530914;--hub-warning-border:#b453094d;--hub-danger:var(--dsw-alias-state-danger-primary,#d1242f);--hub-danger-hover:var(--dsw-alias-state-danger-hover,#b91c1c);--hub-danger-strong:#b0202a;--hub-danger-text:#e5484d;--hub-danger-tint:#e5484d14;--hub-danger-tint-weak:#e5484d0d;--hub-danger-border:#e5484d59;--hub-danger-border-soft:#e5484d47;--hub-danger-soft:#d1242f14}body[data-ds-dark-theme]{--hub-bg-btn:#ffffff1f;--hub-success:#22c55e;--hub-success-tint:#22c55e29;--hub-success-border:#22c55e59}";
|
|
2401
2903
|
const tagId = "dsh-plugin/tokens.module.css";
|
|
2402
2904
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2403
2905
|
const tag = document.createElement("style");
|