dsh-folia 4.12.2 → 4.12.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.
Files changed (2) hide show
  1. package/lib/client.js +45 -17
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -18318,13 +18318,13 @@ window.__ModuleLoader__.load({
18318
18318
  const doc = (resp && resp.data) || null;
18319
18319
  if (resp && resp.ok && doc && doc.ok) {
18320
18320
  // 读"当前在用哪套皮肤"必须**由浏览器发**,不能走宿主代理:
18321
- // `/api/skin-center/v2/*` 的读写被 DSH 自己的会话鉴权挡着,宿主 fetch 没有 cookie
18322
- // ⇒ 代理拿到 401(实测报错「操作失败:skin-center-401」)。
18323
- // 但**不许裸 fetch**(src/api-client.js 的不变量:业务代码零裸 fetch)——
18324
- // apiUrl() 对带 scheme 的地址原样放行,而 location.origin 是同源 ⇒ 照旧带会话。
18321
+ // `/api/skin-center/v2/*` 的读写被 DSH 自己的会话鉴权挡着,宿主 fetch 没有 cookie ⇒ 401。
18322
+ // 路径用**相对 `/api/...`**:不要拼 `location.origin` —— 我们跑在宿主页面里,origin 不一定
18323
+ // 等于宿主 HTTP API 的源;拼错会得到一个不存在的地址,而它的 404 还会被误读成业务 404。
18324
+ // api-client 对 `/api/**` 原样放行(不补 /folia 前缀)。
18325
18325
  if (doc.skinCenter === "present") {
18326
18326
  try {
18327
- const a = await apiJson(location.origin + "/api/skin-center/v2/active", { parse: "always" });
18327
+ const a = await apiJson("/api/skin-center/v2/active", { parse: "always" });
18328
18328
  if (a && a.ok) doc.active = (a.data && a.data.active) || "";
18329
18329
  } catch { /* 读不到就显示"无使用中" */ }
18330
18330
  }
@@ -18349,24 +18349,28 @@ window.__ModuleLoader__.load({
18349
18349
  if (kind === "activate") setBusy("activate:" + ((payload && payload.id) || ""));
18350
18350
  setNote(null);
18351
18351
  try {
18352
- // 切换皮肤**由浏览器直接写**皮肤中心自己的端点(同源请求自带会话);
18353
- // 走宿主代理会 401 —— DSH 对 `/api/skin-center/v2/*` 的读写都做会话鉴权,宿主 fetch 没有 cookie。
18354
18352
  if (kind === "activate") {
18355
18353
  const wantId = (payload && payload.id) || null;
18356
- // 只允许切到本机已装的那几套(state.installed 是权威清单)
18354
+ // ⚠️ 这里写入的必须是**皮肤中心自己认识的 id**(= skin.json 里的原始 id),
18355
+ // 不能用归一键:归一只是用来"比对",拿去当写值会变成另一个名字 ——
18356
+ // 皮肤中心的 activePostHandler 对解析不到的 id 回 404 skin-not-found(实测报错 skin-center-404)。
18357
18357
  if (wantId) {
18358
- const known = ((state && state.installed) || []).some((s) => normSkinId(s.id) === normSkinId(wantId));
18359
- if (!known) {
18358
+ const local = ((state && state.installed) || []).find((s) => s.id === wantId);
18359
+ if (!local) {
18360
18360
  setNote({ ok: false, text: weT("这个皮肤不在本机(先安装)") });
18361
18361
  return;
18362
18362
  }
18363
18363
  }
18364
18364
  // 切换皮肤**由浏览器直接写**皮肤中心自己的端点(同源、自带会话);
18365
18365
  // 走宿主代理会 401 —— DSH 对 `/api/skin-center/v2/*` 的读写都做会话鉴权,宿主 fetch 没有 cookie。
18366
- // 统一走 api-client(不裸 fetch):绝对 URL 原样放行,`location.origin` 是同源 ⇒ 会话照旧带上。
18367
- const resp = await apiPostJson(location.origin + "/api/skin-center/v2/active", { active: wantId }, { parse: "always" });
18366
+ // 统一走 api-client(不裸 fetch),路径用相对 `/api/...`(不拼 location.origin ——
18367
+ // 拼错会得到一个不存在的地址,404 又会被误读成业务 404)。
18368
+ const resp = await apiPostJson("/api/skin-center/v2/active", { active: wantId }, { parse: "always" });
18368
18369
  if (!(resp && resp.ok)) {
18369
- setNote({ ok: false, text: weT("操作失败:{code}", { code: "skin-center-" + ((resp && resp.status) || 0) }) });
18370
+ // 把响应体里的 error 一起显示:`skin-not-found`(它的 catalog 不收)与"路径不对"
18371
+ // 从状态码上看都是 404,只有 body 能分开(实测踩过:把 URL 拼错当成了业务 404)。
18372
+ const detail = (resp && resp.data && resp.data.error) ? ":" + resp.data.error : "";
18373
+ setNote({ ok: false, text: weT("操作失败:{code}", { code: "skin-center-" + ((resp && resp.status) || 0) + detail }) });
18370
18374
  return;
18371
18375
  }
18372
18376
  // 两条收敛路径:① 广播皮肤中心自己监听的 `dsh-skin-applied`(立即就地切换);
@@ -18470,6 +18474,23 @@ window.__ModuleLoader__.load({
18470
18474
  const activeId = (state && state.active) || "";
18471
18475
  /** 这个 id 是不是"正在用"的那套(两边都归一后比,站点 slug 可能带 skin- 前缀)。 */
18472
18476
  const isActiveSkin = (id) => Boolean(activeId) && normSkinId(activeId) === normSkinId(id);
18477
+
18478
+ /**
18479
+ * 站点条目 → 本机已装皮肤的真实 id(皮肤中心只认这个)。
18480
+ *
18481
+ * 站点 slug 由标题生成、并为"全站唯一"可能被加 `skin-` 前缀;本机目录/皮肤中心用的是
18482
+ * skin.json 里的 id。两者可能不同(实测:站点 windows-xp-luna ↔ 本机 xp)。
18483
+ * 先按归一的 id 比,再按标题兜底;都没有就返回空串(表示"本机没有这一套")。
18484
+ */
18485
+ const localIdOf = (siteItem) => {
18486
+ const list = (state && state.installed) || [];
18487
+ const byId = list.find((x) => normSkinId(x.id) === normSkinId(siteItem.id));
18488
+ if (byId) return byId.id;
18489
+ const wantTitle = String((siteItem && siteItem.title) || "").trim();
18490
+ if (!wantTitle) return "";
18491
+ const byTitle = list.find((x) => String(x.name || "").trim() === wantTitle);
18492
+ return byTitle ? byTitle.id : "";
18493
+ };
18473
18494
  if (state) {
18474
18495
  children.push(React.createElement("div", { key: "installed-head", className: "we-picker__hint" },
18475
18496
  weT("本机已装({n})", { n: installed.length }),
@@ -18528,6 +18549,10 @@ window.__ModuleLoader__.load({
18528
18549
  ? [React.createElement("span", { key: "none", className: "we-picker__hint" }, weT("站点上还没有皮肤。"))]
18529
18550
  : site.map((s) => {
18530
18551
  const busyThis = busy === "install:" + s.id;
18552
+ // 站点条目的 slug 与本机皮肤 id **不一定相同**(站点 slug 由标题生成/为避撞名会加 skin- 前缀),
18553
+ // 而皮肤中心只认 skin.json 里的原始 id ⇒ 写之前必须换成**本机那个 id**,
18554
+ // 否则它的 activePostHandler 会回 404 skin-not-found(实测报错 skin-center-404)。
18555
+ const localId = localIdOf(s);
18531
18556
  return React.createElement("div", { key: s.id, style: SKIN_STYLE.card },
18532
18557
  s.thumbUrl
18533
18558
  ? React.createElement("div", {
@@ -18541,16 +18566,15 @@ window.__ModuleLoader__.load({
18541
18566
  s.installed
18542
18567
  // 已装的站点卡片也要能**直接应用**:用户是照着站点缩略图挑的,
18543
18568
  // 让他再滚回上面的「本机已装」区去点一次是多余的一步(实测反馈)。
18544
- // 站点 slug 与本机目录名可能差一个 `skin-` 前缀 ⇒ 用归一后的比较。
18545
18569
  ? [
18546
- isActiveSkin(s.id)
18570
+ localId && isActiveSkin(localId)
18547
18571
  ? React.createElement("span", { key: "on", style: { ...SKIN_STYLE.badge, background: "rgba(60,160,90,0.55)" } }, weT("使用中"))
18548
18572
  : React.createElement("button", {
18549
18573
  key: "apply",
18550
18574
  className: "we-picker__btn", type: "button",
18551
18575
  disabled: Boolean(busy),
18552
- onClick: () => act("activate", { id: normSkinId(s.id) }, s.title),
18553
- }, busy === "activate:" + normSkinId(s.id) ? weT("切换中…") : weT("应用")),
18576
+ onClick: () => act("activate", { id: localId }, s.title),
18577
+ }, busy === "activate:" + localId ? weT("切换中…") : weT("应用")),
18554
18578
  React.createElement("span", { key: "done", style: SKIN_STYLE.badge }, weT("已安装")),
18555
18579
  ]
18556
18580
  : React.createElement("button", {
@@ -23826,6 +23850,10 @@ window.__ModuleLoader__.load({
23826
23850
  // 应用侧封面恒 404,而同路径 curl 200)。
23827
23851
  if (/^[a-z][a-z0-9+.-]*:/i.test(p) || p.startsWith('data:') || p.startsWith('blob:')) return p;
23828
23852
  if (p.startsWith(BASE)) return p;
23853
+ // **宿主自己的 HTTP API** 挂在 `/api/**`(我们的是 `/folia/**`):这类绝对路径必须原样放行。
23854
+ // 补成 `/folia/api/...` 会得到一个不存在的路径 —— 那个 404 还会被调用方误读成"业务侧返回 404"
23855
+ // (实测:皮肤切换报 `skin-center-404`,真因是 URL 被我们拼错,不是皮肤中心说没这套皮肤)。
23856
+ if (p === '/api' || p.startsWith('/api/')) return p;
23829
23857
  return BASE + (p.startsWith('/') ? p : '/' + p);
23830
23858
  }
23831
23859
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-folia",
3
- "version": "4.12.2",
3
+ "version": "4.12.4",
4
4
  "description": "Folia 壁纸引擎:把本机 Wallpaper Engine 壁纸搬进 DSH 界面(场景实时渲染 / 视频 / 网页),内置液态玻璃与 Folia 吉祥物,并可从自建站点拉取壁纸。单包形态(组件已合并)。",
5
5
  "type": "module",
6
6
  "engines": {