dsh-life-pack 0.3.6 → 0.3.12

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.
@@ -0,0 +1,21 @@
1
+ /** 共用配置面板的公开门(**六家只 import 这一个子路径**:`dsh-life-pack/config-panel`)。
2
+ *
3
+ * 为什么需要它:卡片/行渲染/样式表/状态机分几份写(契约/取值与填值/视图/组件本体),
4
+ * 而 `package.json` 的 exports 一条子路径只能指一个文件。故设这一个门,把六家真要用的那几个名字
5
+ * 转出去;**不另开第二个出口**(没有第二消费方——将来真长出第二个用法再开)。
6
+ *
7
+ * 对外给的名字就是下面这几个,数得出来:
8
+ * ① `ConfigPanel`——面板组件本体(六家把它注册进爱生活页签槽);
9
+ * ② `Row`——一行怎么画(跨包锁要拿它当函数调);
10
+ * ③④ `ConfigControl`/`ConfigTier`——行表里两格的字面表;
11
+ * ⑤ `ConfigItem`——行表每一行的形状。
12
+ *
13
+ * **取值与填值的路径读写是内部实现**(`config-panel-value.ts`),不在这里出门:
14
+ * 它只经「取值/填值」两条被验,外面不需要自己拆一份配置取值。
15
+ *
16
+ * 本件不含实现、也不含判断,只做转出。
17
+ */
18
+ export { ConfigPanel } from './config-panel.js';
19
+ export { Row } from './config-panel-view.js';
20
+ export type { ConfigItem, ConfigControl, ConfigTier } from './config-panel-contract.js';
21
+ //# sourceMappingURL=config-panel-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-api.d.ts","sourceRoot":"","sources":["../src/config-panel-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAE7C,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,20 @@
1
+ /** 共用配置面板的公开门(**六家只 import 这一个子路径**:`dsh-life-pack/config-panel`)。
2
+ *
3
+ * 为什么需要它:卡片/行渲染/样式表/状态机分几份写(契约/取值与填值/视图/组件本体),
4
+ * 而 `package.json` 的 exports 一条子路径只能指一个文件。故设这一个门,把六家真要用的那几个名字
5
+ * 转出去;**不另开第二个出口**(没有第二消费方——将来真长出第二个用法再开)。
6
+ *
7
+ * 对外给的名字就是下面这几个,数得出来:
8
+ * ① `ConfigPanel`——面板组件本体(六家把它注册进爱生活页签槽);
9
+ * ② `Row`——一行怎么画(跨包锁要拿它当函数调);
10
+ * ③④ `ConfigControl`/`ConfigTier`——行表里两格的字面表;
11
+ * ⑤ `ConfigItem`——行表每一行的形状。
12
+ *
13
+ * **取值与填值的路径读写是内部实现**(`config-panel-value.ts`),不在这里出门:
14
+ * 它只经「取值/填值」两条被验,外面不需要自己拆一份配置取值。
15
+ *
16
+ * 本件不含实现、也不含判断,只做转出。
17
+ */
18
+ export { ConfigPanel } from './config-panel.js';
19
+ export { Row } from './config-panel-view.js';
20
+ //# sourceMappingURL=config-panel-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-api.js","sourceRoot":"","sources":["../src/config-panel-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /** 共用配置面板 · 契约:行表形状、配置面回执、几条两侧共用的常量。
2
+ *
3
+ * 为什么住这里:六个单品插件的设置页各有一份逐字相同的那套代码(卡片骨架/行渲染/样式表/
4
+ * 状态机/配置面三通电话约 3105 行)。本件是抽件之后的**唯一一处定义地**。
5
+ *
6
+ * 本件不认识任何一家能力:行表由调用方给,分支只能由行表数据与配置面回执决定,
7
+ * 里面不出现任何一个能力的名字(结构纪律「依赖方向」)。
8
+ *
9
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
10
+ */
11
+ /** 分级:常用项直接画在页面上,其余进默认收起的「高级」组。 */
12
+ export type ConfigTier = 'common' | 'advanced';
13
+ /** 控件种类:只有这四种(目录是**字符串那一档的页面形态**——取值仍是串,只是多一个选目录的入口)。 */
14
+ export type ConfigControl = 'text' | 'number' | 'switch' | 'directory';
15
+ /** 设置页的一行:一个可配置项一行,写清它在配置文件里的键、页面上那一行的中文标题、分级、
16
+ * 控件种类、只读与否与人话指引。它是页面渲染的唯一依据(各家自己的那份住各自的 `settings.ts`)。 */
17
+ export interface ConfigItem {
18
+ /** 配置文件里的键路径,一层嵌套用 `.` 连接,例 `backup.dir`。 */
19
+ readonly key: string;
20
+ /** 页面上那一行的中文标题。 */
21
+ readonly title: string;
22
+ readonly tier: ConfigTier;
23
+ readonly control: ConfigControl;
24
+ /** 一行人话:这一项管什么、留空会怎样(一到两句,不写开发期口径)。 */
25
+ readonly hint: string;
26
+ /** **只读行**:页面上不给改,值只经技能侧解析后显示;改它要编辑配置文件。
27
+ * 只读行**不参与保存**(填值时跳过它,免得把显示用的绝对路径当成配置值写回去)。 */
28
+ readonly readonly?: boolean;
29
+ /** 只读行的**显示值来源**:回执 `resolved` 组里的哪一格。标了它 ⇒ 显示技能算好的绝对路径;
30
+ * 不标 ⇒ 显示配置文件里那个值本身(数字类只读项走这一档)。 */
31
+ readonly resolveFrom?: string;
32
+ /** 可改行的**落点来源**:这一行取值空着时,页面上拿回执里的哪一格当它显示的绝对路径。
33
+ * 取法先看回执 `resolved` 组同名格,再看回执顶层同名格(如 `dataDir`)——两种写法收成同一格。 */
34
+ readonly prefillFrom?: string;
35
+ }
36
+ /** 配置面整面回执:形状与各技能侧 `<技能>.config.read` 的 data 逐字段同形。
37
+ *
38
+ * 技能侧多带的格(各家自己的那几格)不写在这里:各家在附加块里自己认(回执形状的唯一定义地
39
+ * 在各家的 `contract.ts`)。本件只认下面这几格,因此里面不出现任何一个能力的名字。 */
40
+ export interface ConfigSurfaceReply {
41
+ /** 配置文件绝对路径。 */
42
+ readonly path: string;
43
+ /** 数据目录绝对路径。 */
44
+ readonly dataDir: string;
45
+ /** 本次是不是「文件不存在、按默认值落了一份」。 */
46
+ readonly created: boolean;
47
+ /** 当前取值(文件里的缺项按默认值补)。 */
48
+ readonly values: Record<string, unknown>;
49
+ /** 一组解析后的绝对路径,给只读行显示用;**可选**:装的是旧技能时这一格缺席。 */
50
+ readonly resolved?: Readonly<Record<string, string | undefined>>;
51
+ }
52
+ /** 面板对配置面的三通电话:读整面/保存一份取值/重置为默认。三个名字各家逐字相同,收在这里一处。 */
53
+ export declare const RPC_ENDPOINT_CONFIG_GET: "config.get";
54
+ export declare const RPC_ENDPOINT_CONFIG_SAVE: "config.save";
55
+ export declare const RPC_ENDPOINT_CONFIG_RESET: "config.reset";
56
+ /** 高级组标题与副文案(六家逐字相同,收在这里一处)。 */
57
+ export declare const ADVANCED_GROUP_TITLE: "\u9AD8\u7EA7";
58
+ export declare const ADVANCED_GROUP_NOTE: "\u4E0D\u5E38\u6539\u3002\u7559\u7A7A\uFF1D\u7528\u9ED8\u8BA4\u503C\u3002";
59
+ /** 请求超时毫秒:与宿主侧 SPAWN_TIMEOUT_MS 同级,界面永不无限转圈。 */
60
+ export declare const READ_TIMEOUT_MS: 20000;
61
+ /** 复制那一枚按钮就地变「已复制」之后,多久变回「复制」(定稿 v3 第三条:1.5 秒,不弹提示)。 */
62
+ export declare const COPY_FEEDBACK_MS: 1500;
63
+ /** 宿主给「这是哪一种目录选择能力」时用的那两格原语的名字(软依赖:按名字现取,缺席即没有入口)。 */
64
+ export declare const REMOTE_DIRECTORY_PICKER: "remote.directoryPicker";
65
+ /** 宿主在「这条路不给」时回的那个码(`directory-browser-state` 的 `openRowBrowser` 只照比不认名)。 */
66
+ export declare const DIRECTORY_PICKER_REFUSED: "directory-picker/unavailable";
67
+ /** 一次配置电话的失败格。 */
68
+ export interface RpcErrorFace {
69
+ readonly code?: string;
70
+ readonly message?: string;
71
+ }
72
+ /** 配置电话的信封(收或拒,永不抛)。 */
73
+ export type RpcReply = {
74
+ readonly ok: true;
75
+ readonly value: unknown;
76
+ } | {
77
+ readonly ok: false;
78
+ readonly error?: RpcErrorFace;
79
+ };
80
+ /** 信封守卫:拆包前校验(信封形状的定义地在这里)。 */
81
+ export declare function isRpcResult(raw: unknown): raw is RpcReply;
82
+ //# sourceMappingURL=config-panel-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-contract.d.ts","sourceRoot":"","sources":["../src/config-panel-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,mCAAmC;AACnC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/C,yDAAyD;AACzD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvE;6DAC6D;AAC7D,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;oDACgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;yCACqC;IACrC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;oEACgE;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;qDAGqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,gBAAgB;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gBAAgB;IAChB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAClE;AAED,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,EAAG,YAAqB,CAAC;AAC7D,eAAO,MAAM,wBAAwB,EAAG,aAAsB,CAAC;AAC/D,eAAO,MAAM,yBAAyB,EAAG,cAAuB,CAAC;AAEjE,gCAAgC;AAChC,eAAO,MAAM,oBAAoB,EAAG,cAAa,CAAC;AAClD,eAAO,MAAM,mBAAmB,EAAG,0EAAuB,CAAC;AAE3D,gDAAgD;AAChD,eAAO,MAAM,eAAe,EAAG,KAAe,CAAC;AAE/C,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAG,IAAa,CAAC;AAE9C,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,EAAG,wBAAiC,CAAC;AAEzE,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,EAAG,8BAAuC,CAAC;AAEhF,kBAAkB;AAClB,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAwB;AACxB,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC;AAE1D,+BAA+B;AAC/B,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,QAAQ,CAGzD"}
@@ -0,0 +1,32 @@
1
+ /** 共用配置面板 · 契约:行表形状、配置面回执、几条两侧共用的常量。
2
+ *
3
+ * 为什么住这里:六个单品插件的设置页各有一份逐字相同的那套代码(卡片骨架/行渲染/样式表/
4
+ * 状态机/配置面三通电话约 3105 行)。本件是抽件之后的**唯一一处定义地**。
5
+ *
6
+ * 本件不认识任何一家能力:行表由调用方给,分支只能由行表数据与配置面回执决定,
7
+ * 里面不出现任何一个能力的名字(结构纪律「依赖方向」)。
8
+ *
9
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
10
+ */
11
+ /** 面板对配置面的三通电话:读整面/保存一份取值/重置为默认。三个名字各家逐字相同,收在这里一处。 */
12
+ export const RPC_ENDPOINT_CONFIG_GET = 'config.get';
13
+ export const RPC_ENDPOINT_CONFIG_SAVE = 'config.save';
14
+ export const RPC_ENDPOINT_CONFIG_RESET = 'config.reset';
15
+ /** 高级组标题与副文案(六家逐字相同,收在这里一处)。 */
16
+ export const ADVANCED_GROUP_TITLE = '高级';
17
+ export const ADVANCED_GROUP_NOTE = '不常改。留空=用默认值。';
18
+ /** 请求超时毫秒:与宿主侧 SPAWN_TIMEOUT_MS 同级,界面永不无限转圈。 */
19
+ export const READ_TIMEOUT_MS = 20_000;
20
+ /** 复制那一枚按钮就地变「已复制」之后,多久变回「复制」(定稿 v3 第三条:1.5 秒,不弹提示)。 */
21
+ export const COPY_FEEDBACK_MS = 1500;
22
+ /** 宿主给「这是哪一种目录选择能力」时用的那两格原语的名字(软依赖:按名字现取,缺席即没有入口)。 */
23
+ export const REMOTE_DIRECTORY_PICKER = 'remote.directoryPicker';
24
+ /** 宿主在「这条路不给」时回的那个码(`directory-browser-state` 的 `openRowBrowser` 只照比不认名)。 */
25
+ export const DIRECTORY_PICKER_REFUSED = 'directory-picker/unavailable';
26
+ /** 信封守卫:拆包前校验(信封形状的定义地在这里)。 */
27
+ export function isRpcResult(raw) {
28
+ if (typeof raw !== 'object' || raw === null)
29
+ return false;
30
+ return raw.ok === true || raw.ok === false;
31
+ }
32
+ //# sourceMappingURL=config-panel-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-contract.js","sourceRoot":"","sources":["../src/config-panel-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+CH,sDAAsD;AACtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,YAAqB,CAAC;AAC7D,MAAM,CAAC,MAAM,wBAAwB,GAAG,aAAsB,CAAC;AAC/D,MAAM,CAAC,MAAM,yBAAyB,GAAG,cAAuB,CAAC;AAEjE,gCAAgC;AAChC,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAa,CAAC;AAClD,MAAM,CAAC,MAAM,mBAAmB,GAAG,cAAuB,CAAC;AAE3D,gDAAgD;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAe,CAAC;AAE/C,wDAAwD;AACxD,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAa,CAAC;AAE9C,sDAAsD;AACtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,wBAAiC,CAAC;AAEzE,6EAA6E;AAC7E,MAAM,CAAC,MAAM,wBAAwB,GAAG,8BAAuC,CAAC;AAahF,+BAA+B;AAC/B,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC1D,OAAQ,GAAwB,CAAC,EAAE,KAAK,IAAI,IAAK,GAAwB,CAAC,EAAE,KAAK,KAAK,CAAC;AACzF,CAAC"}
@@ -0,0 +1,80 @@
1
+ /** 共用配置面板 · 取值与填值半:一份配置取值 ↔ 一张表单态,外加脏基线、跟随键、人话报错与三通电话。
2
+ *
3
+ * 本件**不认识 React**,也不认识宿主:喂一份配置面回执与一张行表,它把「页面上每一行该显示什么」
4
+ * 算出来(取值),再把「表单态里哪几格真能改」还原成一份取值(填值)。因此它在 Node 里就能直测。
5
+ *
6
+ * 三条口径(照 #749 起的定稿):
7
+ * · **只读行显示技能算好的绝对值**(回执 `resolved` 组那一格):面板一个字都不算;回执缺那一格
8
+ * (旧技能)就显示空串,绝不编一条路径出来。
9
+ * · **可改行取值空着**时,直接把回执里那个落点绝对路径显示上去——用户不必自己拼路径。
10
+ * · **保存只提交真能改的行**:只读行显示的是绝对路径,把它当配置值写回去就是把「显示」当「配置」。
11
+ *
12
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
13
+ */
14
+ import type { ConfigItem, ConfigSurfaceReply } from './config-panel-contract.js';
15
+ /** 取数口取用器:每次取数时现取(连接后到也不永久缺席)。 */
16
+ export type GetCall = () => unknown;
17
+ /** 取值要的那几格:配置取值本身,加上「落点来源」两处(回执顶层那一个与 `resolved` 组那一格)。 */
18
+ export interface DraftSource {
19
+ readonly values: Record<string, unknown>;
20
+ /** 回执顶层那个落点绝对路径(各家回执用 `dataDir` 这个名字)。 */
21
+ readonly dataDir?: string;
22
+ /** 回执 `resolved` 组:技能算好的一组绝对路径,按格名取。 */
23
+ readonly resolved?: Readonly<Record<string, string | undefined>>;
24
+ }
25
+ /** 按 `a.b` 路径从配置取值里读(缺层或类型不符一律回 undefined)。 */
26
+ export declare function readPath(values: Record<string, unknown>, key: string): unknown;
27
+ /** 按 `a.b` 路径把值写进配置取值(中间层缺就建一层空组;已存在非组即覆盖成组)。 */
28
+ export declare function writePath(values: Record<string, unknown>, key: string, value: unknown): void;
29
+ /** 把配置取值铺成「行键 → 控件里的文本」(页面表单态;值缺项即空串,不返空留白)。 */
30
+ export declare function toDraft(items: readonly ConfigItem[], values: Record<string, unknown>, source: DraftSource): Record<string, string>;
31
+ /** 表单态 → 配置取值(按控件种类还原类型;空串对文本项照收,语义由「按默认落点」承担)。
32
+ *
33
+ * **只读行不收**:它们显示的是技能算好的绝对路径,写回配置就是把「显示的路径」当成「配置值」——
34
+ * 保存只提交真能改的那些行,其余键由技能侧做组内合并保留现值。 */
35
+ export declare function fromDraft(items: readonly ConfigItem[], draft: Readonly<Record<string, string>>): Record<string, unknown>;
36
+ /** 可改行(脏基线只看这一档)。 */
37
+ export declare function editableItemsOf(items: readonly ConfigItem[]): readonly ConfigItem[];
38
+ /** 常用项与高级项按行表自己的分级切开(不再另要一个「常用几行」的数:那是同一件事的第二处定义)。 */
39
+ export declare function tiersOf(items: readonly ConfigItem[]): {
40
+ readonly common: readonly ConfigItem[];
41
+ readonly advanced: readonly ConfigItem[];
42
+ };
43
+ /** 脏键:表单态里与「刚读到的整面」不一致的**可改行**。
44
+ *
45
+ * 只读行不进来:它们显示的是技能算好的绝对路径,拿它当「改动」会让面板一打开就显示「未保存」。 */
46
+ export declare function dirtyKeysOf(items: readonly ConfigItem[], draft: Readonly<Record<string, string>>, baseline: Readonly<Record<string, string>>): readonly string[];
47
+ /** 跟随映射的缺省:没有映射就是「一行都不跟随」。 */
48
+ export declare function noFollowKeys(): readonly string[];
49
+ /** 「值非法回落」那一条要的两个事实(不为空就说明这一行写的值与生效值不是一个)。
50
+ *
51
+ * 本件只能看见**两个事实**:配置里写的是什么、技能算出来的生效值是什么。所以这里只报事实,
52
+ * **不下「用不了」的判断**——写的是相对路径、尾分隔符写法不同、大小写不同,都会让两个字符串不等,
53
+ * 而那几种情形下配置其实是生效的。判断留给技能侧(它的回执里有且只有一个生效值)。 */
54
+ export interface FallbackFacts {
55
+ readonly written: string;
56
+ readonly effective: string;
57
+ }
58
+ /** 这一行有没有「写的值 ≠ 生效值」这回事:只要是可改行、标了落点来源、写的非空、
59
+ * 且技能算出来的生效值另有其值(去掉尾分隔符后仍不同),就报这两个事实。 */
60
+ export declare function fallbackFactsOf(item: ConfigItem, raw: string, source: DraftSource): FallbackFacts | null;
61
+ /** 配置面报错 → 人话指引。
62
+ *
63
+ * 报文由技能侧给出(`base-link-core` 的 `ConfigError` 已带行号与文件名,技能 `cli/config.ts`
64
+ * 原样交出,插件 bridge 原样带上),所以这里**不重写报文**,只按报错类补一句「接下来怎么办」。 */
65
+ export declare function humanizeConfigFailure(code: string, message: string): string;
66
+ /** 一次配置电话的结果(收整面/落字;永不抛)。 */
67
+ export type ConfigOutcome = {
68
+ readonly ok: true;
69
+ readonly surface: ConfigSurfaceReply;
70
+ } | {
71
+ readonly ok: false;
72
+ readonly message: string;
73
+ };
74
+ /** 读设置页整面。 */
75
+ export declare function fetchConfigSurface(call: unknown, channel: string): Promise<ConfigOutcome>;
76
+ /** 保存一份取值(回执只有 `{path, values}`,**不是**整面:写完要重新读一份整面)。 */
77
+ export declare function saveConfigSurface(call: unknown, channel: string, values: Record<string, unknown>): Promise<ConfigOutcome>;
78
+ /** 重置为默认(技能侧先落一份备份;回执同样不是整面,写完要重新读一份整面)。 */
79
+ export declare function resetConfigSurface(call: unknown, channel: string): Promise<ConfigOutcome>;
80
+ //# sourceMappingURL=config-panel-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-value.d.ts","sourceRoot":"","sources":["../src/config-panel-value.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ /** 共用配置面板 · 取值与填值半:一份配置取值 ↔ 一张表单态,外加脏基线、跟随键、人话报错与三通电话。
2
+ *
3
+ * 本件**不认识 React**,也不认识宿主:喂一份配置面回执与一张行表,它把「页面上每一行该显示什么」
4
+ * 算出来(取值),再把「表单态里哪几格真能改」还原成一份取值(填值)。因此它在 Node 里就能直测。
5
+ *
6
+ * 三条口径(照 #749 起的定稿):
7
+ * · **只读行显示技能算好的绝对值**(回执 `resolved` 组那一格):面板一个字都不算;回执缺那一格
8
+ * (旧技能)就显示空串,绝不编一条路径出来。
9
+ * · **可改行取值空着**时,直接把回执里那个落点绝对路径显示上去——用户不必自己拼路径。
10
+ * · **保存只提交真能改的行**:只读行显示的是绝对路径,把它当配置值写回去就是把「显示」当「配置」。
11
+ *
12
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
13
+ */
14
+ import { RPC_ENDPOINT_CONFIG_GET, RPC_ENDPOINT_CONFIG_RESET, RPC_ENDPOINT_CONFIG_SAVE, READ_TIMEOUT_MS, isRpcResult, } from './config-panel-contract.js';
15
+ /** 按 `a.b` 路径从配置取值里读(缺层或类型不符一律回 undefined)。 */
16
+ export function readPath(values, key) {
17
+ const parts = key.split('.');
18
+ let cur = values;
19
+ for (const part of parts) {
20
+ if (typeof cur !== 'object' || cur === null || Array.isArray(cur))
21
+ return undefined;
22
+ cur = cur[part];
23
+ }
24
+ return cur;
25
+ }
26
+ /** 按 `a.b` 路径把值写进配置取值(中间层缺就建一层空组;已存在非组即覆盖成组)。 */
27
+ export function writePath(values, key, value) {
28
+ const parts = key.split('.');
29
+ let cur = values;
30
+ for (let i = 0; i < parts.length - 1; i++) {
31
+ const part = parts[i];
32
+ const next = cur[part];
33
+ if (typeof next !== 'object' || next === null || Array.isArray(next))
34
+ cur[part] = {};
35
+ cur = cur[part];
36
+ }
37
+ cur[parts[parts.length - 1]] = value;
38
+ }
39
+ /** 落点来源取一格:先看回执 `resolved` 组同名格,再看回执顶层同名格(两种写法收成同一格)。
40
+ *
41
+ * 顶层那一格为什么只认 `dataDir`:它是**技能算出来的生效数据目录**这个概念的格名,各家的回执
42
+ * 都叫它 `dataDir`;其余落点(照片目录、附件目录等)一律住在 `resolved` 组里。本件不猜别的名字。 */
43
+ function prefillValueOf(source, name) {
44
+ const fromResolved = source.resolved?.[name];
45
+ if (typeof fromResolved === 'string' && fromResolved !== '')
46
+ return fromResolved;
47
+ if (name === 'dataDir' && typeof source.dataDir === 'string' && source.dataDir !== '')
48
+ return source.dataDir;
49
+ return undefined;
50
+ }
51
+ /** 只读行显示什么:标了 `resolveFrom` ⇒ 回执 `resolved` 组那一格(技能算好的绝对路径);
52
+ * 没标 ⇒ 配置文件里那个值本身(数字类只读项走这一档:显示的是生效数字)。 */
53
+ function readonlyTextOf(item, raw, source) {
54
+ if (item.resolveFrom === undefined)
55
+ return raw;
56
+ const shown = source.resolved?.[item.resolveFrom];
57
+ return typeof shown === 'string' ? shown : '';
58
+ }
59
+ /** 把配置取值铺成「行键 → 控件里的文本」(页面表单态;值缺项即空串,不返空留白)。 */
60
+ export function toDraft(items, values, source) {
61
+ const draft = {};
62
+ for (const item of items) {
63
+ const v = readPath(values, item.key);
64
+ const raw = v === undefined || v === null ? '' : String(v);
65
+ if (item.readonly === true) {
66
+ draft[item.key] = readonlyTextOf(item, raw, source);
67
+ continue;
68
+ }
69
+ const fallback = item.prefillFrom === undefined ? undefined : prefillValueOf(source, item.prefillFrom);
70
+ draft[item.key] = raw === '' && fallback !== undefined ? fallback : raw;
71
+ }
72
+ return draft;
73
+ }
74
+ /** 表单态 → 配置取值(按控件种类还原类型;空串对文本项照收,语义由「按默认落点」承担)。
75
+ *
76
+ * **只读行不收**:它们显示的是技能算好的绝对路径,写回配置就是把「显示的路径」当成「配置值」——
77
+ * 保存只提交真能改的那些行,其余键由技能侧做组内合并保留现值。 */
78
+ export function fromDraft(items, draft) {
79
+ const values = {};
80
+ for (const item of items) {
81
+ if (item.readonly === true)
82
+ continue;
83
+ const raw = draft[item.key] ?? '';
84
+ if (item.control === 'number') {
85
+ const n = Number(raw);
86
+ writePath(values, item.key, Number.isFinite(n) ? n : 0);
87
+ }
88
+ else if (item.control === 'switch') {
89
+ writePath(values, item.key, raw === 'true');
90
+ }
91
+ else {
92
+ writePath(values, item.key, raw);
93
+ }
94
+ }
95
+ return values;
96
+ }
97
+ /** 可改行(脏基线只看这一档)。 */
98
+ export function editableItemsOf(items) {
99
+ return items.filter((item) => item.readonly !== true);
100
+ }
101
+ /** 常用项与高级项按行表自己的分级切开(不再另要一个「常用几行」的数:那是同一件事的第二处定义)。 */
102
+ export function tiersOf(items) {
103
+ return {
104
+ common: items.filter((item) => item.tier === 'common'),
105
+ advanced: items.filter((item) => item.tier === 'advanced'),
106
+ };
107
+ }
108
+ /** 脏键:表单态里与「刚读到的整面」不一致的**可改行**。
109
+ *
110
+ * 只读行不进来:它们显示的是技能算好的绝对路径,拿它当「改动」会让面板一打开就显示「未保存」。 */
111
+ export function dirtyKeysOf(items, draft, baseline) {
112
+ return editableItemsOf(items)
113
+ .filter((item) => (draft[item.key] ?? '') !== (baseline[item.key] ?? ''))
114
+ .map((item) => item.key);
115
+ }
116
+ /** 跟随映射的缺省:没有映射就是「一行都不跟随」。 */
117
+ export function noFollowKeys() {
118
+ return [];
119
+ }
120
+ /** 这一行有没有「写的值 ≠ 生效值」这回事:只要是可改行、标了落点来源、写的非空、
121
+ * 且技能算出来的生效值另有其值(去掉尾分隔符后仍不同),就报这两个事实。 */
122
+ export function fallbackFactsOf(item, raw, source) {
123
+ if (item.readonly === true || item.prefillFrom === undefined)
124
+ return null;
125
+ const written = raw.trim();
126
+ if (written === '')
127
+ return null;
128
+ const effective = prefillValueOf(source, item.prefillFrom);
129
+ if (effective === undefined)
130
+ return null;
131
+ const strip = (path) => path.replace(/[\\/]+$/, '');
132
+ if (strip(written) === strip(effective))
133
+ return null;
134
+ return { written, effective };
135
+ }
136
+ /** 配置面报错 → 人话指引。
137
+ *
138
+ * 报文由技能侧给出(`base-link-core` 的 `ConfigError` 已带行号与文件名,技能 `cli/config.ts`
139
+ * 原样交出,插件 bridge 原样带上),所以这里**不重写报文**,只按报错类补一句「接下来怎么办」。 */
140
+ export function humanizeConfigFailure(code, message) {
141
+ const text = message.trim().length > 0 ? message.trim() : `(${code},宿主未给报文)`;
142
+ if (/解析|YAML|parse/i.test(text))
143
+ return `${text}\n改回「键: 值」的写法,或点「重置为默认」。`;
144
+ if (/不认识|未知键|UNKNOWN_KEY/i.test(text))
145
+ return `${text}\n删掉页面上没有的行,或点「重置为默认」。`;
146
+ if (/类型|TYPE_MISMATCH/i.test(text))
147
+ return `${text}\n按本页的控件形状填,或点「重置为默认」。`;
148
+ if (/缺席|missing-cli/i.test(text))
149
+ return `${text}\n技能出口没找到:先确认技能包已装好,再点「重新读取」。`;
150
+ return `${text}\n改不动就点「重置为默认」,或照上面那条路径手工改配置文件。`;
151
+ }
152
+ /** 有界等待:借平台 `AbortSignal.timeout` 的 abort 事件做**一次**超时拒绝。
153
+ *
154
+ * 为什么不自建定时器:本仓冻结边界是「无数据轮询」,而设置页等的是一次电话回执,不是轮询;
155
+ * 用平台自带的一次性超时既守住边界的本意,也把「不转圈」落到实处。同一个 signal 也交给传输,
156
+ * 双保险:它搭理 signal 就早收工,不理也有这一道兜底(桌面端自研传输会忽略 signal,见 #760)。 */
157
+ function withDeadline(promise, ms) {
158
+ const signal = AbortSignal.timeout(ms);
159
+ const limit = new Promise((_, reject) => {
160
+ signal.addEventListener('abort', () => {
161
+ const e = new Error(`配置请求超时(${Math.round(ms / 1000)}s):宿主未回`);
162
+ e.name = 'TimeoutError';
163
+ reject(e);
164
+ }, { once: true });
165
+ });
166
+ return Promise.race([promise, limit]);
167
+ }
168
+ /** 一次配置电话(走调用方给的那条通道,靠端点名分发;永不抛,失败落字)。 */
169
+ async function configRpc(call, channel, method, payload) {
170
+ if (typeof call !== 'function')
171
+ return { ok: false, message: '宿主连接缺席:connection.rpc.call 不可用' };
172
+ try {
173
+ const raw = await withDeadline(call('/api', channel.replace(/^\//, ''), { method, payload }, AbortSignal.timeout(READ_TIMEOUT_MS)), READ_TIMEOUT_MS);
174
+ if (!isRpcResult(raw))
175
+ return { ok: false, message: '回执信封异常(非 ok 信封)' };
176
+ if (!raw.ok) {
177
+ return { ok: false, message: humanizeConfigFailure(raw.error?.code ?? 'unknown', raw.error?.message ?? '') };
178
+ }
179
+ return { ok: true, surface: raw.value };
180
+ }
181
+ catch (e) {
182
+ if (e instanceof Error && (e.name === 'AbortError' || e.name === 'TimeoutError')) {
183
+ return { ok: false, message: `配置请求超时(${Math.round(READ_TIMEOUT_MS / 1000)}s):宿主未回` };
184
+ }
185
+ return { ok: false, message: `配置失败:${e instanceof Error ? e.message : String(e)}` };
186
+ }
187
+ }
188
+ /** 读设置页整面。 */
189
+ export function fetchConfigSurface(call, channel) {
190
+ return configRpc(call, channel, RPC_ENDPOINT_CONFIG_GET, {});
191
+ }
192
+ /** 保存一份取值(回执只有 `{path, values}`,**不是**整面:写完要重新读一份整面)。 */
193
+ export function saveConfigSurface(call, channel, values) {
194
+ return configRpc(call, channel, RPC_ENDPOINT_CONFIG_SAVE, { values });
195
+ }
196
+ /** 重置为默认(技能侧先落一份备份;回执同样不是整面,写完要重新读一份整面)。 */
197
+ export function resetConfigSurface(call, channel) {
198
+ return configRpc(call, channel, RPC_ENDPOINT_CONFIG_RESET, {});
199
+ }
200
+ //# sourceMappingURL=config-panel-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-value.js","sourceRoot":"","sources":["../src/config-panel-value.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ /** 共用配置面板 · 视图半:一行怎么画(`Row`)、整面怎么画(`PanelBody`)。
2
+ *
3
+ * 本件是**纯函数**:吃一份状态与一组回调,回一棵 React 元素树,自己不留任何状态、不取任何数。
4
+ * 为什么这么分:状态机与副作用住在 `config-panel.ts` 那一层,于是本件在 Node 里就能直测
5
+ * (照 `directory-browser-ui.ts` 的既有作法:用例把组件当普通函数调,直接读回那棵树)。
6
+ *
7
+ * 手写 `React.createElement`(本包 client 束禁 JSX)。样式表 `S` 就在本件里——面板怎么画只有这一处。
8
+ *
9
+ * 三条定稿(v3)在本件落地:
10
+ * ① **只读行的目录按钮不画**(不画一枚点了也没反应的死按钮);
11
+ * ② 目录行的按钮字面**两档合一**,一律「浏览文件夹」(入口供不了时整枚不画);
12
+ * ③ **每行一枚「复制」**:复制这一行完好的值文本;点下去按钮就地变「已复制」再变回,不弹提示。
13
+ *
14
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
15
+ */
16
+ import * as React from 'react';
17
+ import type { ConfigItem, ConfigSurfaceReply } from './config-panel-contract.js';
18
+ import type { FallbackFacts } from './config-panel-value.js';
19
+ import type { DirectoryRowBrowser } from './directory-browser-state.js';
20
+ import type { DirectoryRowEntry } from './directory-browser-api.js';
21
+ /** 面板的样式表:颜色走 DSH 主题别名(深浅主题自适应,写死值只做回退),字号一律相对单位(em)。 */
22
+ declare const S: {
23
+ card: React.CSSProperties;
24
+ title: React.CSSProperties;
25
+ muted: React.CSSProperties;
26
+ error: React.CSSProperties;
27
+ okText: React.CSSProperties;
28
+ rows: React.CSSProperties;
29
+ info: React.CSSProperties;
30
+ row: React.CSSProperties;
31
+ label: React.CSSProperties;
32
+ hint: React.CSSProperties;
33
+ input: React.CSSProperties;
34
+ pickRow: React.CSSProperties;
35
+ acts: React.CSSProperties;
36
+ btnPick: React.CSSProperties;
37
+ invalid: React.CSSProperties;
38
+ bar: React.CSSProperties;
39
+ saveMsg: React.CSSProperties;
40
+ dirtyDot: React.CSSProperties;
41
+ followNote: React.CSSProperties;
42
+ btn: React.CSSProperties;
43
+ btnPrimary: React.CSSProperties;
44
+ advanced: React.CSSProperties;
45
+ summary: React.CSSProperties;
46
+ version: React.CSSProperties;
47
+ };
48
+ /** 样式表的形状(附加块照面板的视觉写,不各写一套内联样式)。 */
49
+ export type ConfigStyles = typeof S;
50
+ /** 附加块拿到的那两格。 */
51
+ export interface PanelParts {
52
+ /** 面板自己的样式表。 */
53
+ readonly styles: ConfigStyles;
54
+ /** 配置面整面回执;还没读到(读取中/读取失败)时为 null。 */
55
+ readonly reply: ConfigSurfaceReply | null;
56
+ }
57
+ /** 一行点「复制」之后就地显示成哪一档字面。 */
58
+ export type CopyState = 'idle' | 'done' | 'failed';
59
+ /** 复制那一枚按钮的字面(定稿 v3 第三条:就地变,不弹提示)。 */
60
+ export declare function copyLabelOf(state: CopyState | undefined): string;
61
+ export interface RowProps {
62
+ readonly item: ConfigItem;
63
+ readonly value: string;
64
+ readonly disabled: boolean;
65
+ readonly onChange: (key: string, next: string) => void;
66
+ /** 目录行才有:入口三态(`native`/`browse`/`none`)。 */
67
+ readonly browser?: DirectoryRowEntry | null | undefined;
68
+ /** 脏行:这一行与刚读到的整面不一致时画标记。 */
69
+ readonly dirty?: boolean;
70
+ /** 跟随行:只读派生行在触发键变脏时给「将跟随更新」态。 */
71
+ readonly follow?: boolean;
72
+ /** 点这一行的「复制」:把该行的值文本交出去。
73
+ * 定稿 v3 要求每行一枚,所以按钮**一律画**;这一格缺席时按钮 `disabled` 而不是点了就炸
74
+ * (面板那边永远给这一格,缺席只可能是别的调用点少交了东西)。 */
75
+ readonly onCopy?: ((key: string, text: string) => void) | undefined;
76
+ /** 复制那一枚按钮当刻的字面(不给=「复制」)。 */
77
+ readonly copyState?: CopyState | undefined;
78
+ /** 「写的值 ≠ 生效值」两个事实:给了就在这一行下面画一段黄字。 */
79
+ readonly fallback?: FallbackFacts | null | undefined;
80
+ }
81
+ /** 一行输入(四种控件对齐受限 YAML 子集:文本/数字/布尔/目录)。
82
+ *
83
+ * 目录档=文本框 + 一枚唤起目录选择的按钮;入口三态是 `none`(命名空间拿不到、或这条路已被拒)
84
+ * **就不画按钮**,文本框照旧——那是该缝自己的契约(供不了就收起入口,不是失败)。
85
+ * **只读行**:控件一律 `disabled`、`onChange` 不接,目录行的按钮**一枚都不画**(定稿 v3 ①)。 */
86
+ export declare function Row(props: RowProps): React.ReactElement;
87
+ /** 面板状态:读取中/就绪/整面读取失败。 */
88
+ export type PanelState = {
89
+ readonly kind: 'loading';
90
+ } | {
91
+ readonly kind: 'ready';
92
+ readonly surface: ConfigSurfaceReply;
93
+ } | {
94
+ readonly kind: 'failed';
95
+ readonly message: string;
96
+ };
97
+ /** 整面的全部输入:状态 + 行表 + 各档回调(本件只读它、只回调)。 */
98
+ export interface PanelBodyProps {
99
+ /** 卡片标题(各家自己的产品名)。 */
100
+ readonly title: string | undefined;
101
+ readonly items: readonly ConfigItem[];
102
+ readonly state: PanelState;
103
+ readonly draft: Readonly<Record<string, string>>;
104
+ readonly busy: boolean;
105
+ /** 成功提示(已保存/已重置)。 */
106
+ readonly notice: string | null;
107
+ /** 写入失败那一支:落点在底栏紧下面(与「就地失败」分开摆)。 */
108
+ readonly writeError: string | null;
109
+ /** 就地失败那一支(选目录那类)。 */
110
+ readonly error: string | null;
111
+ readonly picking: boolean;
112
+ readonly browseRow: DirectoryRowBrowser | null;
113
+ readonly rowEntry: DirectoryRowEntry | null;
114
+ readonly dirtyKeys: readonly string[];
115
+ readonly followKeys: readonly string[];
116
+ readonly copy: {
117
+ readonly key: string;
118
+ readonly ok: boolean;
119
+ } | null;
120
+ readonly onCopy: (key: string, text: string) => void;
121
+ readonly onChange: (key: string, next: string) => void;
122
+ readonly onSave: () => void;
123
+ readonly onReset: () => void;
124
+ readonly onRetry: () => void;
125
+ /** 自家附加块(版本行/状态行):给了就画在面板主体之后、动作条之前。 */
126
+ readonly extra?: ((parts: PanelParts) => React.ReactNode) | undefined;
127
+ }
128
+ /** 画整面(四支控件、三支错误落位、底栏、附加块槽都在这里)。 */
129
+ export declare function PanelBody(props: PanelBodyProps): React.ReactElement;
130
+ export {};
131
+ //# sourceMappingURL=config-panel-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-view.d.ts","sourceRoot":"","sources":["../src/config-panel-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,226 @@
1
+ /** 共用配置面板 · 视图半:一行怎么画(`Row`)、整面怎么画(`PanelBody`)。
2
+ *
3
+ * 本件是**纯函数**:吃一份状态与一组回调,回一棵 React 元素树,自己不留任何状态、不取任何数。
4
+ * 为什么这么分:状态机与副作用住在 `config-panel.ts` 那一层,于是本件在 Node 里就能直测
5
+ * (照 `directory-browser-ui.ts` 的既有作法:用例把组件当普通函数调,直接读回那棵树)。
6
+ *
7
+ * 手写 `React.createElement`(本包 client 束禁 JSX)。样式表 `S` 就在本件里——面板怎么画只有这一处。
8
+ *
9
+ * 三条定稿(v3)在本件落地:
10
+ * ① **只读行的目录按钮不画**(不画一枚点了也没反应的死按钮);
11
+ * ② 目录行的按钮字面**两档合一**,一律「浏览文件夹」(入口供不了时整枚不画);
12
+ * ③ **每行一枚「复制」**:复制这一行完好的值文本;点下去按钮就地变「已复制」再变回,不弹提示。
13
+ *
14
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
15
+ */
16
+ import * as React from 'react';
17
+ import { ADVANCED_GROUP_NOTE, ADVANCED_GROUP_TITLE } from './config-panel-contract.js';
18
+ import { fallbackFactsOf } from './config-panel-value.js';
19
+ import { DirectoryBrowserFromRow } from './directory-browser-ui.js';
20
+ /** 面板的样式表:颜色走 DSH 主题别名(深浅主题自适应,写死值只做回退),字号一律相对单位(em)。 */
21
+ const S = {
22
+ card: {
23
+ padding: '12px 14px',
24
+ borderRadius: 10,
25
+ border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.35))',
26
+ background: 'var(--dsw-alias-bg-base, transparent)',
27
+ color: 'var(--dsw-alias-label-primary, inherit)',
28
+ lineHeight: 1.6,
29
+ },
30
+ title: { fontSize: '1.08em', fontWeight: 700, marginBottom: 8 },
31
+ muted: { color: 'var(--dsw-alias-label-secondary, #9a9a9a)', fontSize: '0.92em' },
32
+ error: { marginTop: 8, color: 'var(--dsw-alias-label-error, #b3261e)', fontSize: '1em', whiteSpace: 'pre-wrap' },
33
+ okText: { marginTop: 8, color: 'var(--dsw-alias-state-success-primary, #12805c)', fontSize: '0.96em' },
34
+ rows: { marginTop: 8, borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))', paddingTop: 8 },
35
+ info: { color: 'var(--dsw-alias-label-secondary, #9a9a9a)', fontSize: '0.92em', overflowWrap: 'anywhere' },
36
+ row: { marginBottom: 10 },
37
+ label: { fontWeight: 600 },
38
+ hint: { color: 'var(--dsw-alias-label-secondary, #9a9a9a)', fontSize: '0.92em', marginBottom: 4 },
39
+ input: {
40
+ width: '100%',
41
+ boxSizing: 'border-box',
42
+ padding: '4px 8px',
43
+ borderRadius: 6,
44
+ border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',
45
+ background: 'var(--dsw-alias-bg-base, transparent)',
46
+ color: 'var(--dsw-alias-label-primary, inherit)',
47
+ },
48
+ pickRow: { display: 'flex', gap: 6, alignItems: 'center' },
49
+ acts: { display: 'flex', gap: 6, alignItems: 'center', flex: '0 0 auto' },
50
+ btnPick: {
51
+ flex: '0 0 auto',
52
+ padding: '4px 10px',
53
+ borderRadius: 6,
54
+ border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',
55
+ background: 'var(--dsw-alias-bg-base, transparent)',
56
+ color: 'var(--dsw-alias-label-primary, inherit)',
57
+ whiteSpace: 'nowrap',
58
+ cursor: 'pointer',
59
+ },
60
+ invalid: { marginTop: 6, padding: '6px 8px', borderRadius: 6, background: 'color-mix(in srgb, var(--dsw-alias-state-warning-primary, #b26a00) 16%, transparent)', border: '1px solid var(--dsw-alias-state-warning-primary, #b26a00)', color: 'var(--dsw-alias-label-primary, inherit)', fontSize: '0.92em' },
61
+ bar: { display: 'flex', gap: 8, marginTop: 12, flexWrap: 'wrap', position: 'sticky', bottom: 0, zIndex: 1, background: 'var(--dsw-alias-bg-layer-1, #232329)', padding: '8px 0', borderTop: '1px solid var(--dsw-alias-border, rgba(128,128,128,.25))' },
62
+ saveMsg: { marginRight: 'auto', alignSelf: 'center', color: 'var(--dsw-alias-state-warning-primary, #b26a00)', fontSize: '0.9em' },
63
+ dirtyDot: { color: 'var(--dsw-alias-state-warning-primary, #b26a00)', fontSize: '0.85em', marginLeft: 6, fontWeight: 400 },
64
+ followNote: { color: 'var(--dsw-alias-state-warning-primary, #b26a00)', fontSize: '0.85em', marginBottom: 4 },
65
+ btn: {
66
+ padding: '4px 12px',
67
+ borderRadius: 6,
68
+ border: '1px solid var(--dsw-alias-border, rgba(128,128,128,.45))',
69
+ background: 'var(--dsw-alias-bg-base, transparent)',
70
+ color: 'var(--dsw-alias-label-primary, inherit)',
71
+ cursor: 'pointer',
72
+ },
73
+ btnPrimary: {
74
+ padding: '4px 12px',
75
+ borderRadius: 6,
76
+ border: '1px solid var(--dsw-alias-brand-primary, #2f6fed)',
77
+ background: 'var(--dsw-alias-brand-primary, #2f6fed)',
78
+ color: '#fff',
79
+ cursor: 'pointer',
80
+ },
81
+ advanced: { marginTop: 12 },
82
+ summary: { cursor: 'pointer', fontWeight: 600 },
83
+ version: {
84
+ marginTop: 8,
85
+ paddingTop: 8,
86
+ borderTop: '1px dashed var(--dsw-alias-border, rgba(128,128,128,.25))',
87
+ color: 'var(--dsw-alias-label-tertiary, #8a8a8a)',
88
+ fontSize: '0.92em',
89
+ },
90
+ };
91
+ /** 复制那一枚按钮的字面(定稿 v3 第三条:就地变,不弹提示)。 */
92
+ export function copyLabelOf(state) {
93
+ if (state === 'done')
94
+ return '已复制';
95
+ if (state === 'failed')
96
+ return '复制失败';
97
+ return '复制';
98
+ }
99
+ /** 一行输入(四种控件对齐受限 YAML 子集:文本/数字/布尔/目录)。
100
+ *
101
+ * 目录档=文本框 + 一枚唤起目录选择的按钮;入口三态是 `none`(命名空间拿不到、或这条路已被拒)
102
+ * **就不画按钮**,文本框照旧——那是该缝自己的契约(供不了就收起入口,不是失败)。
103
+ * **只读行**:控件一律 `disabled`、`onChange` 不接,目录行的按钮**一枚都不画**(定稿 v3 ①)。 */
104
+ export function Row(props) {
105
+ const { item } = props;
106
+ const readonly = item.readonly === true;
107
+ const disabled = props.disabled || readonly;
108
+ const onChange = readonly
109
+ ? undefined
110
+ : (e) => props.onChange(item.key, e.target.value);
111
+ const control = item.control === 'switch'
112
+ ? React.createElement('input', {
113
+ type: 'checkbox',
114
+ checked: props.value === 'true',
115
+ disabled,
116
+ onChange: readonly
117
+ ? undefined
118
+ : (e) => props.onChange(item.key, e.target.checked ? 'true' : 'false'),
119
+ })
120
+ : React.createElement('input', {
121
+ style: props.dirty === true
122
+ ? { ...S.input, borderColor: 'var(--dsw-alias-state-warning-primary, #b26a00)' }
123
+ : readonly && props.follow === true
124
+ ? { ...S.input, opacity: 0.55 }
125
+ : S.input,
126
+ type: item.control === 'number' ? 'number' : 'text',
127
+ value: props.value,
128
+ disabled,
129
+ spellCheck: false,
130
+ onChange,
131
+ });
132
+ /** 目录入口:只读行不画(定稿 v3 ①),供不了(`none`/缺席)也不画。 */
133
+ const entry = props.browser ?? null;
134
+ const browse = item.control === 'directory' && !readonly && entry !== null && entry.mode !== 'none'
135
+ ? React.createElement('button', {
136
+ style: S.btnPick,
137
+ type: 'button',
138
+ disabled,
139
+ // 回这枚 Promise 是有意的:React 不看 onClick 的返回值,而用例能直接 await 它。
140
+ onClick: () => entry.onOpen(item.key),
141
+ }, '浏览文件夹')
142
+ : null;
143
+ const copy = React.createElement('button', {
144
+ style: S.btnPick,
145
+ type: 'button',
146
+ disabled: props.onCopy === undefined,
147
+ onClick: () => props.onCopy?.(item.key, props.value),
148
+ }, copyLabelOf(props.copyState));
149
+ const acts = React.createElement('div', { style: S.acts }, browse, copy);
150
+ const facts = props.fallback ?? null;
151
+ return React.createElement('div', { style: S.row }, React.createElement('div', { style: S.label }, item.title, props.dirty === true ? React.createElement('span', { style: S.dirtyDot }, '●已改动') : null), React.createElement('div', { style: S.hint }, item.hint), readonly && props.follow === true ? React.createElement('div', { style: S.followNote }, '将跟随更新,保存后生效。') : null, facts === null
152
+ ? null
153
+ : React.createElement('div', { style: S.invalid }, '配置里写的是 ', React.createElement('b', null, facts.written), ';现在生效的是 ', React.createElement('b', null, facts.effective), '。'), React.createElement('div', { style: S.pickRow }, control, acts));
154
+ }
155
+ /** 应用内浏览器对话框的文案(面板自带,逐条对应图上那几个位置)。 */
156
+ const BROWSER_LABELS = {
157
+ title: '选择文件夹',
158
+ close: '关闭',
159
+ up: '上一级',
160
+ pathPlaceholder: '直接填绝对路径,回车即进入',
161
+ go: '转到',
162
+ showHidden: (n) => '显示隐藏目录(' + n + ')',
163
+ empty: '这个目录里没有子目录。',
164
+ loading: '正在读取',
165
+ newFolder: '新建文件夹',
166
+ createConfirm: '创建',
167
+ createCancel: '取消',
168
+ select: '选',
169
+ selected: '已选',
170
+ open: '选定这个目录',
171
+ cancel: '取消',
172
+ willPick: '将选定:',
173
+ };
174
+ /** 画整面(四支控件、三支错误落位、底栏、附加块槽都在这里)。 */
175
+ export function PanelBody(props) {
176
+ const { state, title } = props;
177
+ const surface = state.kind === 'ready' ? state.surface : null;
178
+ const headText = title === undefined ? '配置' : `${title} · 配置`;
179
+ const headDataDir = surface === null ? '' : surface.resolved?.['dbDir'] ?? surface.dataDir;
180
+ const head = React.createElement('div', null, React.createElement('div', { style: S.title }, headText), surface === null
181
+ ? null
182
+ : React.createElement('div', null, React.createElement('div', { style: S.info }, `配置文件 ${surface.path}`), React.createElement('div', { style: S.info }, `数据目录 ${headDataDir}`), surface.created ? React.createElement('div', { style: S.muted }, '(配置文件刚按默认值生成)') : null));
183
+ const parts = { styles: S, reply: surface };
184
+ const extra = props.extra === undefined ? null : props.extra(parts);
185
+ if (state.kind === 'loading') {
186
+ return React.createElement('div', { style: S.card }, head, React.createElement('div', { style: S.muted }, '配置读取中'), extra);
187
+ }
188
+ if (state.kind === 'failed') {
189
+ return React.createElement('div', { style: S.card }, head, React.createElement('div', { style: S.error }, state.message), extra, React.createElement('div', { style: S.bar }, React.createElement('button', { style: S.btn, type: 'button', onClick: props.onRetry }, '重试'), React.createElement('button', { style: S.btn, type: 'button', onClick: props.onReset }, '重置为默认')));
190
+ }
191
+ const common = props.items.filter((item) => item.tier === 'common');
192
+ const advanced = props.items.filter((item) => item.tier === 'advanced');
193
+ const renderRow = (item) => React.createElement(Row, {
194
+ key: item.key,
195
+ item,
196
+ value: props.draft[item.key] ?? '',
197
+ disabled: props.busy,
198
+ onChange: props.onChange,
199
+ browser: props.rowEntry,
200
+ dirty: props.dirtyKeys.includes(item.key),
201
+ follow: props.followKeys.includes(item.key),
202
+ onCopy: props.onCopy,
203
+ copyState: props.copy !== null && props.copy.key === item.key ? (props.copy.ok ? 'done' : 'failed') : 'idle',
204
+ fallback: item.readonly !== true && item.prefillFrom !== undefined
205
+ ? fallbackFactsOf(item, props.draft[item.key] ?? '', draftSourceOf(surface))
206
+ : null,
207
+ });
208
+ const dirtyCount = props.dirtyKeys.length;
209
+ const dirty = dirtyCount > 0;
210
+ return React.createElement('div', { style: S.card }, head, React.createElement('div', { style: S.rows }, common.map(renderRow)), advanced.length === 0
211
+ ? null
212
+ : React.createElement('details', { style: S.advanced }, React.createElement('summary', { style: S.summary }, ADVANCED_GROUP_TITLE), React.createElement('div', { style: S.muted }, ADVANCED_GROUP_NOTE), advanced.map(renderRow)), extra, React.createElement('div', { style: S.bar }, dirty
213
+ ? React.createElement('div', { style: S.saveMsg }, `浏览改动后请点保存(${dirtyCount} 项未保存),保存后跟随项自动更新`)
214
+ : null, React.createElement('button', { style: dirty ? S.btnPrimary : S.btn, type: 'button', disabled: props.busy || !dirty, onClick: props.onSave }, props.busy ? '处理中' : dirty ? `保存(${dirtyCount} 项未保存)` : '保存'), React.createElement('button', { style: S.btn, type: 'button', disabled: props.busy, onClick: props.onReset }, '重置为默认'), React.createElement('button', { style: S.btn, type: 'button', disabled: props.busy, onClick: props.onRetry }, '重新读取')), props.picking ? React.createElement('div', { style: S.muted }, '已唤起系统文件夹对话框:选中后自动填上,取消则不动。') : null, props.browseRow !== null
215
+ ? React.createElement(DirectoryBrowserFromRow, { open: true, row: props.browseRow, labels: BROWSER_LABELS })
216
+ : null, props.writeError !== null
217
+ ? React.createElement('div', { style: S.error, role: 'alert' }, props.writeError)
218
+ : null, props.error !== null ? React.createElement('div', { style: S.error }, props.error) : null, props.notice !== null ? React.createElement('div', { style: S.okText }, props.notice) : null);
219
+ }
220
+ /** 「写的值 ≠ 生效值」两个事实要的那几格:整面回执里取值本身、落点顶层那一个、`resolved` 组。 */
221
+ function draftSourceOf(surface) {
222
+ if (surface === null)
223
+ return { values: {} };
224
+ return { values: surface.values, dataDir: surface.dataDir, resolved: surface.resolved };
225
+ }
226
+ //# sourceMappingURL=config-panel-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel-view.js","sourceRoot":"","sources":["../src/config-panel-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /** 共用配置面板 · 组件本体:一台状态机 + 一圈副作用,渲染交给 `config-panel-view.ts`。
2
+ *
3
+ * 这一件就是六个技能设置页的那张卡片:六家只交「连哪条通道」与「有哪些配置项」(行表),
4
+ * 另加三个可选钩子(跟随映射/卡片标题/自家附加块)。卡片怎么画、值怎么取又怎么填回去、
5
+ * 哪些行被改过还没保存、保存/重置/重新读取怎么走、出错时说什么话,全在本件与它下面那几件里。
6
+ *
7
+ * 状态:读到了没(loading/ready/failed)、哪些行被改过(脏基线)、正在写(busy)、
8
+ * 写完的结果(notice/writeError)、就地失败(error)、目录选择那一路(picking/browseRow)、
9
+ * 复制回执(copy)。**脏基线只看可改行**:只读行显示的是技能算好的绝对路径,拿它当「改动」
10
+ * 会让面板一打开就显示「未保存」。**写完一律重新读一份整面**:写回执不是整面,拿它当整面用
11
+ * 会让页头那行「数据目录」显示成空。
12
+ *
13
+ * 只挂一个副作用(挂载期读一次整面):取数口是**取用器**,每次调它现取,所以那个 effect
14
+ * 不需要跟着任何一格重跑——否则回执一落定就再读一次,会自己把自己转起来。
15
+ *
16
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
17
+ */
18
+ import * as React from 'react';
19
+ import type { ConfigItem } from './config-panel-contract.js';
20
+ import type { GetCall } from './config-panel-value.js';
21
+ import type { PanelParts } from './config-panel-view.js';
22
+ /** 六家的接入面:**一个通道路由名 + 一张行表 + 三个可选钩子**,另加两格六家同形的宿主取数接线。 */
23
+ export interface ConfigPanelProps {
24
+ /** 通道路由名(各家唯一那个真变量,形如 `/ilife-bill-ilife`)。 */
25
+ readonly channel: string;
26
+ /** 行表:顺序即页面顺序,分级写在每一行自己的 `tier` 上。 */
27
+ readonly items: readonly ConfigItem[];
28
+ /** 卡片标题(钩子之一,各家的产品名);不给就只写「配置」。 */
29
+ readonly title?: string | undefined;
30
+ /** 跟随映射(钩子之一):脏键 → 要显示「将跟随更新」的只读行;不给=一行都不跟随。 */
31
+ readonly followKeysOf?: ((dirtyKeys: readonly string[]) => readonly string[]) | undefined;
32
+ /** 自家附加块(钩子之一:版本行/状态行):画在面板主体之后、动作条之前。 */
33
+ readonly extra?: ((parts: PanelParts) => React.ReactNode) | undefined;
34
+ /** 宿主取数口取用器(六家同形的接线,不是各家数据):每次取数时现取,连接后到也不永久缺席。 */
35
+ readonly getCall: GetCall;
36
+ /** 宿主服务查找(六家同形的接线):目录选择是**软依赖**,缺席只是没有入口。 */
37
+ readonly getService?: ((name: string) => unknown) | undefined;
38
+ }
39
+ /** 技能设置页:承载一家自己的全部可配置项(只配置,不干活)。 */
40
+ export declare function ConfigPanel(props: ConfigPanelProps): React.ReactElement;
41
+ //# sourceMappingURL=config-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel.d.ts","sourceRoot":"","sources":["../src/config-panel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,UAAU,EAAsB,MAAM,4BAA4B,CAAC;AAUjF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,wBAAwB,CAAC;AAsDrE,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,mCAAmC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,gDAAgD;IAChD,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IAC1F,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,KAAK,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IACtE,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,6CAA6C;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAC/D;AAED,oCAAoC;AACpC,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAwLvE"}
@@ -0,0 +1,252 @@
1
+ /** 共用配置面板 · 组件本体:一台状态机 + 一圈副作用,渲染交给 `config-panel-view.ts`。
2
+ *
3
+ * 这一件就是六个技能设置页的那张卡片:六家只交「连哪条通道」与「有哪些配置项」(行表),
4
+ * 另加三个可选钩子(跟随映射/卡片标题/自家附加块)。卡片怎么画、值怎么取又怎么填回去、
5
+ * 哪些行被改过还没保存、保存/重置/重新读取怎么走、出错时说什么话,全在本件与它下面那几件里。
6
+ *
7
+ * 状态:读到了没(loading/ready/failed)、哪些行被改过(脏基线)、正在写(busy)、
8
+ * 写完的结果(notice/writeError)、就地失败(error)、目录选择那一路(picking/browseRow)、
9
+ * 复制回执(copy)。**脏基线只看可改行**:只读行显示的是技能算好的绝对路径,拿它当「改动」
10
+ * 会让面板一打开就显示「未保存」。**写完一律重新读一份整面**:写回执不是整面,拿它当整面用
11
+ * 会让页头那行「数据目录」显示成空。
12
+ *
13
+ * 只挂一个副作用(挂载期读一次整面):取数口是**取用器**,每次调它现取,所以那个 effect
14
+ * 不需要跟着任何一格重跑——否则回执一落定就再读一次,会自己把自己转起来。
15
+ *
16
+ * 对外只经 `config-panel-api.ts` 那一道门;本件自己不出门。
17
+ */
18
+ import * as React from 'react';
19
+ import { COPY_FEEDBACK_MS, DIRECTORY_PICKER_REFUSED, REMOTE_DIRECTORY_PICKER } from './config-panel-contract.js';
20
+ import { dirtyKeysOf, fetchConfigSurface, fromDraft, noFollowKeys, resetConfigSurface, saveConfigSurface, toDraft, } from './config-panel-value.js';
21
+ import { PanelBody } from './config-panel-view.js';
22
+ import { openRowBrowser, pickerModeOf, readPickAnswer } from './directory-browser-api.js';
23
+ import { createRootsSource } from './directory-browser-roots.js';
24
+ import { MANAGER_ACTIONS, MANAGER_RPC } from './update-contract.js';
25
+ /** 认一认某个值像不像目录选择命名空间(认不出就当没有,绝不把设置页带下来)。 */
26
+ function isPickerFace(raw) {
27
+ if (typeof raw !== 'object' || raw === null)
28
+ return false;
29
+ return typeof raw.pick === 'function';
30
+ }
31
+ /** 现取目录选择命名空间:**软依赖**,拿不到回 null(页面据此不出入口)。 */
32
+ function resolvePicker(getService) {
33
+ if (getService === undefined)
34
+ return null;
35
+ try {
36
+ const raw = getService(REMOTE_DIRECTORY_PICKER);
37
+ return isPickerFace(raw) ? raw : null;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /** 唤起一次系统文件夹选择器并归一结果(**永不抛**)。 */
44
+ async function pickDirectory(picker) {
45
+ try {
46
+ return readPickAnswer(await picker.pick());
47
+ }
48
+ catch (e) {
49
+ const reason = e instanceof Error ? e.message : String(e);
50
+ return { kind: 'unavailable', message: '打不开系统文件夹对话框(' + reason + '):请直接在框里填绝对路径。' };
51
+ }
52
+ }
53
+ /** 写一次剪贴板:**不碰 DOM**,只读当刻环境的 `globalThis.navigator`(拿不到就回 false,不抛)。
54
+ *
55
+ * 为什么不照原型那样退到 `document.execCommand`:本仓插件侧禁 DOM 直写(`document`/`window`),
56
+ * 所以没有那条兜底;拿不到剪贴板就如实回 false,界面上那一枚按钮就地显示「复制失败」。 */
57
+ async function writeClipboard(text) {
58
+ try {
59
+ const nav = globalThis.navigator;
60
+ const clip = nav?.clipboard;
61
+ if (clip === undefined || typeof clip.writeText !== 'function')
62
+ return false;
63
+ await clip.writeText(text);
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ /** 技能设置页:承载一家自己的全部可配置项(只配置,不干活)。 */
71
+ export function ConfigPanel(props) {
72
+ const [state, setState] = React.useState({ kind: 'loading' });
73
+ const [pickerGone, setPickerGone] = React.useState(false);
74
+ const [picking, setPicking] = React.useState(false);
75
+ const [draft, setDraft] = React.useState({});
76
+ const [busy, setBusy] = React.useState(false);
77
+ const [notice, setNotice] = React.useState(null);
78
+ const [writeError, setWriteError] = React.useState(null);
79
+ const [error, setError] = React.useState(null);
80
+ const [browseRow, setBrowseRow] = React.useState(null);
81
+ const [copy, setCopy] = React.useState(null);
82
+ /** 复制回执的复位定时器:**一次性 UI 回执**,不是数据轮询——点一次起一个,到点自我复位,
83
+ * 下一次点击先清掉旧的,卸载时也清掉(下面那个清扫 effect 就是那一半)。 */
84
+ const copyTimer = React.useRef(null);
85
+ React.useEffect(() => () => {
86
+ if (copyTimer.current !== null) {
87
+ clearTimeout(copyTimer.current);
88
+ copyTimer.current = null;
89
+ }
90
+ }, []);
91
+ /** 挂载期读一次整面:卸载之后回来的回执丢掉(不许往已经没了的页面上写)。 */
92
+ React.useEffect(() => {
93
+ let alive = true;
94
+ void (async () => {
95
+ const r = await fetchConfigSurface(props.getCall(), props.channel);
96
+ if (!alive)
97
+ return;
98
+ if (r.ok) {
99
+ setState({ kind: 'ready', surface: r.surface });
100
+ setDraft(toDraft(props.items, r.surface.values, r.surface));
101
+ }
102
+ else {
103
+ setState({ kind: 'failed', message: r.message });
104
+ }
105
+ })();
106
+ return () => {
107
+ alive = false;
108
+ };
109
+ // 只跑一次:`getCall` 本身是取用器,调用时现取连接;行表与通道在一张卡片里不会换。
110
+ // eslint-disable-next-line react-hooks/exhaustive-deps
111
+ }, []);
112
+ /** 把一份整面铺到页面上(读到之后唯一那一处落点)。 */
113
+ const apply = (surface) => {
114
+ setState({ kind: 'ready', surface });
115
+ setDraft(toDraft(props.items, surface.values, surface));
116
+ };
117
+ const load = async () => {
118
+ setNotice(null);
119
+ setWriteError(null);
120
+ setError(null);
121
+ const r = await fetchConfigSurface(props.getCall(), props.channel);
122
+ if (r.ok)
123
+ apply(r.surface);
124
+ else
125
+ setState({ kind: 'failed', message: r.message });
126
+ };
127
+ /** 写完(保存/重置)之后重新读一份整面:写回执只有 `{path, values}`、重置回执只有
128
+ * `{path, backupPath}`,都不是整面——拿它当整面用,页头那行「数据目录」会显示成空。 */
129
+ const writeThenReload = async (done) => {
130
+ setBusy(true);
131
+ setNotice(null);
132
+ setWriteError(null);
133
+ setError(null);
134
+ const r = await fetchConfigSurface(props.getCall(), props.channel);
135
+ if (r.ok) {
136
+ apply(r.surface);
137
+ setNotice(done);
138
+ }
139
+ else {
140
+ setState({ kind: 'failed', message: r.message });
141
+ }
142
+ setBusy(false);
143
+ };
144
+ const onChange = (key, next) => {
145
+ setDraft((prev) => ({ ...prev, [key]: next }));
146
+ setNotice(null);
147
+ setWriteError(null);
148
+ setError(null);
149
+ };
150
+ const picker = pickerGone ? null : resolvePicker(props.getService);
151
+ /** 唤起系统文件夹选择器那一条路(应用内浏览被拒时的兜底,也是命名空间只给 `pick` 时的唯一一条)。 */
152
+ const openNative = async (key) => {
153
+ const face = pickerGone ? null : resolvePicker(props.getService);
154
+ if (face === null)
155
+ return;
156
+ // 系统对话框是模态的:等它回来的这段时间给一行字,免得看着像「点了没反应」。
157
+ setPicking(true);
158
+ setError(null);
159
+ const outcome = await pickDirectory(face);
160
+ setPicking(false);
161
+ if (outcome.kind === 'picked')
162
+ onChange(key, outcome.path);
163
+ else if (outcome.kind === 'unavailable') {
164
+ setError(outcome.message);
165
+ setPickerGone(true);
166
+ }
167
+ };
168
+ /** 目录行的入口动作:**先应用内浏览,宿主没给这条路再换系统对话框**(判断在共用件里)。 */
169
+ const onOpenRow = async (key) => {
170
+ setError(null);
171
+ const opened = openRowBrowser({
172
+ picker,
173
+ initialPath: draft[key] ?? '',
174
+ onChange: (next) => onChange(key, next),
175
+ onRow: setBrowseRow,
176
+ refusalCode: DIRECTORY_PICKER_REFUSED,
177
+ rootsSource: createRootsSource({
178
+ getCall: props.getCall,
179
+ base: MANAGER_RPC.base,
180
+ endpoint: MANAGER_RPC.endpoint,
181
+ method: MANAGER_ACTIONS.roots,
182
+ }),
183
+ });
184
+ if (opened === undefined || (await opened) === 'refused')
185
+ await openNative(key);
186
+ };
187
+ /** 复制一行(定稿 v3 第三条):写完就地变「已复制」(写不进去就地变「复制失败」),1.5 秒后复位,不弹提示。 */
188
+ const onCopy = (key, text) => {
189
+ void writeClipboard(text).then((ok) => {
190
+ setCopy({ key, ok });
191
+ if (copyTimer.current !== null)
192
+ clearTimeout(copyTimer.current);
193
+ copyTimer.current = setTimeout(() => {
194
+ copyTimer.current = null;
195
+ setCopy(null);
196
+ }, COPY_FEEDBACK_MS);
197
+ });
198
+ };
199
+ const onSave = async () => {
200
+ setBusy(true);
201
+ setNotice(null);
202
+ setWriteError(null);
203
+ setError(null);
204
+ const r = await saveConfigSurface(props.getCall(), props.channel, fromDraft(props.items, draft));
205
+ setBusy(false);
206
+ if (r.ok)
207
+ await writeThenReload('已保存,立即生效(不用重启宿主)');
208
+ else
209
+ setWriteError(r.message);
210
+ };
211
+ const onReset = async () => {
212
+ setBusy(true);
213
+ setNotice(null);
214
+ setWriteError(null);
215
+ setError(null);
216
+ const r = await resetConfigSurface(props.getCall(), props.channel);
217
+ setBusy(false);
218
+ if (r.ok)
219
+ await writeThenReload('已重置为默认(原配置已另存一份 .bak)');
220
+ else
221
+ setWriteError(r.message);
222
+ };
223
+ const surface = state.kind === 'ready' ? state.surface : null;
224
+ const baseline = surface !== null ? toDraft(props.items, surface.values, surface) : null;
225
+ const dirtyKeys = baseline === null ? [] : dirtyKeysOf(props.items, draft, baseline);
226
+ const followKeys = (props.followKeysOf ?? noFollowKeys)(dirtyKeys);
227
+ const mode = pickerModeOf(picker);
228
+ const rowEntry = mode === 'none' ? null : { mode, onOpen: onOpenRow };
229
+ return React.createElement(PanelBody, {
230
+ title: props.title,
231
+ items: props.items,
232
+ state,
233
+ draft,
234
+ busy,
235
+ notice,
236
+ writeError,
237
+ error,
238
+ picking,
239
+ browseRow,
240
+ rowEntry,
241
+ dirtyKeys,
242
+ followKeys,
243
+ copy,
244
+ onCopy,
245
+ onChange,
246
+ onSave: () => void onSave(),
247
+ onReset: () => void onReset(),
248
+ onRetry: () => void load(),
249
+ extra: props.extra,
250
+ });
251
+ }
252
+ //# sourceMappingURL=config-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-panel.js","sourceRoot":"","sources":["../src/config-panel.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-life-pack",
3
- "version": "0.3.6",
3
+ "version": "0.3.12",
4
4
  "description": "爱生活总管插件:单 DSH设置面板槽(爱生活卡)+ 爱生活页签槽 children,技能设置页动态聚合,不依赖单品、不 import 单品页",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -10,6 +10,7 @@
10
10
  "./client": "./dist/client.js",
11
11
  "./directory-browser": "./dist/directory-browser-api.js",
12
12
  "./directory-browser-ui": "./dist/directory-browser-ui.js",
13
+ "./config-panel": "./dist/config-panel-api.js",
13
14
  "./package.json": "./package.json"
14
15
  },
15
16
  "files": [