dsh-folia 4.13.0 → 4.13.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/cordis.patch.yml CHANGED
@@ -1,23 +1,24 @@
1
1
  # dsh-plugin-folia bundle patch.
2
2
  #
3
- # ⚠️ 这里**只有一条** row。皮肤中心由桌面端/市场自己那条 row 负责,我们不再插第二条(见下)。
3
+ # 两条 row:我们自己的 `folia` + 随身携带的皮肤中心 `skin-center`。
4
4
  #
5
- # ── 为什么不再声明 skin-center 的 row 与依赖(2026-10-30 实测)─────────────────
6
- # 我们一厢情愿地"随身携带"皮肤中心(`dependencies` + 第二条 insert row),结果与桌面端自己
7
- # 管理的同一条 row 撞了:`.dsh-market/log.ndjson` 每次启动都会写
5
+ # ── 皮肤中心为什么"带过一次、去掉、又带回来"(两次都是实测结论)──────────────
6
+ # 1) 4.12.x:带着它(dependencies + row)→ 0.4.12 的 engines 要求 `dsh >= 0.2.1-rc.3`,
7
+ # 而当时桌面端是 0.2.1-rc.2 ⇒ 市场把这条行**保持为 off**:
8
+ # ".dsh-market/log.ndjson": "plugin kept off: @linxin666/dsh-client-ui-skin-center"
9
+ # `/api/skin-center/v2/*` 整族变成路由 miss(带会话实测 404),页签点「应用」必失败。
10
+ # 当时把依赖钉到 0.4.8 只在一两次启动里有效,桌面端会把 0.4.12 投影回来 ⇒ 又 off。
11
+ # 2) 现在:桌面端基线升到 0.2.1-rc.3+(本机实测 dsh=0.2.1-rc.3),engines 满足 ⇒ 可以正常携带。
12
+ # 携带的意义:用户装 dsh-folia 就同时得到"皮肤渲染方",不必再自己去市场找。
8
13
  #
9
- # "@linxin666/dsh-client-ui-skin-center -> off: fiber=true"
10
- # "plugin kept off: @linxin666/dsh-client-ui-skin-center"
11
- #
12
- # 也就是**它被关掉了**,于是 `/api/skin-center/v2/*` 整族变成路由 miss(带会话实测:404),
13
- # 「助手皮肤」页签里点「应用」必然失败。把依赖钉到 0.4.8 只在那一次启动里生效,桌面端重启后
14
- # 会把 0.4.12 投影回来(engines 要求 `dsh >= 0.2.1-rc.3`,而当前桌面端是 rc.2)→ 又被关掉。
15
- # 直接改 profile 的 package.json / overrides 会让桌面端"Profile 恢复未完成"进安全模式 —— 那条路
16
- # 我们已经走过一次并回滚,不再重复。
17
- #
18
- # 结论:**不由我们替用户装这个插件**。它该由用户在自己的插件市场/桌面端里装(那里管版本与引擎
19
- # 匹配),我们的页签只做两件事:把站点 zip 解到 `$DSH_HOME/skins`,以及在它确实在跑时写选择。
20
- # 判据见 test/verify-skin-center-bundle.mjs:**只允许一条 row**,且不得再声明为依赖。
14
+ # ── 仍然保留的纪律 ─────────────────────────────────────────────────────────
15
+ # · 重复挂载是安全的(实测):宿主侧 apply 走 `mountOnce`,客户端 slots.register 包 try/catch
16
+ # ⇒ 用户市场里再装一份也不会打起来(第二次是空操作)。
17
+ # · 若某台机器 dsh 低于 0.4.12 的要求:市场会 keep off,我们的页签会如实显示
18
+ # "皮肤中心未运行",壁纸/桌宠/开机动画/玻璃**完全不受影响**(探测四态 + 应用禁用)。
19
+ # · row id 不得以 `folia-` 开头:`lib/subpackage-boot.js#subpackageSpecifiers` 会把
20
+ # 「id 以 folia- 开头的行」当成我们自己的子包去仓库解析(解析不到就抛)。
21
+ # · 依赖版本**精确**(不带 ^):0.4.9+ 的 engines 会随上游再抬,我们不能让用户被动中招。
21
22
  #
22
23
  # A patch replaces the targeted row's whole `config`, so only additive `insert`
23
24
  # rows appear here (we never override an existing shipped row).
@@ -25,3 +26,5 @@
25
26
  - insert:
26
27
  - id: folia
27
28
  name: 'dsh-folia'
