dsh-folia 4.15.3 → 4.15.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 CHANGED
@@ -18504,7 +18504,7 @@ window.__ModuleLoader__.load({
18504
18504
  className: "we-picker__btn", type: "button",
18505
18505
  disabled: Boolean(busy),
18506
18506
  onClick: () => load(true),
18507
- }, weT("刷新")),
18507
+ }, busyIsStructural ? weT("下载中…(可继续切换皮肤)") : weT("刷新")),
18508
18508
  ));
18509
18509
 
18510
18510
  // 皮肤中心在不在,决定这段提示说什么:
@@ -18568,6 +18568,14 @@ window.__ModuleLoader__.load({
18568
18568
  },
18569
18569
  }, note ? note.text : "\u00a0"));
18570
18570
 
18571
+ // ⚠️ 「正在下载/安装」**不能**把整块面板锁住:实测用户点「安装」后想切到另一套皮肤,
18572
+ // 结果所有「应用」都灰着,必须等 zip 下完 —— 下载是长任务,切换应该与它互不阻塞。
18573
+ // 所以把 busy 拆成两条互不相干的通道:
18574
+ // · 结构操作(install / remove / repair):改动磁盘目录,串行,期间只锁**结构按钮**
18575
+ // · 切换(activate):只写 active,幂等且"最后动作优先",期间只锁**该卡片的「应用」**
18576
+ const busyIsStructural = /^(install|remove|repair):/.test(String(busy || ""));
18577
+ const busyIsActivating = /^activate:/.test(String(busy || ""));
18578
+
18571
18579
  const installed = (state && state.installed) || [];
18572
18580
  const activeId = (state && state.active) || "";
18573
18581
  // 「皮肤中心记着哪套」≠「屏上现在是哪套」:壁纸在台上时皮肤会 withhold 自己,
