dsh-pighub 0.9.69 → 0.9.71
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 +37 -17
- package/lib/index.js +1 -1
- package/package.json +1 -1
- package/test/themes.test.mjs +25 -0
package/lib/client.js
CHANGED
|
@@ -131,6 +131,18 @@ window.__ModuleLoader__.load({
|
|
|
131
131
|
'.pighub-themelist{max-height:0;opacity:0;overflow:hidden;transition:max-height .2s ease,opacity .2s ease,margin .2s ease;margin:0}',
|
|
132
132
|
'.pighub-themelist.is-open{max-height:240px;opacity:1;margin:4px 0}',
|
|
133
133
|
'.pighub-themerow{display:flex;align-items:center;justify-content:space-between;gap:6px;margin:3px 0}',
|
|
134
|
+
'.pighub-themebtn{flex:1;text-align:left;font-size:11px;padding:5px 9px;border-radius:8px;cursor:pointer;',
|
|
135
|
+
'border:1px solid color-mix(in oklab,var(--dsw-alias-border-secondary,#3a3a3a) 80%,transparent);',
|
|
136
|
+
'background:var(--dsw-alias-bg-secondary,#232323);color:var(--dsw-alias-label-primary,#e6e6e6);} ',
|
|
137
|
+
'.pighub-themebtn:hover:not(:disabled){border-color:var(--dsw-alias-label-secondary,#7a7a7a)}',
|
|
138
|
+
'.pighub-themebtn.is-selected{border-color:#7fbf5a;background:color-mix(in oklab,#7fbf5a 18%,transparent);',
|
|
139
|
+
'color:#cfe8bd;font-weight:600;cursor:default}',
|
|
140
|
+
'.pighub-themebtn:disabled{opacity:1}',
|
|
141
|
+
'.pighub-themedel{font-size:11px;padding:4px 9px;border-radius:8px;cursor:pointer;color:#f0b7b7;',
|
|
142
|
+
'background:transparent;border:1px solid color-mix(in oklab,#7a3b3b 70%,transparent)}',
|
|
143
|
+
'.pighub-themedel:hover:not(:disabled){background:color-mix(in oklab,#7a3b3b 22%,transparent)}',
|
|
144
|
+
'.pighub-themedel:disabled{color:var(--dsw-alias-label-tertiary,#6b7280);border-color:transparent;',
|
|
145
|
+
'background:transparent;cursor:not-allowed;opacity:.55}',
|
|
134
146
|
'.pighub-themedel{font-size:11px;padding:2px 8px;border-radius:999px;cursor:pointer;color:#f0b7b7;',
|
|
135
147
|
'background:transparent;border:1px solid color-mix(in oklab,#7a3b3b 70%,transparent)}',
|
|
136
148
|
'.pighub-themedel.is-disabled{color:var(--dsw-alias-text-tertiary,#6b7280);border-color:transparent;cursor:default}',
|
|
@@ -822,7 +834,11 @@ window.__ModuleLoader__.load({
|
|
|
822
834
|
function Meadow(props) {
|
|
823
835
|
const theme = (props && props.theme) || CLASSIC_THEME_FALLBACK;
|
|
824
836
|
const geo = theme.geometry || {};
|
|
825
|
-
|
|
837
|
+
/* 草坪**强制使用标准尺寸**(用户口径 2026-11-14:「草坪要强制拉伸到标准尺寸」):
|
|
838
|
+
* 主题只应该换「草地长什么样」,不该改草坪的占地范围——否则换了主题草坪会缩进/错位,
|
|
839
|
+
* 与围栏对不上。所以这里忽略 theme.geometry.grass,一律用 classic 的 PEN_GRASS;
|
|
840
|
+
* 主题若要自带草地贴图,就拉伸铺满这个标准矩形(见下面的 grassImage)。 */
|
|
841
|
+
const G = PEN_GRASS;
|
|
826
842
|
const I = themeRect(geo.inner, PEN_INNER);
|
|
827
843
|
const gw = G.x1 - G.x0;
|
|
828
844
|
const gh = G.y1 - G.y0;
|
|
@@ -1743,24 +1759,28 @@ window.__ModuleLoader__.load({
|
|
|
1743
1759
|
}, themeMenuOpen ? '收起' : '更换…'),
|
|
1744
1760
|
),
|
|
1745
1761
|
h('div', { className: 'pighub-themelist' + (themeMenuOpen ? ' is-open' : '') },
|
|
1746
|
-
((data && data.themes) || [{ name: 'classic', title: 'classic(默认)' }]).map((item) =>
|
|
1747
|
-
|
|
1762
|
+
((data && data.themes) || [{ name: 'classic', title: 'classic(默认)' }]).map((item) => {
|
|
1763
|
+
const selected = activeTheme.name === item.name;
|
|
1764
|
+
const builtin = item.name === 'classic';
|
|
1765
|
+
return h('div', { key: 'theme-row-' + item.name, className: 'pighub-themerow' },
|
|
1766
|
+
/* 三态:选中(is-selected + aria-pressed) / 可用 / 不可用 —— 用真按钮语义,不用 span 假装按钮 */
|
|
1748
1767
|
h('button', {
|
|
1749
1768
|
type: 'button',
|
|
1750
|
-
className: 'pighub-
|
|
1751
|
-
'aria-pressed':
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1769
|
+
className: 'pighub-themebtn' + (selected ? ' is-selected' : ''),
|
|
1770
|
+
'aria-pressed': selected ? 'true' : 'false',
|
|
1771
|
+
disabled: selected,
|
|
1772
|
+
title: selected ? '当前正在使用' : '切换到「' + (item.title || item.name) + '」',
|
|
1773
|
+
onClick: () => { if (!selected) STORE.setTheme(item.name); },
|
|
1774
|
+
}, (selected ? '● ' : '○ ') + (item.title || item.name)),
|
|
1775
|
+
h('button', {
|
|
1776
|
+
type: 'button',
|
|
1777
|
+
className: 'pighub-themedel',
|
|
1778
|
+
disabled: builtin,
|
|
1779
|
+
title: builtin ? '内置主题不可删除' : '删除「' + (item.title || item.name) + '」',
|
|
1780
|
+
onClick: () => { if (!builtin) STORE.removeTheme(item.name); },
|
|
1781
|
+
}, builtin ? '内置' : '删除'),
|
|
1782
|
+
);
|
|
1783
|
+
}),
|
|
1764
1784
|
),
|
|
1765
1785
|
/* 「更换主题包」:用隐藏的 <input type=file accept=.zip> 唤起系统文件选择器(Electron 里就是原生对话框),
|
|
1766
1786
|
* 选中的 zip 原样 POST 到 /pighub/theme-import;宿主校验并解压后**自动切到新主题**,这里只负责刷新快照。 */
|
package/lib/index.js
CHANGED
|
@@ -44,7 +44,7 @@ export const inject = ['tools'];
|
|
|
44
44
|
import { startDesktopPet, stopDesktopPet, syncDesktopPet, desktopPetState, sayOnDesktop, reclaimStaleSessions } from './desktop-pet.js';
|
|
45
45
|
|
|
46
46
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
47
|
-
const VERSION = '0.9.
|
|
47
|
+
const VERSION = '0.9.71';
|
|
48
48
|
/** 桌面桌宠的精灵边长(CSS px 基准,= manifest 里 sizeRatio 的中位数)。 */
|
|
49
49
|
const DESKTOP_PET_SIZE = 96;
|
|
50
50
|
/** 全局尺寸系数(用户口径 2026-11-13:「整体猪猪缩小到 75% 大小」)。三层一起乘。 */
|
package/package.json
CHANGED
package/test/themes.test.mjs
CHANGED
|
@@ -31,5 +31,30 @@ check('normaliseTheme 对坏 geometry 逐字段回落 classic', () => {
|
|
|
31
31
|
assert.deepEqual(t2.geometry.inner, [1, 2, 3, 4]);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
// ---- 目录版准入(用户口径 2026-11-14:非法主题不进列表)----
|
|
35
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
36
|
+
import { tmpdir } from 'node:os';
|
|
37
|
+
import { join as pjoin } from 'node:path';
|
|
38
|
+
import { validateThemeDir } from '../lib/themes.js';
|
|
39
|
+
|
|
40
|
+
check('坏 JSON 的主题目录 → 判为非法(不进列表)', () => {
|
|
41
|
+
const dir = mkdtempSync(pjoin(tmpdir(), 'pgtheme-'));
|
|
42
|
+
writeFileSync(pjoin(dir, 'theme.json'), '{ not json');
|
|
43
|
+
const r = validateThemeDir(dir, 'x');
|
|
44
|
+
rmSync(dir, { recursive: true, force: true });
|
|
45
|
+
assert.equal(r.ok, false);
|
|
46
|
+
assert.equal(r.reason, 'theme_json_invalid');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
check('合法主题目录 → 通过', () => {
|
|
50
|
+
const dir = mkdtempSync(pjoin(tmpdir(), 'pgtheme-'));
|
|
51
|
+
writeFileSync(pjoin(dir, 'theme.json'), JSON.stringify({ name: 'ok', geometry: { grass: [10, 20, 90, 95] } }));
|
|
52
|
+
writeFileSync(pjoin(dir, 'fence.png'), Buffer.from([137, 80, 78, 71]));
|
|
53
|
+
const r = validateThemeDir(dir, 'ok');
|
|
54
|
+
rmSync(dir, { recursive: true, force: true });
|
|
55
|
+
assert.equal(r.ok, true);
|
|
56
|
+
assert.equal(r.name, 'ok');
|
|
57
|
+
});
|
|
58
|
+
|
|
34
59
|
console.log('\n' + pass + ' PASS / ' + fail + ' FAIL — themes');
|
|
35
60
|
process.exit(fail === 0 ? 0 : 1);
|