@morehao/dsh-github-trending 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/client.js +206 -182
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.2 - 2026-10-31
|
|
4
|
+
|
|
5
|
+
### 改进
|
|
6
|
+
|
|
7
|
+
- **更新入口更显眼**:概览页新增「插件更新」卡片——当前 / 最新版本、检查更新、更新到 vX、本地安装时的手动命令都在这里;侧栏包名在有新版时显示红点。关于弹层与概览共用同一个 controller(模块级单例),打开多个位置不会重复请求。
|
|
8
|
+
- 关于弹层的更新区块改为复用同一组件(`client/update-panel.ts`),行为不变。
|
|
9
|
+
|
|
3
10
|
## 0.3.1 - 2026-10-31
|
|
4
11
|
|
|
5
12
|
### 新增
|
package/client.js
CHANGED
|
@@ -357,7 +357,8 @@ var DICT = {
|
|
|
357
357
|
"about.update.manual": "当前是本地 {kind} 安装,不能一键更新(会把开发链接换成 npm 版)。手动更新:",
|
|
358
358
|
"about.update.copy": "复制命令",
|
|
359
359
|
"about.update.copied": "已复制",
|
|
360
|
-
"about.update.hint": "只检查 npm 上的 latest 稳定版;更新后需要重启 DSH。"
|
|
360
|
+
"about.update.hint": "只检查 npm 上的 latest 稳定版;更新后需要重启 DSH。",
|
|
361
|
+
"update.badge": "有新版本可用"
|
|
361
362
|
},
|
|
362
363
|
en: {
|
|
363
364
|
"section.title": "GitHub Trending",
|
|
@@ -671,7 +672,8 @@ var DICT = {
|
|
|
671
672
|
"about.update.manual": "Installed from a local {kind} spec; one-click update is disabled (it would replace the dev link). Update manually:",
|
|
672
673
|
"about.update.copy": "Copy command",
|
|
673
674
|
"about.update.copied": "Copied",
|
|
674
|
-
"about.update.hint": "Checks the npm latest stable tag only; applying requires a DSH restart."
|
|
675
|
+
"about.update.hint": "Checks the npm latest stable tag only; applying requires a DSH restart.",
|
|
676
|
+
"update.badge": "Update available"
|
|
675
677
|
}
|
|
676
678
|
};
|
|
677
679
|
function activeLang(locale) {
|
|
@@ -952,6 +954,9 @@ var CSS = `
|
|
|
952
954
|
.dshgt-update-manual{margin-top:9px;padding:9px 10px;border:1px solid color-mix(in srgb,var(--gt-warn) 35%,var(--gt-border));border-radius:8px;background:color-mix(in srgb,var(--gt-warn) 6%,var(--gt-card));}
|
|
953
955
|
.dshgt-update-manual .dshgt-update-warn{margin:0 0 6px;}
|
|
954
956
|
.dshgt-update-cmd{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;line-height:1.5;color:var(--gt-fg);word-break:break-all;user-select:all;}
|
|
957
|
+
.dshgt-update-dot{display:inline-block;width:6px;height:6px;margin-left:6px;border-radius:50%;background:var(--gt-err);vertical-align:middle;flex:none;}
|
|
958
|
+
.dshgt-update-bare{margin-top:0;padding-top:0;border-top:0;}
|
|
959
|
+
.dshgt-update-card .dshgt-card-h{margin-bottom:2px;}
|
|
955
960
|
|
|
956
961
|
@media (max-width:1100px){
|
|
957
962
|
.dshgt-app{grid-template-columns:190px minmax(0,1fr);}
|
|
@@ -1995,6 +2000,196 @@ function LiveRun(props) {
|
|
|
1995
2000
|
);
|
|
1996
2001
|
}
|
|
1997
2002
|
|
|
2003
|
+
// node_modules/@morehao/dsh-plugin-kit/dist/update-client.js
|
|
2004
|
+
var IDLE = { status: "idle", view: null, error: null };
|
|
2005
|
+
function errorOf(error) {
|
|
2006
|
+
if (error !== null && typeof error === "object") {
|
|
2007
|
+
const value = error;
|
|
2008
|
+
const message = typeof value.message === "string" && value.message !== "" ? value.message : "操作失败";
|
|
2009
|
+
return typeof value.code === "string" ? { code: value.code, message } : { message };
|
|
2010
|
+
}
|
|
2011
|
+
return { message: String(error ?? "操作失败") };
|
|
2012
|
+
}
|
|
2013
|
+
function createUpdateController(options) {
|
|
2014
|
+
const now = options.now ?? Date.now;
|
|
2015
|
+
let state = { ...IDLE };
|
|
2016
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2017
|
+
let inFlight = null;
|
|
2018
|
+
function emit(next) {
|
|
2019
|
+
state = next;
|
|
2020
|
+
options.onChange?.(state);
|
|
2021
|
+
for (const listener of listeners) listener(state);
|
|
2022
|
+
}
|
|
2023
|
+
async function check(checkOptions = {}) {
|
|
2024
|
+
if (inFlight !== null) return;
|
|
2025
|
+
inFlight = "check";
|
|
2026
|
+
emit({ ...state, status: "checking", error: null });
|
|
2027
|
+
try {
|
|
2028
|
+
const view = await options.request.check(checkOptions);
|
|
2029
|
+
const checkedAt = new Date(now()).toISOString();
|
|
2030
|
+
if (view.checkFailed) {
|
|
2031
|
+
emit({
|
|
2032
|
+
status: "failed",
|
|
2033
|
+
view,
|
|
2034
|
+
error: { code: "CHECK_FAILED", message: "检查更新失败:拿不到 registry 上的最新版本" },
|
|
2035
|
+
checkedAt
|
|
2036
|
+
});
|
|
2037
|
+
} else {
|
|
2038
|
+
emit({ status: view.updateAvailable ? "available" : "current", view, error: null, checkedAt });
|
|
2039
|
+
}
|
|
2040
|
+
} catch (error) {
|
|
2041
|
+
emit({ ...state, status: "failed", error: errorOf(error) });
|
|
2042
|
+
} finally {
|
|
2043
|
+
inFlight = null;
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
async function apply2() {
|
|
2047
|
+
if (inFlight !== null) return;
|
|
2048
|
+
const view = state.view;
|
|
2049
|
+
if (view === null || !view.updateAvailable) {
|
|
2050
|
+
emit({ ...state, status: "failed", error: { code: "NO_UPDATE", message: "没有可更新的版本,请先检查更新" } });
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
if (!view.canApply) {
|
|
2054
|
+
emit({
|
|
2055
|
+
...state,
|
|
2056
|
+
status: "failed",
|
|
2057
|
+
error: { code: "NO_APPLY", message: `当前环境不支持一键更新,请执行:${view.manualCommand}` }
|
|
2058
|
+
});
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
inFlight = "apply";
|
|
2062
|
+
emit({ ...state, status: "applying", error: null });
|
|
2063
|
+
try {
|
|
2064
|
+
const result = await options.request.apply();
|
|
2065
|
+
const restartRequired = result.restartRequired ?? result.application !== "applied";
|
|
2066
|
+
emit({ ...state, status: restartRequired ? "restart-required" : "applied", error: null });
|
|
2067
|
+
} catch (error) {
|
|
2068
|
+
emit({ ...state, status: "failed", error: errorOf(error) });
|
|
2069
|
+
} finally {
|
|
2070
|
+
inFlight = null;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
return {
|
|
2074
|
+
getState: () => state,
|
|
2075
|
+
subscribe: (listener) => {
|
|
2076
|
+
listeners.add(listener);
|
|
2077
|
+
return () => {
|
|
2078
|
+
listeners.delete(listener);
|
|
2079
|
+
};
|
|
2080
|
+
},
|
|
2081
|
+
check,
|
|
2082
|
+
apply: apply2,
|
|
2083
|
+
reset: () => emit({ ...IDLE })
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
// client/update-panel.ts
|
|
2088
|
+
var singleton = null;
|
|
2089
|
+
function getUpdateController() {
|
|
2090
|
+
if (singleton === null) {
|
|
2091
|
+
singleton = createUpdateController({
|
|
2092
|
+
request: {
|
|
2093
|
+
check: (options) => getPluginUpdate(options.fresh === true ? { fresh: true } : {}),
|
|
2094
|
+
apply: () => applyPluginUpdate()
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
return singleton;
|
|
2099
|
+
}
|
|
2100
|
+
function usePluginUpdate() {
|
|
2101
|
+
const controller = getUpdateController();
|
|
2102
|
+
const [state, setState] = import_react.default.useState(() => controller.getState());
|
|
2103
|
+
import_react.default.useEffect(() => {
|
|
2104
|
+
const unsubscribe = controller.subscribe(setState);
|
|
2105
|
+
if (controller.getState().status === "idle") void controller.check();
|
|
2106
|
+
return unsubscribe;
|
|
2107
|
+
}, [controller]);
|
|
2108
|
+
return [state, controller];
|
|
2109
|
+
}
|
|
2110
|
+
function UpdateDot(props) {
|
|
2111
|
+
const [state] = usePluginUpdate();
|
|
2112
|
+
if (state.view?.updateAvailable !== true) return null;
|
|
2113
|
+
return h("span", { className: "dshgt-update-dot", title: props.t("update.badge") });
|
|
2114
|
+
}
|
|
2115
|
+
function PluginUpdateSection(props) {
|
|
2116
|
+
const { t } = props;
|
|
2117
|
+
const [state, controller] = usePluginUpdate();
|
|
2118
|
+
const [confirming, setConfirming] = import_react.default.useState(false);
|
|
2119
|
+
const [copied, setCopied] = import_react.default.useState(false);
|
|
2120
|
+
import_react.default.useEffect(() => {
|
|
2121
|
+
if (state.status === "applying" || state.status === "restart-required" || state.status === "applied") setConfirming(false);
|
|
2122
|
+
}, [state.status]);
|
|
2123
|
+
const copyCommand = () => {
|
|
2124
|
+
const command = state.view?.manualCommand;
|
|
2125
|
+
if (command === void 0) return;
|
|
2126
|
+
void copyText(command).then((ok) => {
|
|
2127
|
+
if (!ok) return;
|
|
2128
|
+
setCopied(true);
|
|
2129
|
+
setTimeout(() => setCopied(false), 1600);
|
|
2130
|
+
});
|
|
2131
|
+
};
|
|
2132
|
+
const view = state.view;
|
|
2133
|
+
const status = state.status;
|
|
2134
|
+
const target = view !== null && view.updateAvailable ? view.latestVersion ?? "" : "";
|
|
2135
|
+
const busy = status === "checking" || status === "applying";
|
|
2136
|
+
const settled = status === "restart-required" || status === "applied";
|
|
2137
|
+
const actionable = view !== null && view.updateAvailable && view.canApply && !settled && !busy;
|
|
2138
|
+
const manual = view !== null && (!view.canApply || view.checkFailed) ? view.manualCommand : null;
|
|
2139
|
+
const statusLine = () => {
|
|
2140
|
+
if (status === "checking" || view === null) return t("about.update.checking");
|
|
2141
|
+
if (status === "applying") return t("about.update.applying", { version: target });
|
|
2142
|
+
if (status === "restart-required") return t("about.update.done", { version: view.latestVersion ?? target });
|
|
2143
|
+
if (status === "applied") return t("about.update.applied", { version: view.latestVersion ?? target });
|
|
2144
|
+
if (status === "failed") {
|
|
2145
|
+
if (state.error?.code === "CHECK_FAILED") return t("about.update.checkFailed");
|
|
2146
|
+
return t("about.update.failed", { message: state.error?.message ?? "" });
|
|
2147
|
+
}
|
|
2148
|
+
if (view.checkFailed) return t("about.update.checkFailed");
|
|
2149
|
+
if (view.updateAvailable) return t("about.update.available", { latest: view.latestVersion ?? "", current: view.currentVersion });
|
|
2150
|
+
return t("about.update.current", { version: view.currentVersion });
|
|
2151
|
+
};
|
|
2152
|
+
const actions = [
|
|
2153
|
+
h(Btn, { key: "check", small: true, disabled: busy, onClick: () => void controller.check({ fresh: true }) }, t("about.update.check")),
|
|
2154
|
+
manual === null ? null : h(Btn, { key: "copy", small: true, onClick: copyCommand }, copied ? t("about.update.copied") : t("about.update.copy")),
|
|
2155
|
+
actionable ? confirming ? [
|
|
2156
|
+
h(
|
|
2157
|
+
Btn,
|
|
2158
|
+
{
|
|
2159
|
+
key: "confirm",
|
|
2160
|
+
small: true,
|
|
2161
|
+
variant: "danger",
|
|
2162
|
+
onClick: () => {
|
|
2163
|
+
setConfirming(false);
|
|
2164
|
+
void controller.apply();
|
|
2165
|
+
}
|
|
2166
|
+
},
|
|
2167
|
+
t("about.update.confirmYes")
|
|
2168
|
+
),
|
|
2169
|
+
h(Btn, { key: "cancel", small: true, onClick: () => setConfirming(false) }, t("about.update.cancel"))
|
|
2170
|
+
] : h(Btn, { key: "apply", small: true, variant: "primary", onClick: () => setConfirming(true) }, t("about.update.apply", { version: target })) : null
|
|
2171
|
+
].filter((item) => item !== null);
|
|
2172
|
+
return h(
|
|
2173
|
+
"div",
|
|
2174
|
+
{ className: `dshgt-update${props.bare === true ? " dshgt-update-bare" : ""}` },
|
|
2175
|
+
props.bare === true ? null : h(
|
|
2176
|
+
"div",
|
|
2177
|
+
{ className: "dshgt-update-head" },
|
|
2178
|
+
h("h4", null, t("about.update.title")),
|
|
2179
|
+
h("span", { className: "dshgt-hint" }, t("about.update.hint"))
|
|
2180
|
+
),
|
|
2181
|
+
h("p", { className: `dshgt-update-line${status === "failed" ? " dshgt-update-err" : ""}` }, statusLine()),
|
|
2182
|
+
confirming ? h("p", { className: "dshgt-update-warn" }, t("about.update.confirm", { version: target })) : null,
|
|
2183
|
+
h("div", { className: "dshgt-update-actions" }, actions),
|
|
2184
|
+
manual === null ? null : h(
|
|
2185
|
+
"div",
|
|
2186
|
+
{ className: "dshgt-update-manual" },
|
|
2187
|
+
h("p", { className: "dshgt-update-warn" }, t("about.update.manual", { kind: view?.installKind ?? "unknown" })),
|
|
2188
|
+
h("code", { className: "dshgt-update-cmd" }, manual)
|
|
2189
|
+
)
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
2192
|
+
|
|
1998
2193
|
// client/digest-core.ts
|
|
1999
2194
|
var DIGEST_WINDOW_DAYS = 30;
|
|
2000
2195
|
var DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
@@ -2328,6 +2523,12 @@ function OverviewView(props) {
|
|
|
2328
2523
|
)
|
|
2329
2524
|
);
|
|
2330
2525
|
})
|
|
2526
|
+
),
|
|
2527
|
+
h(
|
|
2528
|
+
"section",
|
|
2529
|
+
{ className: "dshgt-card dshgt-update-card" },
|
|
2530
|
+
h("div", { className: "dshgt-card-h" }, h("h3", null, t("about.update.title"))),
|
|
2531
|
+
h(PluginUpdateSection, { t, bare: true })
|
|
2331
2532
|
)
|
|
2332
2533
|
)
|
|
2333
2534
|
);
|
|
@@ -3179,117 +3380,10 @@ function metaLine(rendered) {
|
|
|
3179
3380
|
);
|
|
3180
3381
|
}
|
|
3181
3382
|
|
|
3182
|
-
// node_modules/@morehao/dsh-plugin-kit/dist/update-client.js
|
|
3183
|
-
var IDLE = { status: "idle", view: null, error: null };
|
|
3184
|
-
function errorOf(error) {
|
|
3185
|
-
if (error !== null && typeof error === "object") {
|
|
3186
|
-
const value = error;
|
|
3187
|
-
const message = typeof value.message === "string" && value.message !== "" ? value.message : "操作失败";
|
|
3188
|
-
return typeof value.code === "string" ? { code: value.code, message } : { message };
|
|
3189
|
-
}
|
|
3190
|
-
return { message: String(error ?? "操作失败") };
|
|
3191
|
-
}
|
|
3192
|
-
function createUpdateController(options) {
|
|
3193
|
-
const now = options.now ?? Date.now;
|
|
3194
|
-
let state = { ...IDLE };
|
|
3195
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
3196
|
-
let inFlight = null;
|
|
3197
|
-
function emit(next) {
|
|
3198
|
-
state = next;
|
|
3199
|
-
options.onChange?.(state);
|
|
3200
|
-
for (const listener of listeners) listener(state);
|
|
3201
|
-
}
|
|
3202
|
-
async function check(checkOptions = {}) {
|
|
3203
|
-
if (inFlight !== null) return;
|
|
3204
|
-
inFlight = "check";
|
|
3205
|
-
emit({ ...state, status: "checking", error: null });
|
|
3206
|
-
try {
|
|
3207
|
-
const view = await options.request.check(checkOptions);
|
|
3208
|
-
const checkedAt = new Date(now()).toISOString();
|
|
3209
|
-
if (view.checkFailed) {
|
|
3210
|
-
emit({
|
|
3211
|
-
status: "failed",
|
|
3212
|
-
view,
|
|
3213
|
-
error: { code: "CHECK_FAILED", message: "检查更新失败:拿不到 registry 上的最新版本" },
|
|
3214
|
-
checkedAt
|
|
3215
|
-
});
|
|
3216
|
-
} else {
|
|
3217
|
-
emit({ status: view.updateAvailable ? "available" : "current", view, error: null, checkedAt });
|
|
3218
|
-
}
|
|
3219
|
-
} catch (error) {
|
|
3220
|
-
emit({ ...state, status: "failed", error: errorOf(error) });
|
|
3221
|
-
} finally {
|
|
3222
|
-
inFlight = null;
|
|
3223
|
-
}
|
|
3224
|
-
}
|
|
3225
|
-
async function apply2() {
|
|
3226
|
-
if (inFlight !== null) return;
|
|
3227
|
-
const view = state.view;
|
|
3228
|
-
if (view === null || !view.updateAvailable) {
|
|
3229
|
-
emit({ ...state, status: "failed", error: { code: "NO_UPDATE", message: "没有可更新的版本,请先检查更新" } });
|
|
3230
|
-
return;
|
|
3231
|
-
}
|
|
3232
|
-
if (!view.canApply) {
|
|
3233
|
-
emit({
|
|
3234
|
-
...state,
|
|
3235
|
-
status: "failed",
|
|
3236
|
-
error: { code: "NO_APPLY", message: `当前环境不支持一键更新,请执行:${view.manualCommand}` }
|
|
3237
|
-
});
|
|
3238
|
-
return;
|
|
3239
|
-
}
|
|
3240
|
-
inFlight = "apply";
|
|
3241
|
-
emit({ ...state, status: "applying", error: null });
|
|
3242
|
-
try {
|
|
3243
|
-
const result = await options.request.apply();
|
|
3244
|
-
const restartRequired = result.restartRequired ?? result.application !== "applied";
|
|
3245
|
-
emit({ ...state, status: restartRequired ? "restart-required" : "applied", error: null });
|
|
3246
|
-
} catch (error) {
|
|
3247
|
-
emit({ ...state, status: "failed", error: errorOf(error) });
|
|
3248
|
-
} finally {
|
|
3249
|
-
inFlight = null;
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
return {
|
|
3253
|
-
getState: () => state,
|
|
3254
|
-
subscribe: (listener) => {
|
|
3255
|
-
listeners.add(listener);
|
|
3256
|
-
return () => {
|
|
3257
|
-
listeners.delete(listener);
|
|
3258
|
-
};
|
|
3259
|
-
},
|
|
3260
|
-
check,
|
|
3261
|
-
apply: apply2,
|
|
3262
|
-
reset: () => emit({ ...IDLE })
|
|
3263
|
-
};
|
|
3264
|
-
}
|
|
3265
|
-
|
|
3266
3383
|
// client/about.ts
|
|
3267
3384
|
function AboutDialog(props) {
|
|
3268
3385
|
const { t, state } = props;
|
|
3269
3386
|
const [copied, setCopied] = import_react.default.useState(false);
|
|
3270
|
-
const [copiedCommand, setCopiedCommand] = import_react.default.useState(false);
|
|
3271
|
-
const [confirming, setConfirming] = import_react.default.useState(false);
|
|
3272
|
-
const controllerRef = import_react.default.useRef(null);
|
|
3273
|
-
if (controllerRef.current === null) {
|
|
3274
|
-
controllerRef.current = createUpdateController({
|
|
3275
|
-
request: {
|
|
3276
|
-
check: (options) => getPluginUpdate(options.fresh === true ? { fresh: true } : {}),
|
|
3277
|
-
apply: () => applyPluginUpdate()
|
|
3278
|
-
}
|
|
3279
|
-
});
|
|
3280
|
-
}
|
|
3281
|
-
const controller = controllerRef.current;
|
|
3282
|
-
const [updateState, setUpdateState] = import_react.default.useState(() => controller.getState());
|
|
3283
|
-
import_react.default.useEffect(() => {
|
|
3284
|
-
const unsubscribe = controller.subscribe(setUpdateState);
|
|
3285
|
-
if (controller.getState().status === "idle") void controller.check();
|
|
3286
|
-
return unsubscribe;
|
|
3287
|
-
}, [controller]);
|
|
3288
|
-
import_react.default.useEffect(() => {
|
|
3289
|
-
if (updateState.status === "applying" || updateState.status === "restart-required" || updateState.status === "applied") {
|
|
3290
|
-
setConfirming(false);
|
|
3291
|
-
}
|
|
3292
|
-
}, [updateState.status]);
|
|
3293
3387
|
const plugin = state.plugin;
|
|
3294
3388
|
const fullName = `${plugin.name}@v${plugin.version}`;
|
|
3295
3389
|
const repository = plugin.repository;
|
|
@@ -3309,59 +3403,6 @@ function AboutDialog(props) {
|
|
|
3309
3403
|
setTimeout(() => setCopied(false), 1600);
|
|
3310
3404
|
});
|
|
3311
3405
|
};
|
|
3312
|
-
const copyCommand = () => {
|
|
3313
|
-
const command = updateState.view?.manualCommand;
|
|
3314
|
-
if (command === void 0) return;
|
|
3315
|
-
void copyText(command).then((ok) => {
|
|
3316
|
-
if (!ok) return;
|
|
3317
|
-
setCopiedCommand(true);
|
|
3318
|
-
setTimeout(() => setCopiedCommand(false), 1600);
|
|
3319
|
-
});
|
|
3320
|
-
};
|
|
3321
|
-
const view = updateState.view;
|
|
3322
|
-
const status = updateState.status;
|
|
3323
|
-
const target = view !== null && view.updateAvailable ? view.latestVersion ?? "" : "";
|
|
3324
|
-
const busy = status === "checking" || status === "applying";
|
|
3325
|
-
const settled = status === "restart-required" || status === "applied";
|
|
3326
|
-
const actionable = view !== null && view.updateAvailable && view.canApply && !settled && !busy;
|
|
3327
|
-
const manual = view !== null && (!view.canApply || view.checkFailed) ? view.manualCommand : null;
|
|
3328
|
-
const statusLine = () => {
|
|
3329
|
-
if (status === "checking" || view === null) return t("about.update.checking");
|
|
3330
|
-
if (status === "applying") return t("about.update.applying", { version: target });
|
|
3331
|
-
if (status === "restart-required") return t("about.update.done", { version: view.latestVersion ?? target });
|
|
3332
|
-
if (status === "applied") return t("about.update.applied", { version: view.latestVersion ?? target });
|
|
3333
|
-
if (status === "failed") {
|
|
3334
|
-
if (updateState.error?.code === "CHECK_FAILED") return t("about.update.checkFailed");
|
|
3335
|
-
return t("about.update.failed", { message: updateState.error?.message ?? "" });
|
|
3336
|
-
}
|
|
3337
|
-
if (view.checkFailed) return t("about.update.checkFailed");
|
|
3338
|
-
if (view.updateAvailable) return t("about.update.available", { latest: view.latestVersion ?? "", current: view.currentVersion });
|
|
3339
|
-
return t("about.update.current", { version: view.currentVersion });
|
|
3340
|
-
};
|
|
3341
|
-
const updateActions = [
|
|
3342
|
-
h(Btn, { key: "check", small: true, disabled: busy, onClick: () => void controller.check({ fresh: true }) }, t("about.update.check")),
|
|
3343
|
-
manual === null ? null : h(
|
|
3344
|
-
Btn,
|
|
3345
|
-
{ key: "copy-command", small: true, onClick: copyCommand },
|
|
3346
|
-
copiedCommand ? t("about.update.copied") : t("about.update.copy")
|
|
3347
|
-
),
|
|
3348
|
-
actionable ? confirming ? [
|
|
3349
|
-
h(
|
|
3350
|
-
Btn,
|
|
3351
|
-
{
|
|
3352
|
-
key: "confirm",
|
|
3353
|
-
small: true,
|
|
3354
|
-
variant: "danger",
|
|
3355
|
-
onClick: () => {
|
|
3356
|
-
setConfirming(false);
|
|
3357
|
-
void controller.apply();
|
|
3358
|
-
}
|
|
3359
|
-
},
|
|
3360
|
-
t("about.update.confirmYes")
|
|
3361
|
-
),
|
|
3362
|
-
h(Btn, { key: "cancel", small: true, onClick: () => setConfirming(false) }, t("about.update.cancel"))
|
|
3363
|
-
] : h(Btn, { key: "apply", small: true, variant: "primary", onClick: () => setConfirming(true) }, t("about.update.apply", { version: target })) : null
|
|
3364
|
-
].filter((item) => item !== null);
|
|
3365
3406
|
const dialog = h(
|
|
3366
3407
|
"div",
|
|
3367
3408
|
{ className: "dshgt-modal-mask", onClick: (event) => {
|
|
@@ -3393,25 +3434,7 @@ function AboutDialog(props) {
|
|
|
3393
3434
|
[t("about.env"), t("about.env.value")]
|
|
3394
3435
|
]
|
|
3395
3436
|
}),
|
|
3396
|
-
h(
|
|
3397
|
-
"div",
|
|
3398
|
-
{ className: "dshgt-update" },
|
|
3399
|
-
h(
|
|
3400
|
-
"div",
|
|
3401
|
-
{ className: "dshgt-update-head" },
|
|
3402
|
-
h("h4", null, t("about.update.title")),
|
|
3403
|
-
h("span", { className: "dshgt-hint" }, t("about.update.hint"))
|
|
3404
|
-
),
|
|
3405
|
-
h("p", { className: `dshgt-update-line${status === "failed" ? " dshgt-update-err" : ""}` }, statusLine()),
|
|
3406
|
-
confirming ? h("p", { className: "dshgt-update-warn" }, t("about.update.confirm", { version: target })) : null,
|
|
3407
|
-
h("div", { className: "dshgt-update-actions" }, updateActions),
|
|
3408
|
-
manual === null ? null : h(
|
|
3409
|
-
"div",
|
|
3410
|
-
{ className: "dshgt-update-manual" },
|
|
3411
|
-
h("p", { className: "dshgt-update-warn" }, t("about.update.manual", { kind: view?.installKind ?? "unknown" })),
|
|
3412
|
-
h("code", { className: "dshgt-update-cmd" }, manual)
|
|
3413
|
-
)
|
|
3414
|
-
)
|
|
3437
|
+
h(PluginUpdateSection, { t })
|
|
3415
3438
|
)
|
|
3416
3439
|
);
|
|
3417
3440
|
return h("div", { className: "dshgt-root" }, dialog);
|
|
@@ -3659,7 +3682,8 @@ function apply(ctx) {
|
|
|
3659
3682
|
onClick: () => setAboutOpen(true),
|
|
3660
3683
|
title: plugin === void 0 ? "" : fullName
|
|
3661
3684
|
},
|
|
3662
|
-
plugin?.name ?? t("section.title")
|
|
3685
|
+
plugin?.name ?? t("section.title"),
|
|
3686
|
+
h(UpdateDot, { t })
|
|
3663
3687
|
),
|
|
3664
3688
|
h(
|
|
3665
3689
|
"div",
|