@@ -18670,7 +18678,7 @@ window.__ModuleLoader__.load({
18670
18678
  ? React.createElement("span", { style: { ...SKIN_STYLE.badge, background: "rgba(60,160,90,0.55)" } }, weT("使用中"))
18671
18679
  : React.createElement("button", {
18672
18680
  className: "we-picker__btn", type: "button",
18673
- disabled: Boolean(busy) || !canApply || notListed,
18681
+ disabled: (busyIsActivating && busyThis) || !canApply || notListed,
18674
18682
  title: notListed ? notListedWhy : (applyBlockedReason || undefined),
18675
18683
  onClick: () => act("activate", { id: s.id }, s.name),
18676
18684
  }, busyThis ? weT("切换中…") : weT("应用")),
@@ -18679,14 +18687,14 @@ window.__ModuleLoader__.load({
18679
18687
  notListed
18680
18688
  ? React.createElement("button", {
18681
18689
  className: "we-picker__btn", type: "button",
18682
- disabled: Boolean(busy),
18690
+ disabled: busyIsStructural,
18683
18691
  title: notListedWhy,
18684
18692
  onClick: () => act("repair", { id: s.dirId || s.id }, s.name),
18685
18693
  }, busy === "repair:" + (s.dirId || s.id) ? weT("修复中…") : weT("修复清单"))
18686
18694
  : null,
18687
18695
  React.createElement("button", {
18688
18696
  className: "we-picker__btn", type: "button",
18689
- disabled: Boolean(busy) || isActive,
18697
+ disabled: busyIsStructural || isActive,
18690
18698
  title: isActive ? weT("正在使用,先切到别的再卸") : undefined,
18691
18699
  onClick: () => act("remove", { id: s.id }, s.name),
18692
18700
  }, busy === "remove:" + s.id ? weT("卸载中…") : weT("卸载")),
@@ -18727,7 +18735,7 @@ window.__ModuleLoader__.load({
18727
18735
  : React.createElement("button", {
18728
18736
  key: "apply",
18729
18737
  className: "we-picker__btn", type: "button",
18730
- disabled: Boolean(busy) || !canApply,
18738
+ disabled: (busyIsActivating && busy === "activate:" + localId) || !canApply,
18731
18739
  title: applyBlockedReason || undefined,
18732
18740
  onClick: () => act("activate", { id: localId }, s.title),
18733
18741
  }, busy === "activate:" + localId ? weT("切换中…") : weT("应用")),
@@ -18735,7 +18743,7 @@ window.__ModuleLoader__.load({
18735
18743
  ]
18736
18744
  : React.createElement("button", {
18737
18745
  className: "we-picker__btn", type: "button",
18738
- disabled: Boolean(busy),
18746
+ disabled: busyIsStructural || busy === "install:" + s.id,
18739
18747
  title: skinCenter === "absent" ? weT("先装皮肤中心,否则皮肤装好也没法启用") : undefined,
18740
18748
  onClick: () => act("install", { id: s.id, url: s.url }, s.title),
18741
18749
  }, busyThis ? weT("安装中…") : weT("安装")),
package/lib/features.js CHANGED
@@ -37,7 +37,7 @@ export const FEATURES = [
37
37
  role: '本机/上传/站点三源合并成壁纸库;着色、图层、播放与轮换由客户端接管',
38
38
  host: [
39
39
  'lib/routes/inventory.js',
40
- 'lib/routes/site-media.js',
40
+ 'lib/routes/site-media.js',
41
41
  'lib/routes/media-bytes.js',
42
42
  'lib/routes/media-derived.js',
43
43
  'lib/routes/scene-frame.js',
package/lib/index.js CHANGED
@@ -86,7 +86,7 @@ import { registerOcclusionRoutes } from './routes/occlusion.js';
86
86
  import { registerSceneFrameRoutes } from './routes/scene-frame.js';
87
87
  import { registerMediaDerivedRoutes } from './routes/media-derived.js';
88
88
  import { registerMediaBytesRoutes } from './routes/media-bytes.js';
89
- import { registerSiteMediaRoutes } from './routes/site-media.js';
89
+ import { registerSiteMediaRoutes } from './routes/site-media.js';
90
90
  import { registerWeAssetsRoutes } from './routes/we-assets.js';
91
91
  import { registerSceneMediaRoutes } from './routes/scene-media.js';
92
92
  import { registerSceneServeRoutes } from './routes/scene-serve.js';
@@ -330,7 +330,9 @@ export function apply(ctx) {
330
330
  // 为什么单开一族而不是塞进 /media:那条是**本机字节直出**(token → 磁盘),
331
331
  // 这条是"上游 → 磁盘 → 客户端"的三方转发,失败语义完全不同(一切失败 302 直连)。
332
332
  // ⚠️ 必须早于任何 `/site-*` 前缀族:本路由是 exact,不受顺序影响,但保持就近声明。
333
- registerSiteMediaRoutes(webServer, { disposers, base: BASE, serveFile, log });
333
+ registerSiteMediaRoutes(webServer, { disposers, base: BASE, serveFile, log });
334
+
335
+
334
336
 
335
337
  // 3c-3b/3c-5. 场景帧服务族路由(实时抓帧缓存 / 自定义画面)→ lib/routes/scene-frame.js。
336
338
  // 三条注册与它们的依赖都在那个文件里;这里只声明它的依赖。
@@ -92,7 +92,7 @@ export const FEATURE_ROUTE_FAMILIES = [
92
92
  export const INLINE_ROUTE_FAMILIES = [
93
93
  // 每条写「族 id + 门面里的注册函数名」:两者**不总同形**(presets → registerGlassPresetsRoutes),
94
94
  // 靠名字猜会在守卫里制造假红。迁移一个族 = 在 FEATURE_ROUTE_FAMILIES 加一条 + 删这里一行。
95
- { id: 'site-media', fn: 'registerSiteMediaRoutes' },
95
+ { id: 'site-media', fn: 'registerSiteMediaRoutes' },
96
96
  { id: 'media-bytes', fn: 'registerMediaBytesRoutes' },
97
97
  { id: 'media-derived', fn: 'registerMediaDerivedRoutes' },
98
98
  { id: 'scene-frame', fn: 'registerSceneFrameRoutes' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-folia",
3
- "version": "4.15.3",
3
+ "version": "4.15.4",
4
4
  "description": "Folia 壁纸引擎:把本机 Wallpaper Engine 壁纸搬进 DSH 界面(场景实时渲染 / 视频 / 网页),内置液态玻璃与 Folia 吉祥物,并可从自建站点拉取壁纸。单包形态(组件已合并)。",
5
5
  "type": "module",
6
6
  "engines": {
@@ -42,6 +42,7 @@
42
42
  "files": [
43
43
  "icon.png",
44
44
  "lib/index.js",
45
+ "lib/client.js",
45
46
  "lib/host-boot.js",
46
47
  "lib/log.js",
47
48
  "lib/notice.js",
@@ -57,7 +58,6 @@
57
58
  "lib/glass-presets/",
58
59
  "lib/about/",
59
60
  "lib/component-visibility.js",
60
- "lib/client.js",
61
61
  "lib/http-body.js",
62
62
  "lib/json-response.js",
63
63
  "lib/pkg-read.js",