29
+ - id: skin-center
30
+ name: '@linxin666/dsh-client-ui-skin-center'
package/lib/client.js CHANGED
@@ -18340,7 +18340,12 @@ window.__ModuleLoader__.load({
18340
18340
  }
18341
18341
  setState(doc);
18342
18342
  if (doc.siteError && doc.siteError !== "site-off") {
18343
- setNote({ ok: false, text: weT("站点清单读不到:{msg}", { msg: String(doc.siteError) }) });
18343
+ // `site-locked` = 站点整站上锁(登录页 + {"code":"site_locked"}),不是网络/插件问题。
18344
+ // 给它一句能照做的说明,而不是甩一个 http-401(实测:这个错误码让人误判成插件坏了)。
18345
+ const msg = doc.siteError === "site-locked"
18346
+ ? weT("站点已锁定:只对已登录的管理员开放(需站点侧放行 GET /api/public/wallpapers)")
18347
+ : String(doc.siteError);
18348
+ setNote({ ok: false, text: weT("站点清单读不到:{msg}", { msg }) });
18344
18349
  }
18345
18350
  } else {
18346
18351
  setNote({ ok: false, text: weT("读取失败:{msg}", { msg: (doc && doc.error) || "unknown" }) });
@@ -18468,11 +18473,19 @@ window.__ModuleLoader__.load({
18468
18473
  // 不在 → 明说它是个**独立插件**(不在 dsh-web-all 里),给一条可复制的安装命令
18469
18474
  // unknown(探测失败)→ 保守地按"在"讲,不吓唬用户
18470
18475
  const skinCenter = (state && state.skinCenter) || "unknown";
18476
+ // 用户在插件市场里手动禁用了它 —— 这是最准确的原因,优先于所有 http 状态码推测。
18477
+ const marketDisabled = Boolean(state && state.skinCenterDisabled);
18471
18478
  // `present` 是**唯一**允许点「应用」的状态:只有真的拿到 catalog JSON 才算它在跑。
18472
18479
  // `absent`=路由不存在(插件没装/未启用);`auth-gated`=鉴权在路由前面挡住(无法判定);
18473
18480
  // `unknown`=探测失败。后三种都如实告诉用户"现在点应用不会成功",而不是让他点了看 404。
18474
18481
  const canApply = skinCenter === "present";
18475
- if (skinCenter === "absent") {
18482
+ if (marketDisabled) {
18483
+ children.push(React.createElement("div", {
18484
+ key: "hint-disabled",
18485
+ className: "we-picker__hint",
18486
+ style: { margin: "6px 0 4px", color: "#ffd08a", lineHeight: "1.6" },
18487
+ }, weT("皮肤中心被**你在插件市场里禁用了**(市场记录里它在 disabled 列表里)。皮肤的实际渲染方就是它,禁用它 ⇒ 这里只能装/卸皮肤包,不能应用。到插件市场把它重新启用即可(dsh-folia 已把它作为依赖随身携带,不需要另装)。")));
18488
+ } else if (skinCenter === "absent") {
18476
18489
  children.push(React.createElement("div", {
18477
18490
  key: "hint-absent",
18478
18491
  className: "we-picker__hint",
@@ -83,6 +83,23 @@ function siteBase() {
83
83
  * 判据用**它自己的 catalog 路由**:该路由不需要鉴权(实测 200),404 就是没装。
84
84
  */
85
85
  const skinCenterProbe = { at: 0, state: 'unknown', detail: '' };
86
+
87
+ /**
88
+ * 皮肤中心是不是被**用户自己在插件市场里禁用了**。
89
+ *
90
+ * 为什么要单独读:它被禁用时 DSH 的鉴权中间件先于路由回答 401,和"需要会话"长得一模一样,
91
+ * 于是页签只能写出"浏览器侧也被鉴权挡住"这种既对又没用的话(实测被用户当成插件故障)。
92
+ * 市场的 `.dsh-market/state.json` 里有 `disabled` 数组 —— 读它是**只读事实**,比猜准得多。
93
+ */
94
+ function readMarketDisabled() {
95
+ try {
96
+ const p = join(dshHome(), 'profiles', 'web', '.dsh-market', 'state.json');
97
+ const j = JSON.parse(readFileSync(p, 'utf8'));
98
+ const list = Array.isArray(j && j.disabled) ? j.disabled : [];
99
+ return { known: true, skinCenterDisabled: list.includes('@linxin666/dsh-client-ui-skin-center') };
100
+ } catch { return { known: false, skinCenterDisabled: false }; }
101
+ }
102
+
86
103
  async function probeSkinCenter(hostHeader, force) {
87
104
  const now = Date.now();
88
105
  if (!force && skinCenterProbe.at && now - skinCenterProbe.at < 30000) return skinCenterProbe.state;
@@ -144,11 +161,26 @@ async function fetchSiteSkins(force) {
144
161
  mime: String(it.mime || ''),
145
162
  url: String(it.url || ''),
146
163
  thumbUrl: it.thumbUrl ? String(it.thumbUrl) : '',
147
- tags: (() => { try { return JSON.parse(it.tags || '[]'); } catch { return []; } })(),
164
+ // 站点现在把 tags 直接给**数组**(旧版给的是字符串化 JSON)。两种都收:
165
+ // 只认字符串会让「动态」这类标记静默丢失(实测:线上返回 ["皮肤","catppuccin",…])。
166
+ tags: (() => {
167
+ const raw = it.tags;
168
+ if (Array.isArray(raw)) return raw.map((t) => String(t));
169
+ try { const parsed = JSON.parse(raw || '[]'); return Array.isArray(parsed) ? parsed.map((t) => String(t)) : []; } catch { return []; }
170
+ })(),
148
171
  }));
149
172
  siteCache.error = null;
150
173
  } catch (e) {
151
- siteCache.error = (e && e.message) || 'fetch-failed';
174
+ // 把站点的**真实原因**带出来:站点整站上锁时只回 401 + `{"error":{"code":"site_locked"}}`,
175
+ // 只显示 "http-401" 会让人以为是插件/网络问题(实测就栽在这条上)。
176
+ const msg = (e && e.message) || 'fetch-failed';
177
+ const status = /^http-(\d+)$/.exec(msg);
178
+ if (status) {
179
+ const code = Number(status[1]);
180
+ siteCache.error = (code === 401 || code === 403) ? 'site-locked' : msg;
181
+ } else {
182
+ siteCache.error = msg;
183
+ }
152
184
  siteCache.items = siteCache.items || [];
153
185
  }
154
186
  siteCache.at = now;
@@ -320,16 +352,19 @@ export function registerSkinsRoutes(webServer, c) {
320
352
  installedKeys.add(normSkinId(s.id));
321
353
  installedKeys.add(normSkinId(s.dirId));
322
354
  }
355
+ const market = readMarketDisabled();
323
356
  sendJson(res, 200, {
324
357
  ok: true,
325
358
  skinCenter,
359
+ // 用户在插件市场里**手动禁用**它 ⇒ 这是我们能给出的最准确的原因(比 401 含糊其辞好)
360
+ skinCenterDisabled: market.skinCenterDisabled,
361
+ skinCenterMarketKnown: market.known,
326
362
  skinCenterDetail: skinCenterProbe.detail || '',
327
- // 皮肤中心被"保持为 off"时(peer 版本不匹配等),用户需要知道去改什么。
328
- // 这里不动它,只把"它为什么可能不在"说清楚:我们钉的是 0.4.8(peer dsh >= 0.2.1-rc.2),
329
- // 0.4.9+ 要求 rc.3,装了更高版本就会被市场关掉。
363
+ // 版本线索:我们随身携带的是 0.4.12(engines 要求 dsh >= 0.2.1-rc.3)。
364
+ // 低于该内核的机器会被市场 keep off —— 页签据此告诉用户"要么升级桌面端、要么别指望它"。
330
365
  skinCenterHint: skinCenter === 'present'
331
366
  ? ''
332
- : 'skin-center-0.4.8',
367
+ : 'skin-center-0.4.12',
333
368
  siteBase: siteBase(),
334
369
  siteError: site.error,
335
370
  installed,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-folia",
3
- "version": "4.13.0",
3
+ "version": "4.13.1",
4
4
  "description": "Folia 壁纸引擎:把本机 Wallpaper Engine 壁纸搬进 DSH 界面(场景实时渲染 / 视频 / 网页),内置液态玻璃与 Folia 吉祥物,并可从自建站点拉取壁纸。单包形态(组件已合并)。",
5
5
  "type": "module",
6
6
  "engines": {
@@ -193,6 +193,7 @@
193
193
  }
194
194
  },
195
195
  "dependencies": {
196
+ "@linxin666/dsh-client-ui-skin-center": "0.4.12",
196
197
  "webwallgl": "^3.0.0",
197
198
  "x11": "^4.3.1"
198
199
  },