@androidsup/dsh-plugin-updates 0.0.0-stage → 0.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/lib/client.js ADDED
@@ -0,0 +1,538 @@
1
+ window.__ModuleLoader__.load({ id: "@androidsup/dsh-plugin-updates", factory: (require) => { var module = { exports: {} };
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name3 in all)
8
+ __defProp(target, name3, { get: all[name3], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/client.jsx
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ UpdateReminder: () => UpdateReminder,
24
+ UpdatesIntro: () => UpdatesIntro,
25
+ UpdatesPage: () => UpdatesPage,
26
+ apply: () => apply,
27
+ inject: () => inject,
28
+ name: () => name2
29
+ });
30
+ module.exports = __toCommonJS(client_exports);
31
+ var import_react3 = require("react");
32
+
33
+ // package.json
34
+ var name = "@androidsup/dsh-plugin-updates";
35
+ var version = "0.1.1";
36
+ var repository = {
37
+ type: "git",
38
+ url: "https://github.com/AndroidSix/dsh-plugin-updates.git"
39
+ };
40
+
41
+ // src/panel.jsx
42
+ var import_react = require("react");
43
+ var import_jsx_runtime = require("react/jsx-runtime");
44
+ var when = (n) => n ? new Date(n).toLocaleString("zh-CN", { hour12: false }) : "\u5C1A\u672A\u83B7\u53D6";
45
+ function Modal({ title, close, children, busy }) {
46
+ const ref = (0, import_react.useRef)(null);
47
+ (0, import_react.useEffect)(() => {
48
+ const dialog = ref.current;
49
+ dialog.showModal();
50
+ return () => dialog.close();
51
+ }, []);
52
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dialog", { ref, "aria-label": title, onCancel: (e) => {
53
+ e.preventDefault();
54
+ if (!busy) close();
55
+ }, children: [
56
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-head bar", children: [
57
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: title }),
58
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", disabled: busy, onClick: close, children: "\u5173\u95ED" })
59
+ ] }),
60
+ children
61
+ ] });
62
+ }
63
+ var updateNames = { unchecked: "\u5F85\u68C0\u67E5", available: "\u53EF\u66F4\u65B0", current: "\u5DF2\u540C\u6B65", pinned: "\u56FA\u5B9A\u63D0\u4EA4", unsupported: "\u672C\u5730\u6765\u6E90", failed: "\u68C0\u67E5 / \u5B89\u88C5\u5931\u8D25", installed: "\u5DF2\u5B89\u88C5" };
64
+ function PluginUpdatesPanel({ data, busy, act }) {
65
+ const [selected, setSelected] = (0, import_react.useState)([]), [plan, setPlan] = (0, import_react.useState)(null), [registry, setRegistry] = (0, import_react.useState)(""), [filter, setFilter] = (0, import_react.useState)("all"), [pluginSearch, setPluginSearch] = (0, import_react.useState)("");
66
+ const [diagnostic, setDiagnostic] = (0, import_react.useState)(null), [copied, setCopied] = (0, import_react.useState)(false), [reminderNotice, setReminderNotice] = (0, import_react.useState)(null);
67
+ const running = data?.job?.state === "running", blocked = busy || running;
68
+ const rows = (data?.rows ?? []).filter((r) => r.source.kind !== "builtin"), available = rows.filter((r) => r.status === "available" || r.status === "failed" && r.target);
69
+ (0, import_react.useEffect)(() => {
70
+ if (data?.available && !running) void act({ action: !data.checkedAt || Date.now() - data.checkedAt > 864e5 ? "plugins.check" : "plugins.list" });
71
+ }, []);
72
+ const notIgnored = available.filter((r) => !r.ignored), ignored = available.filter((r) => r.ignored);
73
+ const chosen = available.filter((r) => selected.includes(r.name));
74
+ const freshVersions = plan ? [...new Set(plan.rows.filter((r) => r.source.kind === "npm" && r.latestVersion).map((r) => `${r.source.package}@${r.latestVersion}`))] : [];
75
+ const visibleRows = rows.filter((r) => r.name.toLowerCase().includes(pluginSearch.toLowerCase()) && (filter === "all" || (filter === "updates" ? notIgnored.includes(r) : filter === "ignored" ? ignored.includes(r) : r.source.kind === filter)));
76
+ async function toggleReminder(row) {
77
+ setReminderNotice(null);
78
+ if (await act({ action: row.ignored ? "plugins.unignore" : "plugins.ignore", keys: [row.targetKey] })) {
79
+ setReminderNotice({ name: row.name, targetKey: row.targetKey, ignored: !row.ignored, message: `${row.name}\uFF1A${row.ignored ? "\u5DF2\u6062\u590D\u6B64\u7248\u672C\u63D0\u9192" : "\u5DF2\u5FFD\u7565\u6B64\u7248\u672C\u63D0\u9192\uFF1B\u65B0\u7248\u672C\u4ECD\u4F1A\u63D0\u9192\uFF0C\u53EF\u968F\u65F6\u6062\u590D\u6216\u624B\u52A8\u66F4\u65B0"}` });
80
+ if (!row.ignored) setSelected((names) => names.filter((name3) => name3 !== row.name));
81
+ }
82
+ }
83
+ async function submitPlan() {
84
+ if (await act({ action: "plugins.update", names: plan.rows.map((r) => r.name), registry: registry || void 0, allowFreshVersions: plan.allowFresh === true ? freshVersions : [] })) {
85
+ setPlan(null);
86
+ setSelected([]);
87
+ }
88
+ }
89
+ if (!data?.available) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5F53\u524D DSH \u672A\u63D0\u4F9B\u63D2\u4EF6\u7BA1\u7406\u63A5\u53E3" }),
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "\u8BF7\u5347\u7EA7 DeepSeek Harness \u540E\u91CD\u8BD5\u3002\u672C\u9875\u7BA1\u7406\u5F53\u524D DSH \u914D\u7F6E\u4E2D\u7531\u7528\u6237\u5B89\u88C5\u7684\u63D2\u4EF6\u3002" })
92
+ ] });
93
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
94
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
96
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
97
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u5DF2\u5B89\u88C5\u63D2\u4EF6" }),
98
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
99
+ rows.length,
100
+ " \u4E2A\u7528\u6237\u5B89\u88C5\u63D2\u4EF6 \xB7 ",
101
+ available.length,
102
+ " \u4E2A\u53EF\u66F4\u65B0 \xB7 ",
103
+ ignored.length,
104
+ " \u4E2A\u5DF2\u5FFD\u7565\u63D0\u9192"
105
+ ] })
106
+ ] }),
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: blocked, onClick: () => {
108
+ void act({ action: "plugins.check" });
109
+ }, children: "\u68C0\u67E5\u5168\u90E8\u66F4\u65B0" })
110
+ ] }),
111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
112
+ "\u4E0A\u6B21\u68C0\u67E5 ",
113
+ when(data.checkedAt),
114
+ " \xB7 \u6BCF\u5929\u81EA\u52A8\u68C0\u67E5\u5E76\u63D0\u9192"
115
+ ] }),
116
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5FFD\u7565\u4EC5\u5C4F\u853D\u6307\u5B9A\u7248\u672C / \u63D0\u4EA4\u7684\u63D0\u9192\uFF0C\u91CD\u542F\u540E\u4FDD\u7559\uFF1B\u65B0\u7248\u672C\u4ECD\u63D0\u9192\u3002\u5DF2\u5FFD\u7565\u9879\u4E0D\u53C2\u4E0E\u5168\u9009\uFF0C\u4ECD\u53EF\u624B\u52A8\u66F4\u65B0\u6216\u6062\u590D\u63D0\u9192\u3002" }),
117
+ reminderNotice && rows.some((row) => row.name === reminderNotice.name && row.targetKey === reminderNotice.targetKey && row.ignored === reminderNotice.ignored) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: reminderNotice.message }),
118
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: "help", children: [
119
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: "\u5B89\u88C5\u6E90\u4E0E\u68C0\u67E5\u89C4\u5219" }),
120
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
121
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
122
+ "npm \u5B89\u88C5\u6E90",
123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: registry, disabled: blocked, onChange: (e) => setRegistry(e.target.value), children: [
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "DSH \u8BBE\u7F6E\uFF08\u542B\u56DE\u9000\u6765\u6E90\uFF09" }),
125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "https://registry.npmjs.org/", children: "npm \u5B98\u65B9" }),
126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "https://registry.npmmirror.com/", children: "npmmirror" })
127
+ ] })
128
+ ] }),
129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "npm \u6309\u7248\u672C / \u53D1\u5E03\u9891\u9053\u68C0\u67E5\uFF0CGitHub \u6309\u5206\u652F\u63D0\u4EA4\u68C0\u67E5\uFF1B\u4FDD\u7559\u542F\u7528\u72B6\u6001\uFF0C\u56FA\u5B9A Git \u63D0\u4EA4\u4FDD\u6301\u4E0D\u52A8\u3002" })
130
+ ] })
131
+ ] })
132
+ ] }),
133
+ data.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "error", role: "alert", children: data.error }),
134
+ data.job && !(data.job.kind === "check" && data.job.state === "done") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", "aria-live": "polite", children: [
135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: running ? data.job.kind === "check" ? "\u6B63\u5728\u68C0\u67E5\u66F4\u65B0\u2026" : "\u6B63\u5728\u5B89\u88C5\u63D2\u4EF6\u2026" : data.job.state === "cancelled" ? "\u64CD\u4F5C\u5DF2\u53D6\u6D88" : data.job.state === "failed" || data.job.results.some((r) => r.status === "failed") ? "\u6709\u63D2\u4EF6\u672A\u5B8C\u6210\u5B89\u88C5" : "\u64CD\u4F5C\u5DF2\u5B8C\u6210" }),
137
+ running && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
138
+ void act({ action: "plugins.cancel" });
139
+ }, children: "\u53D6\u6D88" })
140
+ ] }),
141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("progress", { max: Math.max(1, data.job.total), value: data.job.results.length, "aria-label": "\u63D2\u4EF6\u64CD\u4F5C\u8FDB\u5EA6" }),
142
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
143
+ data.job.results.length,
144
+ " / ",
145
+ data.job.total,
146
+ data.job.current ? ` \xB7 ${data.job.current}` : ""
147
+ ] }),
148
+ data.job.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "error", children: data.job.message }),
149
+ data.job.results.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "item", children: [
150
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: r.name }),
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: r.status === "failed" ? "error" : "notice", children: r.message || updateNames[r.status] || r.status }),
152
+ r.diagnostic && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => {
153
+ setCopied(false);
154
+ setDiagnostic(JSON.stringify({ plugin: r.name, targetVersion: r.expectedVersion, ...r.diagnostic }, null, 2));
155
+ }, children: "\u67E5\u770B\u8131\u654F\u8BCA\u65AD" }),
156
+ r.pendingBuilds?.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
157
+ "\u5F85\u6388\u6743\u811A\u672C\uFF1A",
158
+ r.pendingBuilds.join("\u3001"),
159
+ "\u3002\u8BF7\u5728 DSH \u539F\u63D2\u4EF6\u5B89\u88C5\u9875\u6388\u6743\u540E\u91CD\u8BD5\u3002"
160
+ ] })
161
+ ] }, r.name + i)),
162
+ data.job.results.some((r) => r.restartRequired) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u66F4\u65B0\u6587\u4EF6\u5DF2\u5B89\u88C5\u3002macOS \u4F7F\u7528 \u2318Q \u5B8C\u5168\u9000\u51FA DSH \u540E\u91CD\u5F00\uFF1BWindows \u9000\u51FA\u6258\u76D8\u5E94\u7528\u540E\u91CD\u5F00\uFF1B\u7F51\u9875\u7248\u91CD\u542F\u670D\u52A1\u3002\u5173\u95ED\u7A97\u53E3\u548C\u300C\u5237\u65B0\u9762\u677F\u300D\u4E0D\u4F1A\u91CD\u8F7D\u540E\u53F0\u3002" })
163
+ ] }),
164
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box table-shell", children: [
165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar section-pad", children: [
166
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
167
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !notIgnored.length, onClick: () => setSelected(notIgnored.map((r) => r.name)), children: "\u9009\u62E9\u5168\u90E8\u672A\u5FFD\u7565" }),
168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked || !selected.length, onClick: () => setSelected([]), children: "\u6E05\u7A7A\u9009\u62E9" })
169
+ ] }),
170
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { className: "primary", disabled: blocked || !chosen.length, onClick: () => setPlan({ kind: "update", rows: chosen }), children: [
171
+ "\u66F4\u65B0\u6240\u9009\uFF08",
172
+ chosen.length,
173
+ "\uFF09"
174
+ ] })
175
+ ] }),
176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row section-pad", children: [
177
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { flex: 1 }, children: [
178
+ "\u641C\u7D22\u5DF2\u5B89\u88C5\u63D2\u4EF6",
179
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { value: pluginSearch, onChange: (e) => setPluginSearch(e.target.value), placeholder: "\u6309\u63D2\u4EF6\u540D\u79F0\u7B5B\u9009" })
180
+ ] }),
181
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "filter", children: [
182
+ "\u663E\u793A\u8303\u56F4",
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { value: filter, onChange: (e) => setFilter(e.target.value), children: [
184
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "all", children: "\u5168\u90E8\u7528\u6237\u5B89\u88C5\u63D2\u4EF6" }),
185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "updates", children: "\u53EF\u66F4\u65B0 / \u91CD\u8BD5\uFF08\u672A\u5FFD\u7565\uFF09" }),
186
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "ignored", children: "\u5DF2\u5FFD\u7565\u63D0\u9192" }),
187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "npm", children: "npm \u6765\u6E90" }),
188
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "github", children: "GitHub \u6765\u6E90" })
189
+ ] })
190
+ ] })
191
+ ] }),
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "scroll", role: "region", "aria-label": "\u7528\u6237\u5B89\u88C5\u63D2\u4EF6\u5217\u8868", tabIndex: "0", children: [
193
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: "table", children: [
194
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
195
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u63D2\u4EF6 / \u9009\u62E9" }),
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u6765\u6E90\u4E0E\u7248\u672C" }),
197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: "\u72B6\u6001" }),
198
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", className: "cell-actions", children: "\u64CD\u4F5C" })
199
+ ] }) }),
200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: visibleRows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { className: selected.includes(r.name) ? "selected" : "", children: [
201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
202
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
203
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { "aria-label": `\u9009\u62E9\u66F4\u65B0 ${r.name}`, type: "checkbox", disabled: blocked || !available.includes(r), checked: selected.includes(r.name), onChange: (e) => setSelected(e.target.checked ? [...selected, r.name] : selected.filter((n) => n !== r.name)) }),
204
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { className: "mono", children: r.name })
205
+ ] }),
206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: r.enabled ? "\u542F\u7528" : "\u505C\u7528" })
207
+ ] }),
208
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
209
+ r.source.kind === "npm" ? `npm \xB7 ${r.version || "\u672A\u77E5"}${r.latestVersion ? " \u2192 " + r.latestVersion : ""}` : r.source.kind === "github" ? `GitHub \xB7 ${r.version || "\u672A\u77E5\u7248\u672C"}` : "\u672C\u5730\u6587\u4EF6 / \u5F00\u53D1\u94FE\u63A5",
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted mono", children: r.source.kind === "npm" ? `\u5B89\u88C5\u58F0\u660E ${r.source.source} \xB7 \u68C0\u67E5 ${r.source.tag}` : r.source.kind === "github" ? `${r.commit?.slice(0, 8) || "\u672A\u77E5\u63D0\u4EA4"}${r.latestCommit ? " \u2192 " + r.latestCommit.slice(0, 8) : ""}` : "" })
211
+ ] }),
212
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
213
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: r.status === "failed" ? "error" : r.status === "available" ? "good" : "muted", children: updateNames[r.status] }),
214
+ r.ignored && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: "muted", children: "\u5DF2\u5FFD\u7565\u6B64\u7248\u672C\u63D0\u9192" }),
215
+ r.message && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { className: r.status === "failed" ? "error" : "muted", children: r.message })
216
+ ] }),
217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: "cell-actions", children: available.includes(r) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack row-actions", children: [
218
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, onClick: () => setPlan({ kind: "update", rows: [r] }), children: "\u67E5\u770B\u5E76\u66F4\u65B0" }),
219
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, "aria-label": `${r.ignored ? "\u6062\u590D" : "\u5FFD\u7565"} ${r.name} \u6B64\u7248\u672C\u63D0\u9192`, onClick: () => {
220
+ void toggleReminder(r);
221
+ }, children: r.ignored ? "\u6062\u590D\u6B64\u7248\u672C\u63D0\u9192" : "\u5FFD\u7565\u6B64\u7248\u672C\u63D0\u9192" })
222
+ ] }) : "\u2014" })
223
+ ] }, r.name)) })
224
+ ] }),
225
+ !visibleRows.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "empty", children: running ? "\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u6E05\u5355\u2026" : rows.length ? "\u6CA1\u6709\u5339\u914D\u7684\u5DF2\u5B89\u88C5\u63D2\u4EF6\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002" : "\u5F53\u524D\u914D\u7F6E\u5C1A\u672A\u8BFB\u53D6\u63D2\u4EF6\uFF0C\u8BF7\u68C0\u67E5\u66F4\u65B0\u3002" })
226
+ ] })
227
+ ] }),
228
+ diagnostic && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modal, { title: "\u63D2\u4EF6\u5B89\u88C5\u8BCA\u65AD", close: () => setDiagnostic(null), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
229
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u4EE5\u4E0B\u4FE1\u606F\u53EA\u542B\u63D2\u4EF6\u540D\u3001\u7248\u672C\u3001\u7CFB\u7EDF\u548C\u9519\u8BEF\u5206\u7C7B\uFF0C\u53EF\u590D\u5236\u7528\u4E8E\u6392\u67E5\uFF1B\u672A\u5305\u542B\u539F\u59CB\u65E5\u5FD7\u3001\u7528\u6237\u540D\u8DEF\u5F84\u6216\u51ED\u8BC1\u3002\u82E5\u539F\u56E0\u672A\u77E5\uFF0C\u8BF7\u5728 DSH \u539F\u751F\u63D2\u4EF6\u9875\u83B7\u53D6\u5B89\u88C5\u65E5\u5FD7\u3002" }),
230
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", { "aria-label": "\u8131\u654F\u5B89\u88C5\u8BCA\u65AD", readOnly: true, rows: "9", value: diagnostic, onFocus: (e) => e.currentTarget.select() }),
231
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: async () => {
232
+ try {
233
+ await navigator.clipboard.writeText(diagnostic);
234
+ setCopied(true);
235
+ } catch {
236
+ setCopied(false);
237
+ }
238
+ }, children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u8BCA\u65AD" })
239
+ ] }) }),
240
+ plan && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Modal, { title: "\u786E\u8BA4\u66F4\u65B0\u63D2\u4EF6", close: () => setPlan(null), busy: blocked, children: [
241
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-body stack", children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "\u8FD9\u4E9B\u64CD\u4F5C\u4F5C\u7528\u4E8E\u5F53\u524D DSH \u914D\u7F6E\u7684\u6240\u6709\u4F1A\u8BDD\u3002\u5B89\u88C5\u540E\u662F\u5426\u9700\u8981\u91CD\u542F\uFF0C\u4F1A\u5728\u7ED3\u679C\u4E2D\u8BF4\u660E\u3002" }),
243
+ plan.rows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "steps", children: [
244
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: r.name }),
245
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mono", children: r.target }),
246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: r.source.kind === "npm" ? `${r.version || "\u672A\u77E5"} \u2192 ${r.latestVersion}` : `${r.commit?.slice(0, 8) || "\u672A\u77E5\u63D0\u4EA4"} \u2192 ${r.latestCommit?.slice(0, 8) || "\u672A\u77E5\u63D0\u4EA4"}` }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
248
+ "\u4FDD\u7559\u4E3A",
249
+ r.enabled ? "\u542F\u7528" : "\u505C\u7528",
250
+ "\uFF1B",
251
+ r.source.kind === "github" ? "\u7EE7\u7EED\u8DDF\u968F\u539F\u5206\u652F / \u6807\u7B7E\uFF0C\u5E76\u6838\u9A8C\u63D0\u4EA4" : "\u6309\u539F\u9891\u9053\u66F4\u65B0\uFF0C\u5E76\u6838\u9A8C\u6240\u793A npm \u7248\u672C",
252
+ "\u3002"
253
+ ] })
254
+ ] }, r.name)),
255
+ freshVersions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "steps stack", children: [
256
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "check", children: [
257
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", disabled: blocked, checked: plan.allowFresh === true, onChange: (e) => setPlan((p) => ({ ...p, allowFresh: e.target.checked })) }),
258
+ "\u5141\u8BB8\u672C\u6B21\u6307\u5B9A\u7248\u672C\u7ACB\u5373\u5B89\u88C5\uFF08\u4E0D\u7B49\u5F85 24 \u5C0F\u65F6\uFF09"
259
+ ] }),
260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
261
+ "\u786E\u8BA4\u66F4\u65B0\u540E\uFF0C\u4EC5\u4E3A\u4EE5\u4E0B\u7248\u672C\u4FDD\u5B58\u7B49\u5F85\u671F\u4F8B\u5916\uFF1A",
262
+ freshVersions.join("\u3001"),
263
+ "\u3002\u65B0\u5305\u7B49\u5F85\u671F\u7528\u4E8E\u964D\u4F4E\u4F9B\u5E94\u94FE\u98CE\u9669\uFF1B\u5176\u4ED6\u7248\u672C\u3001\u4F9D\u8D56\u548C\u811A\u672C\u6388\u6743\u4ECD\u9075\u5B88 DSH \u7B56\u7565\u3002\u9ED8\u8BA4\u9075\u5B88\u7B49\u5F85\u671F\uFF0C\u4EC5\u5728\u660E\u786E\u77E5\u6089\u98CE\u9669\u540E\u52FE\u9009\u3002"
264
+ ] })
265
+ ] }),
266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
267
+ "npm \u5B89\u88C5\u6E90\uFF1A",
268
+ registry || "\u6CBF\u7528 DSH \u8BBE\u7F6E"
269
+ ] })
270
+ ] }),
271
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "modal-foot row", children: [
272
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: blocked, onClick: () => {
273
+ void submitPlan();
274
+ }, children: "\u786E\u8BA4\u66F4\u65B0" }),
275
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: blocked, onClick: () => setPlan(null), children: "\u53D6\u6D88" })
276
+ ] })
277
+ ] })
278
+ ] });
279
+ }
280
+
281
+ // src/styles.mjs
282
+ var styles = `
283
+ .pu{--pu-accent:var(--dsw-alias-state-active-primary,#3a71db);--pu-border:var(--dsw-alias-border-l2,#555);--pu-bg:var(--dsw-alias-bg-layer-1,#202020);--pu-card:var(--dsw-alias-bg-module-platform,#282828);--pu-text:var(--dsw-alias-label-primary,#f4f4f4);--pu-muted:var(--dsw-alias-label-secondary,#b8b8b8);--pu-soft:color-mix(in srgb,var(--pu-text) 4%,var(--pu-card));color:var(--pu-text);font:inherit;font-size:14px;line-height:1.6;max-width:1280px;min-width:0}
284
+ .pu *{box-sizing:border-box}.pu h2,.pu h3,.pu p{margin:0}.pu h2{font-size:24px;font-weight:650;letter-spacing:-.4px}.pu h3{font-size:16px}.pu small,.pu .muted,.pu .notice{color:var(--pu-muted)}.pu .notice{font-size:13px}.pu .mono{font:12px ui-monospace,monospace;overflow-wrap:anywhere}
285
+ .pu .bar,.pu .row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.pu .bar{justify-content:space-between}.pu.stack,.pu .stack{display:flex;flex-direction:column;gap:20px}.pu .box{border:1px solid var(--pu-border);border-radius:14px;padding:20px;background:var(--pu-card)}.pu header.box{background:linear-gradient(130deg,var(--pu-soft),var(--pu-card))}.pu .principles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}.pu .principles h3{margin-bottom:4px}
286
+ .pu .community{padding:10px 14px;border:1px solid var(--pu-border);border-radius:8px;background:var(--pu-card);font-size:13px;column-gap:16px;row-gap:8px}.pu .community a{display:inline-flex;align-items:center;min-height:44px;color:var(--pu-accent);font-weight:500;text-decoration:underline;text-underline-offset:3px}.pu .community a:hover{opacity:.8}.pu .community a:focus-visible{outline:2px solid var(--pu-accent);outline-offset:4px;border-radius:2px}.pu .community span{min-width:0;overflow-wrap:anywhere}
287
+ .pu button,.pu input,.pu select,.pu textarea{font:inherit;color:inherit;border:1px solid var(--pu-border);border-radius:8px;background:var(--pu-bg);min-height:44px;padding:9px 12px}.pu button{cursor:pointer;transition:background .15s}.pu button:hover{background:var(--pu-soft)}.pu button:disabled{opacity:.45;cursor:default}.pu button.primary{background:var(--pu-text);color:var(--pu-card);border-color:var(--pu-text)}.pu :is(button,input,select,textarea,summary):focus-visible{outline:2px solid var(--pu-accent);outline-offset:3px}.pu input:not([type=checkbox]),.pu select,.pu textarea{width:100%;min-width:0}.pu input[type=checkbox]{width:18px;height:18px;min-height:0;accent-color:var(--pu-accent)}.pu label{display:flex;flex-direction:column;gap:6px;font-size:13px}.pu label.check{flex-direction:row;align-items:center;gap:8px;min-height:44px}.pu .filter{min-width:170px;max-width:240px}
288
+ .pu .error{color:var(--dsw-alias-state-error-primary,#ef9393)}.pu .good{color:var(--dsw-alias-state-success-primary,#77ca9d)}.pu summary{cursor:pointer;color:var(--pu-muted);min-height:44px;display:flex;align-items:center}.pu details>div{padding-top:12px}.pu progress{width:100%;height:8px;accent-color:var(--pu-accent)}.pu .item{padding:16px 0;border-top:1px solid var(--pu-border)}.pu .empty{padding:24px;text-align:center;color:var(--pu-muted)}.pu .steps{padding:14px 16px;border:1px solid var(--pu-border);background:var(--pu-soft);border-radius:10px}
289
+ .pu .row-actions{gap:8px;align-items:stretch}.pu .reminder-list{list-style:none;padding:0;margin:0}.pu .reminder-list li{padding:12px 0;border-bottom:1px solid var(--pu-border)}.pu .reminder-list .mono{flex:1;min-width:180px}.pu .reminder-list button{flex-shrink:0}
290
+ .pu .table-shell{padding:0;overflow:hidden}.pu .section-pad{padding:16px 20px}.pu .scroll{overflow:auto;max-width:100%}.pu .scroll:focus-visible{outline:2px solid var(--pu-accent);outline-offset:-3px}.pu .table{width:100%;min-width:760px;border-collapse:collapse;font-size:14px}.pu th,.pu td{text-align:left;border-bottom:1px solid var(--pu-border);padding:16px 20px;vertical-align:middle}.pu th{background:var(--pu-soft);font-size:12px;color:var(--pu-muted)}.pu .table td small{display:block;font-size:12px;margin-top:3px}.pu .table tr:last-child td{border-bottom:0}.pu .table tr.selected,.pu .table tbody tr:hover{background:var(--pu-soft)}.pu .cell-actions{text-align:right;white-space:nowrap}
291
+ .pu dialog{color:var(--pu-text);background:var(--pu-bg);border:1px solid var(--pu-border);border-radius:16px;width:min(900px,calc(100vw - 32px));max-height:calc(100dvh - 40px);padding:0;box-shadow:0 24px 80px #0008}.pu dialog::backdrop{background:#000a}.pu .modal-head,.pu .modal-foot{padding:18px 24px;background:var(--pu-bg);position:sticky;z-index:1}.pu .modal-head{top:0;border-bottom:1px solid var(--pu-border)}.pu .modal-foot{bottom:0;border-top:1px solid var(--pu-border)}.pu .modal-body{padding:24px}
292
+ @media(max-width:600px){.pu .principles{grid-template-columns:1fr;gap:12px}.pu .box,.pu .section-pad,.pu .modal-body,.pu .modal-head,.pu .modal-foot{padding:16px}.pu .box.table-shell{padding:0}.pu .filter{max-width:none;flex:1}.pu h2{font-size:22px}}
293
+ @media(prefers-reduced-motion:reduce){.pu *{transition:none!important}}
294
+ `;
295
+
296
+ // src/intro.jsx
297
+ var import_react2 = require("react");
298
+ var import_jsx_runtime2 = require("react/jsx-runtime");
299
+ var descriptions = {
300
+ zh: {
301
+ title: "\u63D2\u4EF6\u66F4\u65B0\u7BA1\u7406",
302
+ language: "\u4ECB\u7ECD\u8BED\u8A00 / Introduction language",
303
+ community: "\u9879\u76EE\u4EA4\u6D41\u4E0E\u652F\u6301",
304
+ qq: "\u52A0\u5165 QQ \u4EA4\u6D41\u7FA4 \u2197",
305
+ group: "AndroidSix \u7684\u5F00\u6E90\u9879\u76EE\u4EA4\u6D41\u7FA4 \xB7 \u7FA4\u53F7",
306
+ repository: "GitHub \u4ED3\u5E93 \u2197",
307
+ star: "\u89C9\u5F97\u597D\u7528\uFF1F\u70B9\u4E2A Star \u9F13\u52B1\u4E00\u4E0B",
308
+ tagline: "\u53EA\u7BA1\u5DF2\u5B89\u88C5\u63D2\u4EF6\uFF0C\u8BA9\u6BCF\u4E00\u6B21\u66F4\u65B0\u6709\u636E\u53EF\u67E5\u3002",
309
+ principles: [
310
+ ["\u6765\u6E90\u4E0D\u4E71\u6362", "npm \u9891\u9053\u4E0E GitHub \u63D0\u4EA4\u5206\u522B\u68C0\u67E5\uFF0C\u4FDD\u7559\u542F\u7528\u72B6\u6001\u3002"],
311
+ ["\u66F4\u65B0\u5148\u786E\u8BA4", "\u6BCF\u5929\u68C0\u67E5\u3001\u786E\u8BA4\u540E\u5B89\u88C5\uFF1B\u53EF\u5FFD\u7565\u6307\u5B9A\u7248\u672C\u63D0\u9192\uFF0C\u65B0\u7248\u672C\u4ECD\u4F1A\u63D0\u9192\u3002"],
312
+ ["\u7ED3\u679C\u8981\u6838\u9A8C", "\u6838\u5BF9\u5B9E\u9645\u7248\u672C\u6216\u9501\u6587\u4EF6\u63D0\u4EA4\uFF0C\u5B89\u88C5\u4E0E\u751F\u6548\u5206\u5F00\u8BF4\u660E\u3002"]
313
+ ],
314
+ boundary: "\u4E0D\u662F\u63D2\u4EF6\u5E02\u573A\uFF1A\u4E0D\u63D0\u4F9B\u53D1\u73B0\u3001\u63A8\u8350\u3001\u6392\u884C\u6216\u65B0\u63D2\u4EF6\u5B89\u88C5\u3002\u5B89\u88C5\u3001\u5378\u8F7D\u548C\u811A\u672C\u6388\u6743\u4ECD\u5728 DSH \u539F\u751F\u63D2\u4EF6\u9875\u5904\u7406\u3002"
315
+ },
316
+ en: {
317
+ title: "Plugin Update Manager",
318
+ language: "\u4ECB\u7ECD\u8BED\u8A00 / Introduction language",
319
+ community: "Community and support",
320
+ qq: "Join the QQ group \u2197",
321
+ group: "AndroidSix community \xB7 QQ group",
322
+ repository: "GitHub repository \u2197",
323
+ star: "Find it useful? Give us a Star!",
324
+ tagline: "Only installed plugins. Every update checked and accounted for.",
325
+ principles: [
326
+ ["Keep the source", "Check npm channels and GitHub commits separately. Preserve enabled and disabled states."],
327
+ ["You decide", "Check daily, install only after confirmation. Ignore a specific release; newer releases still notify you."],
328
+ ["Verify the result", "Verify the installed version or locked commit. Distinguish installation from activation."]
329
+ ],
330
+ boundary: "Not a plugin marketplace: no discovery, recommendations, rankings, or new plugin installs. Use the native DSH plugin page for installation, removal, and build-script approval."
331
+ }
332
+ };
333
+ function UpdatesIntro({ initialLanguage = "zh" }) {
334
+ const [language, setLanguage] = (0, import_react2.useState)(initialLanguage === "en" ? "en" : "zh");
335
+ const text = descriptions[language];
336
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("header", { className: "box stack", lang: language === "zh" ? "zh-CN" : "en", children: [
337
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "bar", children: [
338
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "row", children: [
339
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: text.title }),
340
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "notice", children: [
341
+ "v",
342
+ version
343
+ ] })
344
+ ] }),
345
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: "filter", children: [
346
+ text.language,
347
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("select", { value: language, onChange: (e) => setLanguage(e.target.value), children: [
348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }),
349
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "en", children: "English" })
350
+ ] })
351
+ ] })
352
+ ] }),
353
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "row community", "aria-label": text.community, children: [
354
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: "https://qm.qq.com/q/eQC7OQXQe4", target: "_blank", rel: "noopener noreferrer", children: text.qq }),
355
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "muted", children: [
356
+ text.group,
357
+ " ",
358
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "1124103038" })
359
+ ] }),
360
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: repository.url.replace(/^git\+/, "").replace(/\.git$/, ""), target: "_blank", rel: "noopener noreferrer", children: text.repository }),
361
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "muted", children: text.star })
362
+ ] }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: text.tagline }),
364
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "principles", children: text.principles.map(([title, detail]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { children: [
365
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: title }),
366
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "notice", children: detail })
367
+ ] }, title)) }),
368
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "notice", children: text.boundary })
369
+ ] });
370
+ }
371
+
372
+ // src/client.jsx
373
+ var import_jsx_runtime3 = require("react/jsx-runtime");
374
+ var name2 = "dsh-plugin-updates-client";
375
+ var inject = ["slots"];
376
+ var ENDPOINT = "/.well-known/dsh-plugin-updates";
377
+ var updateListeners = /* @__PURE__ */ new Set();
378
+ var openUpdates;
379
+ function apply(ctx) {
380
+ openUpdates = () => ctx.get("pluginNavigation")?.openBundle(name);
381
+ ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({ name: "plugins.bundle.config", key: name }, UpdatesPage));
382
+ ctx.slots.inject("shell.overlay", () => ctx.slots.register({ name: "shell.overlay", id: "dsh-plugin-updates-reminder" }, UpdateReminder));
383
+ }
384
+ async function readResponse(response) {
385
+ let value;
386
+ try {
387
+ value = await response.json();
388
+ } catch {
389
+ throw Error("\u66F4\u65B0\u7BA1\u7406\u540E\u53F0\u5C1A\u672A\u8FDE\u63A5\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
390
+ }
391
+ if (!response.ok) throw Error(value.error || "\u64CD\u4F5C\u672A\u5B8C\u6210");
392
+ if (!value?.pluginUpdates || value.pluginVersion !== version) throw Error("\u66F4\u65B0\u7BA1\u7406\u524D\u540E\u53F0\u7248\u672C\u672A\u540C\u6B65\uFF0C\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u65B0\u6253\u5F00 DSH");
393
+ return value;
394
+ }
395
+ function useUpdates() {
396
+ const [data, setData] = (0, import_react3.useState)(null), [error, setError] = (0, import_react3.useState)(""), [busy, setBusy] = (0, import_react3.useState)(false);
397
+ const running = data?.pluginUpdates.job?.state === "running";
398
+ (0, import_react3.useEffect)(() => {
399
+ let live = true, pending = false;
400
+ const abort = new AbortController();
401
+ async function poll() {
402
+ if (document.hidden || pending) return;
403
+ pending = true;
404
+ try {
405
+ const value = await readResponse(await fetch(ENDPOINT, { cache: "no-store", signal: AbortSignal.any([abort.signal, AbortSignal.timeout(8e3)]) }));
406
+ if (live) {
407
+ setData(value);
408
+ setError("");
409
+ }
410
+ } catch (e) {
411
+ if (live) setError(e.message);
412
+ } finally {
413
+ pending = false;
414
+ }
415
+ }
416
+ void poll();
417
+ const timer = setInterval(poll, running ? 2e3 : 6e4);
418
+ const sync = (value) => {
419
+ if (live) {
420
+ setData(value);
421
+ setError("");
422
+ }
423
+ };
424
+ updateListeners.add(sync);
425
+ document.addEventListener("visibilitychange", poll);
426
+ return () => {
427
+ live = false;
428
+ abort.abort();
429
+ clearInterval(timer);
430
+ updateListeners.delete(sync);
431
+ document.removeEventListener("visibilitychange", poll);
432
+ };
433
+ }, [running]);
434
+ async function act(action) {
435
+ if (busy || !data) return false;
436
+ setBusy(true);
437
+ setError("");
438
+ try {
439
+ const value = await readResponse(await fetch(ENDPOINT, {
440
+ method: "POST",
441
+ headers: { "Content-Type": "application/json", "X-Plugin-Updates-Key": data.key },
442
+ body: JSON.stringify(action),
443
+ signal: AbortSignal.timeout(15e3)
444
+ }));
445
+ setData(value);
446
+ for (const listener of updateListeners) listener(value);
447
+ return value;
448
+ } catch (e) {
449
+ setError(e.message);
450
+ return false;
451
+ } finally {
452
+ setBusy(false);
453
+ }
454
+ }
455
+ return { data, error, busy, act };
456
+ }
457
+ function UpdatesPage() {
458
+ const { data, error, busy, act } = useUpdates();
459
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "pu stack", children: [
460
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: styles }),
461
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UpdatesIntro, {}),
462
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "error", role: "alert", children: error }),
463
+ data ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PluginUpdatesPanel, { data: data.pluginUpdates, busy, act }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "status", children: "\u6B63\u5728\u8FDE\u63A5\u66F4\u65B0\u7BA1\u7406\u540E\u53F0\u2026" })
464
+ ] });
465
+ }
466
+ function UpdateReminder() {
467
+ const { data, busy, act } = useUpdates();
468
+ const [opened, setOpened] = (0, import_react3.useState)(null), [error, setError] = (0, import_react3.useState)("");
469
+ const reminders = data?.pluginUpdates.reminders;
470
+ (0, import_react3.useEffect)(() => {
471
+ setOpened((current) => {
472
+ if (!reminders?.length) return null;
473
+ if (!current?.length) return document.querySelector("dialog[open]") ? null : reminders;
474
+ const remaining = current.filter((row) => reminders.some((next) => next.key === row.key));
475
+ return remaining.length ? remaining : null;
476
+ });
477
+ }, [reminders]);
478
+ async function ignore(rows) {
479
+ const result = await act({ action: "plugins.ignore", keys: rows.map((row) => row.targetKey) });
480
+ if (!result) {
481
+ setError("\u5FFD\u7565\u7248\u672C\u672A\u4FDD\u5B58\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
482
+ return;
483
+ }
484
+ setError("");
485
+ setOpened((current) => {
486
+ const remaining = current?.filter((row) => !rows.some((ignored) => ignored.key === row.key));
487
+ return remaining?.length ? remaining : null;
488
+ });
489
+ }
490
+ async function dismiss(open = false) {
491
+ const result = await act({ action: "plugins.dismiss", keys: opened.map((row) => row.key) });
492
+ if (!result) {
493
+ setError("\u63D0\u9192\u5904\u7406\u672A\u4FDD\u5B58\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5");
494
+ return;
495
+ }
496
+ setOpened(null);
497
+ if (open) openUpdates?.();
498
+ }
499
+ if (!opened?.length || !data) return null;
500
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "pu", children: [
501
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: styles }),
502
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Modal, { title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6\u6709\u66F4\u65B0", busy, close: () => {
503
+ void dismiss();
504
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "modal-body stack", children: [
505
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { children: [
506
+ opened.length,
507
+ " \u4E2A\u63D2\u4EF6\u53EF\u66F4\u65B0\u3002\u4E0D\u4F1A\u81EA\u52A8\u5B89\u88C5\uFF0C\u8BF7\u5148\u67E5\u770B\u76EE\u6807\u7248\u672C\u3002"
508
+ ] }),
509
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { role: "alert", className: "error", children: error }),
510
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "reminder-list", children: opened.map((row) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "bar", children: [
511
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mono", children: [
512
+ row.name,
513
+ " \xB7 ",
514
+ row.version || "\u672A\u77E5\u7248\u672C",
515
+ " \u2192 ",
516
+ row.latestCommit?.slice(0, 8) || row.latestVersion
517
+ ] }),
518
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { disabled: busy, "aria-label": `\u5FFD\u7565 ${row.name} \u6B64\u7248\u672C\u63D0\u9192`, onClick: () => {
519
+ void ignore([row]);
520
+ }, children: "\u5FFD\u7565\u6B64\u7248\u672C" })
521
+ ] }) }, row.key)) }),
522
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "notice", children: "\u5FFD\u7565\u4EC5\u5C4F\u853D\u5BF9\u5E94\u7248\u672C / \u63D0\u4EA4\u7684\u63D0\u9192\uFF0C\u91CD\u542F\u540E\u4FDD\u7559\uFF1B\u65B0\u7248\u672C\u4ECD\u63D0\u9192\u3002\u5728\u66F4\u65B0\u6E05\u5355\u53EF\u6062\u590D\u63D0\u9192\u6216\u624B\u52A8\u66F4\u65B0\u3002" }),
523
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "row", children: [
524
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "primary", disabled: busy, onClick: () => {
525
+ void dismiss(true);
526
+ }, children: "\u67E5\u770B\u66F4\u65B0\u7BA1\u7406" }),
527
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { disabled: busy, onClick: () => {
528
+ void ignore(opened);
529
+ }, children: "\u5FFD\u7565\u4EE5\u4E0A\u7248\u672C" }),
530
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { disabled: busy, onClick: () => {
531
+ void dismiss();
532
+ }, children: "\u7A0D\u540E\u5904\u7406" })
533
+ ] })
534
+ ] }) })
535
+ ] });
536
+ }
537
+ return module.exports; } });
538
+ //# sourceMappingURL=client.js.map