dsh-folia 2.4.1 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +101 -15
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -16244,10 +16244,15 @@ window.__ModuleLoader__.load({
|
|
|
16244
16244
|
setLoading(true);
|
|
16245
16245
|
setError(null);
|
|
16246
16246
|
try {
|
|
16247
|
-
|
|
16247
|
+
// ⚠️ `apiJson` 返回的是 **`{ ok, status, data, error }` 包装对象**,不是响应体本身
|
|
16248
|
+
//(见 src/api-client.js 的 apiFetch)。最初按裸体取值 ⇒ `list=[] 且 error=null`,
|
|
16249
|
+
// 界面显示"没有匹配的皮肤包"却没有任何错误提示 —— 静默空列表比报错难查得多。
|
|
16250
|
+
// `parse: "always"` 让非 2xx 的 `{error}` 也能被读到。
|
|
16251
|
+
const resp = await apiJson("/skins" + (force ? "?refresh=1" : ""), { parse: "always" });
|
|
16252
|
+
const r = (resp && resp.data) || null;
|
|
16248
16253
|
setList((r && r.skins) || []);
|
|
16249
16254
|
setActive((r && r.active) || null);
|
|
16250
|
-
setError((r && r.error) || null);
|
|
16255
|
+
setError((r && r.error) || (resp && resp.error) || null);
|
|
16251
16256
|
setHarnessFound(!r || r.harnessFound !== false);
|
|
16252
16257
|
} catch (e) {
|
|
16253
16258
|
setError("network");
|
|
@@ -16259,20 +16264,43 @@ window.__ModuleLoader__.load({
|
|
|
16259
16264
|
|
|
16260
16265
|
React.useEffect(() => { load(false); }, [load]);
|
|
16261
16266
|
|
|
16267
|
+
/**
|
|
16268
|
+
* 执行一个动作(install / activate / remove)。
|
|
16269
|
+
*
|
|
16270
|
+
* ⚠️ **「使用」必须立刻有反馈**:切换皮肤只写 `skin-center-active.json`,host 端 6 ms 就应,
|
|
16271
|
+
* 而皮肤要重启才生效 —— 如果等一次 `?refresh=1`(约 600 ms)再改标记,用户看到的就是
|
|
16272
|
+
* "点了一下,半天没反应"。所以「使用」走**乐观更新**:先本地翻转 active 并把提示打出来,
|
|
16273
|
+
* 请求失败再回滚重拉。装 / 删仍然要重拉(已装标记与体积都变了)。
|
|
16274
|
+
*/
|
|
16262
16275
|
async function act(kind, id, label) {
|
|
16263
16276
|
if (busy) return;
|
|
16264
16277
|
setBusy(id);
|
|
16265
16278
|
setNote(null);
|
|
16279
|
+
const prevActive = active;
|
|
16280
|
+
if (kind === "activate") {
|
|
16281
|
+
// 乐观:先给反馈,再等网络
|
|
16282
|
+
setActive(id);
|
|
16283
|
+
setList((prev) => prev.map((x) => ({ ...x, active: x.id === id })));
|
|
16284
|
+
setNote({ kind: "ok", text: weT("正在切换到「") + label + weT("」…") });
|
|
16285
|
+
}
|
|
16266
16286
|
try {
|
|
16267
|
-
|
|
16268
|
-
|
|
16287
|
+
// 同样是包装对象:`ok` 是 HTTP 2xx,业务结论在 `data.ok`(宿主回 `{ok:false,error}`)。
|
|
16288
|
+
const resp = await apiPostJson("/skins/" + kind, { id }, { parse: "always" });
|
|
16289
|
+
const r = (resp && resp.data) || null;
|
|
16290
|
+
if (resp && resp.ok && r && r.ok) {
|
|
16269
16291
|
if (kind === "install") {
|
|
16270
16292
|
setNote({ kind: "ok", text: weT("已安装:") + label });
|
|
16271
16293
|
await load(true);
|
|
16272
16294
|
} else if (kind === "activate") {
|
|
16273
|
-
|
|
16274
|
-
|
|
16275
|
-
|
|
16295
|
+
setNote({
|
|
16296
|
+
kind: "ok",
|
|
16297
|
+
text: weT("已切换到「") + label + weT("」"),
|
|
16298
|
+
// 皮肤中心是在**页面启动时**拉 `/api/skin-center/v2/active` 再注入样式的,
|
|
16299
|
+
// 所以"换皮肤"只需刷新这一页(不重启 DSH 进程):下面的按钮就做这件事。
|
|
16300
|
+
// 不自动刷:用户可能正在输入,突然刷新会打断。
|
|
16301
|
+
reload: true,
|
|
16302
|
+
});
|
|
16303
|
+
// 不再整表重拉:本地标记已经对了,省掉那 600 ms 的"没反应"窗口。
|
|
16276
16304
|
} else if (kind === "remove") {
|
|
16277
16305
|
setNote({ kind: "ok", text: weT("已删除:") + label });
|
|
16278
16306
|
await load(true);
|
|
@@ -16281,9 +16309,18 @@ window.__ModuleLoader__.load({
|
|
|
16281
16309
|
const code = (r && r.error) || "failed";
|
|
16282
16310
|
const detail = (r && r.detail) ? "(" + r.detail + ")" : "";
|
|
16283
16311
|
setNote({ kind: "err", text: weT("操作失败:") + code + detail });
|
|
16312
|
+
if (kind === "activate") {
|
|
16313
|
+
// 回滚乐观更新
|
|
16314
|
+
setActive(prevActive);
|
|
16315
|
+
setList((prev) => prev.map((x) => ({ ...x, active: x.id === prevActive })));
|
|
16316
|
+
}
|
|
16284
16317
|
}
|
|
16285
16318
|
} catch (e) {
|
|
16286
16319
|
setNote({ kind: "err", text: weT("请求失败:") + (e && e.message ? e.message : weT("网络错误")) });
|
|
16320
|
+
if (kind === "activate") {
|
|
16321
|
+
setActive(prevActive);
|
|
16322
|
+
setList((prev) => prev.map((x) => ({ ...x, active: x.id === prevActive })));
|
|
16323
|
+
}
|
|
16287
16324
|
} finally {
|
|
16288
16325
|
setBusy("");
|
|
16289
16326
|
}
|
|
@@ -16320,6 +16357,22 @@ window.__ModuleLoader__.load({
|
|
|
16320
16357
|
}
|
|
16321
16358
|
|
|
16322
16359
|
const children = [React.createElement("div", { className: "we-picker__section", key: "sec" }, header)];
|
|
16360
|
+
// 常驻一行「当前皮肤」:切换只写文件、皮肤要重启才生效,不给这一行用户就无从判断
|
|
16361
|
+
// 刚才那次点击到底成没成(这是"点了没反应"的一半原因)。
|
|
16362
|
+
if (active) {
|
|
16363
|
+
const activeName = (list.find((x) => x.id === active) || {}).name || active;
|
|
16364
|
+
children.push(React.createElement("div", {
|
|
16365
|
+
key: "active",
|
|
16366
|
+
className: "we-picker__hint",
|
|
16367
|
+
style: { margin: "4px 0 8px", display: "flex", gap: "8px", alignItems: "center", flexWrap: "wrap" },
|
|
16368
|
+
},
|
|
16369
|
+
React.createElement("span", null, weT("当前皮肤:") + activeName),
|
|
16370
|
+
React.createElement("span", {
|
|
16371
|
+
style: { fontSize: "11px", padding: "1px 6px", borderRadius: "999px", background: "rgba(142,230,168,0.16)", color: "#8ee6a8" },
|
|
16372
|
+
}, weT("重启 DSH 生效")),
|
|
16373
|
+
));
|
|
16374
|
+
}
|
|
16375
|
+
|
|
16323
16376
|
if (error) {
|
|
16324
16377
|
children.push(React.createElement("div", {
|
|
16325
16378
|
key: "err",
|
|
@@ -16331,8 +16384,29 @@ window.__ModuleLoader__.load({
|
|
|
16331
16384
|
children.push(React.createElement("div", {
|
|
16332
16385
|
key: "note",
|
|
16333
16386
|
className: "we-picker__hint",
|
|
16334
|
-
style: {
|
|
16335
|
-
|
|
16387
|
+
style: {
|
|
16388
|
+
color: note.kind === "err" ? "#ff9a9a" : "#8ee6a8",
|
|
16389
|
+
margin: "6px 0 10px",
|
|
16390
|
+
display: "flex",
|
|
16391
|
+
gap: "10px",
|
|
16392
|
+
alignItems: "center",
|
|
16393
|
+
flexWrap: "wrap",
|
|
16394
|
+
},
|
|
16395
|
+
},
|
|
16396
|
+
React.createElement("span", null, note.text),
|
|
16397
|
+
note.reload
|
|
16398
|
+
? React.createElement("button", {
|
|
16399
|
+
type: "button",
|
|
16400
|
+
className: "we-picker__btn we-picker__btn--primary",
|
|
16401
|
+
style: { fontSize: "11.5px", padding: "3px 10px" },
|
|
16402
|
+
onClick: () => {
|
|
16403
|
+
// 只刷新这个前端页面(皮肤中心启动时重新拉 active),不必重启 DSH 进程。
|
|
16404
|
+
try { window.location.reload(); } catch { /* 极端环境刷不动就留着让用户手动重启 */ }
|
|
16405
|
+
},
|
|
16406
|
+
title: weT("重新加载界面以应用新皮肤(对话与设置都在宿主侧,不会丢)"),
|
|
16407
|
+
}, weT("立即生效"))
|
|
16408
|
+
: null,
|
|
16409
|
+
));
|
|
16336
16410
|
}
|
|
16337
16411
|
children.push(React.createElement("div", {
|
|
16338
16412
|
key: "search",
|
|
@@ -17332,6 +17406,9 @@ window.__ModuleLoader__.load({
|
|
|
17332
17406
|
// 两页,外加壁纸页。
|
|
17333
17407
|
const QP_TABS = [
|
|
17334
17408
|
{ id: "wallpaper", get label() { return weT("壁纸"); } },
|
|
17409
|
+
// 「皮肤包」与设置页那个页签是**同一个组件**(SkinsTabPanel):首页这里只是把它挂进抽屉,
|
|
17410
|
+
// 不另写一份列表逻辑 —— 两份实现迟早会漂移。
|
|
17411
|
+
{ id: "skins", get label() { return weT("皮肤包"); } },
|
|
17335
17412
|
{ id: "appearance", get label() { return weT("外观"); } },
|
|
17336
17413
|
{ id: "playback", get label() { return weT("播放"); } },
|
|
17337
17414
|
];
|
|
@@ -17977,11 +18054,17 @@ window.__ModuleLoader__.load({
|
|
|
17977
18054
|
target: "playback",
|
|
17978
18055
|
title: weT("在设置页打开「播放」页签 —— 出图来源 / 实时帧 / 帧率上限在那里"),
|
|
17979
18056
|
}
|
|
17980
|
-
:
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
|
|
18057
|
+
: qpTab === "skins"
|
|
18058
|
+
? {
|
|
18059
|
+
label: weT("皮肤包设置 ›"),
|
|
18060
|
+
target: "skins",
|
|
18061
|
+
title: weT("在设置页打开「皮肤包」页签 —— 下载 / 切换 / 删除皮肤包"),
|
|
18062
|
+
}
|
|
18063
|
+
: {
|
|
18064
|
+
label: weT("壁纸引擎设置 ›"),
|
|
18065
|
+
target: "",
|
|
18066
|
+
title: weT("打开设置对话框的「壁纸引擎」分区(外观 / 播放 / 系统与全部配置)"),
|
|
18067
|
+
};
|
|
17985
18068
|
|
|
17986
18069
|
return React.createElement("div", { className: "we-qp we-qp--" + dock },
|
|
17987
18070
|
qpRenderCurrent(sel, current, playbackLive),
|
|
@@ -18011,7 +18094,10 @@ window.__ModuleLoader__.load({
|
|
|
18011
18094
|
})
|
|
18012
18095
|
: qpTab === "playback"
|
|
18013
18096
|
? qpRenderPlaybackPane(sel, switchQpTab)
|
|
18014
|
-
|
|
18097
|
+
// 皮肤包:直接挂设置页那个同一个组件(它自己管列表/下载/激活状态)。
|
|
18098
|
+
: qpTab === "skins"
|
|
18099
|
+
? React.createElement(SkinsTabPanel, null)
|
|
18100
|
+
: null),
|
|
18015
18101
|
!(qpTab === "wallpaper" && userPropsPanelOpen() && propsAvailable) && qpTab === "wallpaper" && React.createElement(React.Fragment, null,
|
|
18016
18102
|
// ── 壁纸列表(搜索 + 视图切换 + 快切)──
|
|
18017
18103
|
// 库还没回来 / 扫描失败:**只有这一页**给一句话 —— 外观 / 播放两页不依赖库,
|