dsh-memo-ilife 0.3.7 → 0.3.9
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/dist/client.js +118 -99
- package/dist/client.js.map +1 -1
- package/dist/contract.d.ts +37 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/settings.d.ts +28 -7
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +27 -41
- package/dist/settings.js.map +1 -1
- package/dist/slot.d.ts +1 -1
- package/dist/slot.js +1 -1
- package/package.json +3 -3
package/dist/client.js
CHANGED
|
@@ -60,7 +60,7 @@ window.__ModuleLoader__.load({
|
|
|
60
60
|
/** 版本行唯一来源(面板展示用;smoke 断言与两处 package.json 一致,防漂移)。
|
|
61
61
|
* 发版 bump 时同步改这里(与 package.json 同值):0.3.2 那轮之前停在 0.2.1——
|
|
62
62
|
* 面板自报家门报了旧号(#743 真机截图逮到),本票一并摆正。 */
|
|
63
|
-
const PLUGIN_VERSION = "0.3.
|
|
63
|
+
const PLUGIN_VERSION = "0.3.8";
|
|
64
64
|
const SKILL_VERSION = "0.3.0";
|
|
65
65
|
//#endregion
|
|
66
66
|
//#region src/settings.ts
|
|
@@ -79,56 +79,30 @@ window.__ModuleLoader__.load({
|
|
|
79
79
|
title: "库文件名",
|
|
80
80
|
tier: "common",
|
|
81
81
|
control: "text",
|
|
82
|
-
|
|
82
|
+
readonly: true,
|
|
83
|
+
resolveFrom: "dbFile",
|
|
84
|
+
hint: "数据目录下的库文件(备忘不建库,显示的是会落在哪)。只读,要改请编辑配置文件。"
|
|
83
85
|
},
|
|
84
86
|
{
|
|
85
87
|
key: "html.dir",
|
|
86
88
|
title: "HTML 产物目录名",
|
|
87
89
|
tier: "common",
|
|
88
90
|
control: "text",
|
|
89
|
-
|
|
91
|
+
readonly: true,
|
|
92
|
+
resolveFrom: "htmlDir",
|
|
93
|
+
hint: "数据目录下存放 HELP 页面的子目录名。只读,要改请编辑配置文件。"
|
|
90
94
|
},
|
|
91
95
|
{
|
|
92
96
|
key: "media.dir",
|
|
93
97
|
title: "附件目录",
|
|
94
98
|
tier: "common",
|
|
95
99
|
control: "directory",
|
|
96
|
-
|
|
100
|
+
prefillResolved: "mediaDir",
|
|
101
|
+
hint: "附件的存放根目录。留空=数据目录下的 media(目录须已存在,技能不替你建)。"
|
|
97
102
|
}
|
|
98
103
|
];
|
|
99
|
-
/**
|
|
100
|
-
const
|
|
101
|
-
{
|
|
102
|
-
key: "files.help",
|
|
103
|
-
title: "产物文件名主体 · HELP",
|
|
104
|
-
tier: "advanced",
|
|
105
|
-
control: "text",
|
|
106
|
-
hint: "HELP 文件名前缀,后面自动加时间戳。"
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
key: "files.lookup",
|
|
110
|
-
title: "产物文件名主体 · 速查表",
|
|
111
|
-
tier: "advanced",
|
|
112
|
-
control: "text",
|
|
113
|
-
hint: "速查表文件名前缀。"
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
key: "lark.cliPath",
|
|
117
|
-
title: "飞书 CLI 路径",
|
|
118
|
-
tier: "advanced",
|
|
119
|
-
control: "text",
|
|
120
|
-
hint: "飞书 CLI 的可执行文件路径。留空=自动探测。"
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
key: "lark.qrDir",
|
|
124
|
-
title: "飞书授权二维码落点",
|
|
125
|
-
tier: "advanced",
|
|
126
|
-
control: "directory",
|
|
127
|
-
hint: "飞书授权二维码 PNG 的存放目录,缺就现建。留空=系统临时目录。"
|
|
128
|
-
}
|
|
129
|
-
];
|
|
130
|
-
/** 设置页的行表,顺序即页面顺序。 */
|
|
131
|
-
const CONFIG_ITEMS = [...COMMON, ...ADVANCED];
|
|
104
|
+
/** 设置页的行表,顺序即页面顺序(#760 起高级组清空:删键 4 项出表,无高级项)。 */
|
|
105
|
+
const CONFIG_ITEMS = [...COMMON];
|
|
132
106
|
/** 常用项行数(页面上直接画出来的那些)。 */
|
|
133
107
|
const COMMON_ITEM_COUNT = COMMON.length;
|
|
134
108
|
/** 高级组标题与副文案。 */
|
|
@@ -334,15 +308,6 @@ window.__ModuleLoader__.load({
|
|
|
334
308
|
if (needle === "") return entries;
|
|
335
309
|
return entries.filter((entry) => entry.name.toLowerCase().includes(needle));
|
|
336
310
|
}
|
|
337
|
-
/** 给界面用的一句话位置说明:优先显示相对 home 的说法,省得整条绝对路径占满一行。 */
|
|
338
|
-
function locationLabel(listing) {
|
|
339
|
-
const home = listing.home.replace(/[\\/]+$/, "");
|
|
340
|
-
if (home !== "" && listing.path !== home && listing.path.startsWith(home)) {
|
|
341
|
-
const tail = listing.path.slice(home.length).replace(/^[\\/]+/, "");
|
|
342
|
-
if (tail !== "") return "~" + (listing.path.includes("\\") ? "\\" : "/") + tail;
|
|
343
|
-
}
|
|
344
|
-
return listing.path;
|
|
345
|
-
}
|
|
346
311
|
/** 新建文件夹的名字合不合法(单个路径段:不许分隔符、不许空、不许 `.`/`..`)。
|
|
347
312
|
*
|
|
348
313
|
* 与宿主 browse 后端的校验同口径——这里先拦一道,是为了在图上给得出人话,不是替代宿主校验。 */
|
|
@@ -721,14 +686,6 @@ window.__ModuleLoader__.load({
|
|
|
721
686
|
fontSize: 14,
|
|
722
687
|
fontWeight: 700
|
|
723
688
|
},
|
|
724
|
-
headTail: {
|
|
725
|
-
marginLeft: "auto",
|
|
726
|
-
fontSize: 12,
|
|
727
|
-
opacity: .72,
|
|
728
|
-
overflow: "hidden",
|
|
729
|
-
textOverflow: "ellipsis",
|
|
730
|
-
whiteSpace: "nowrap"
|
|
731
|
-
},
|
|
732
689
|
crumbs: {
|
|
733
690
|
display: "flex",
|
|
734
691
|
flexWrap: "wrap",
|
|
@@ -758,10 +715,6 @@ window.__ModuleLoader__.load({
|
|
|
758
715
|
padding: "0 12px 8px",
|
|
759
716
|
fontSize: 12
|
|
760
717
|
},
|
|
761
|
-
rootsLabel: {
|
|
762
|
-
opacity: .72,
|
|
763
|
-
marginRight: 2
|
|
764
|
-
},
|
|
765
718
|
rootButton: {
|
|
766
719
|
border: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.35))",
|
|
767
720
|
borderRadius: 6,
|
|
@@ -870,14 +823,11 @@ window.__ModuleLoader__.load({
|
|
|
870
823
|
});
|
|
871
824
|
return react.createElement("div", { style: S$1.crumbs }, parts);
|
|
872
825
|
}
|
|
873
|
-
/** 可跳转的根那一行(Windows
|
|
874
|
-
|
|
826
|
+
/** 可跳转的根那一行(Windows 上的盘符等):**就是本机全部磁盘**,故不加行首说明。
|
|
827
|
+
* **少于两个根就不画**:一个根没有「跳到别处」可言。 */
|
|
828
|
+
function rootsRow(state, onEnter) {
|
|
875
829
|
if (state.roots.length < 2) return null;
|
|
876
|
-
const parts =
|
|
877
|
-
key: "roots-label",
|
|
878
|
-
style: S$1.rootsLabel
|
|
879
|
-
}, labels.roots)];
|
|
880
|
-
for (const root of state.roots) parts.push(react.createElement("button", {
|
|
830
|
+
const parts = state.roots.map((root) => react.createElement("button", {
|
|
881
831
|
key: root.path,
|
|
882
832
|
type: "button",
|
|
883
833
|
style: {
|
|
@@ -887,11 +837,7 @@ window.__ModuleLoader__.load({
|
|
|
887
837
|
title: ROOT_KIND_TEXT[root.kind] ?? ROOT_KIND_TEXT.other,
|
|
888
838
|
onClick: () => onEnter(root.path)
|
|
889
839
|
}, root.path));
|
|
890
|
-
return react.createElement("div", {
|
|
891
|
-
style: S$1.roots,
|
|
892
|
-
role: "group",
|
|
893
|
-
"aria-label": labels.roots
|
|
894
|
-
}, parts);
|
|
840
|
+
return react.createElement("div", { style: S$1.roots }, parts);
|
|
895
841
|
}
|
|
896
842
|
/** 一行子目录:点名字进它,点「选」把它当目标(「选」再点一次取消)。 */
|
|
897
843
|
function entryRow(entry, selected, labels, onToggleSelect, onEnter) {
|
|
@@ -969,11 +915,10 @@ window.__ModuleLoader__.load({
|
|
|
969
915
|
if (!open) return null;
|
|
970
916
|
const rows = rowsOf(state);
|
|
971
917
|
const target = targetOf(state);
|
|
972
|
-
const
|
|
973
|
-
const hidden = hiddenCount(listing);
|
|
918
|
+
const hidden = hiddenCount(state.listing ?? EMPTY_LISTING);
|
|
974
919
|
const body = [];
|
|
975
920
|
body.push(crumbRow(state, props.onEnter));
|
|
976
|
-
body.push(rootsRow(state,
|
|
921
|
+
body.push(rootsRow(state, props.onEnter));
|
|
977
922
|
body.push(react.createElement("div", { style: S$1.pathRow }, react.createElement("input", {
|
|
978
923
|
style: S$1.input,
|
|
979
924
|
value: state.draft,
|
|
@@ -1040,12 +985,12 @@ window.__ModuleLoader__.load({
|
|
|
1040
985
|
role: "dialog",
|
|
1041
986
|
"aria-modal": true,
|
|
1042
987
|
"aria-label": labels.title
|
|
1043
|
-
}, react.createElement("div", { style: S$1.head }, react.createElement("span", { style: S$1.title }, labels.title), react.createElement("
|
|
1044
|
-
style: S$1.headTail,
|
|
1045
|
-
title: listing.path
|
|
1046
|
-
}, state.listing === null ? "" : locationLabel(listing)), react.createElement("button", {
|
|
988
|
+
}, react.createElement("div", { style: S$1.head }, react.createElement("span", { style: S$1.title }, labels.title), react.createElement("button", {
|
|
1047
989
|
type: "button",
|
|
1048
|
-
style:
|
|
990
|
+
style: {
|
|
991
|
+
...S$1.button,
|
|
992
|
+
marginLeft: "auto"
|
|
993
|
+
},
|
|
1049
994
|
"aria-label": labels.close,
|
|
1050
995
|
title: labels.close,
|
|
1051
996
|
onClick: props.onClose
|
|
@@ -1326,7 +1271,7 @@ window.__ModuleLoader__.load({
|
|
|
1326
1271
|
alive = false;
|
|
1327
1272
|
};
|
|
1328
1273
|
}, [props.getCall]);
|
|
1329
|
-
if (state.kind === "loading") return react.createElement("div", { style: S.card }, react.createElement("div", { style: S.muted }, "
|
|
1274
|
+
if (state.kind === "loading") return react.createElement("div", { style: S.card }, react.createElement("div", { style: S.muted }, "备忘录加载中"));
|
|
1330
1275
|
if (state.kind === "data") return react.createElement("div", { style: S.card }, react.createElement("div", { style: S.title }, SLOT_TITLE), react.createElement("div", { style: S.total }, `total ${state.total}`), react.createElement(VersionLine, null));
|
|
1331
1276
|
return react.createElement("div", { style: S.card }, react.createElement("div", { style: state.kind === "absent" ? S.muted : S.error }, state.message), react.createElement(VersionLine, null));
|
|
1332
1277
|
}
|
|
@@ -1392,24 +1337,42 @@ window.__ModuleLoader__.load({
|
|
|
1392
1337
|
function resetConfigSurface(call) {
|
|
1393
1338
|
return configRpc(call, RPC_ENDPOINT_CONFIG_RESET, {});
|
|
1394
1339
|
}
|
|
1395
|
-
/**
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1340
|
+
/** 只读行显示什么:标了 `resolveFrom` ⇒ 回执 `resolved` 组那一格;没标 ⇒ 配置文件里那个值本身。 */
|
|
1341
|
+
function readonlyTextOf(item, raw, prefill) {
|
|
1342
|
+
if (item.resolveFrom === void 0) return raw;
|
|
1343
|
+
const shown = prefill.resolved?.[item.resolveFrom];
|
|
1344
|
+
return typeof shown === "string" ? shown : "";
|
|
1345
|
+
}
|
|
1399
1346
|
function toDraft(values, prefill = {}) {
|
|
1400
1347
|
const draft = {};
|
|
1401
1348
|
for (const item of CONFIG_ITEMS) {
|
|
1402
1349
|
const v = readPath(values, item.key);
|
|
1403
1350
|
const raw = v === void 0 || v === null ? "" : String(v);
|
|
1351
|
+
if (item.readonly === true) {
|
|
1352
|
+
draft[item.key] = readonlyTextOf(item, raw, prefill);
|
|
1353
|
+
continue;
|
|
1354
|
+
}
|
|
1355
|
+
if (raw === "" && item.prefillResolved !== void 0) {
|
|
1356
|
+
const shown = prefill.resolved?.[item.prefillResolved];
|
|
1357
|
+
if (typeof shown === "string" && shown !== "") {
|
|
1358
|
+
draft[item.key] = shown;
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1404
1362
|
const fallback = item.prefillFrom === void 0 ? void 0 : prefill[item.prefillFrom];
|
|
1405
1363
|
draft[item.key] = raw === "" && typeof fallback === "string" && fallback !== "" ? fallback : raw;
|
|
1406
1364
|
}
|
|
1407
1365
|
return draft;
|
|
1408
1366
|
}
|
|
1409
|
-
/** 表单态 → 配置取值(按控件种类还原类型;空串对文本项照收,语义由「按默认落点」承担)。
|
|
1367
|
+
/** 表单态 → 配置取值(按控件种类还原类型;空串对文本项照收,语义由「按默认落点」承担)。
|
|
1368
|
+
*
|
|
1369
|
+
* **只读行不收**(#760,照 #749 样板):它们显示的是技能算好的绝对路径,写回配置就是把「显示的路径」
|
|
1370
|
+
* 当成「配置值」——保存只提交真能改的那些行(本家=`db.dir`/`media.dir` 两行),其余键由技能侧做组内
|
|
1371
|
+
* 合并保留现值。 */
|
|
1410
1372
|
function fromDraft(draft) {
|
|
1411
1373
|
const values = {};
|
|
1412
1374
|
for (const item of CONFIG_ITEMS) {
|
|
1375
|
+
if (item.readonly === true) continue;
|
|
1413
1376
|
const raw = draft[item.key] ?? "";
|
|
1414
1377
|
if (item.control === "number") {
|
|
1415
1378
|
const n = Number(raw);
|
|
@@ -1468,33 +1431,75 @@ window.__ModuleLoader__.load({
|
|
|
1468
1431
|
else if (outcome.kind === "unavailable") deps.onUnavailable(outcome.message);
|
|
1469
1432
|
};
|
|
1470
1433
|
}
|
|
1434
|
+
function copyPrompt(text, port) {
|
|
1435
|
+
const globalNavigator = globalThis.navigator;
|
|
1436
|
+
const channel = port !== void 0 ? port : globalNavigator?.clipboard ?? null;
|
|
1437
|
+
if (channel === null || typeof channel.writeText !== "function") return Promise.resolve(false);
|
|
1438
|
+
try {
|
|
1439
|
+
return Promise.resolve(channel.writeText(text)).then(() => true, () => false);
|
|
1440
|
+
} catch {
|
|
1441
|
+
return Promise.resolve(false);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
/** 「飞书 CLI」状态行(#760,定稿 #759;不是配置项):三档读数 + 复制安装指引按钮 + 官网链接。
|
|
1445
|
+
*
|
|
1446
|
+
* 判据由技能侧出(回执 `lark` 格),面板只显示:
|
|
1447
|
+
* · 没找到 CLI → 红「没找到飞书 CLI」+ 复制安装指引按钮 + 官网链接;
|
|
1448
|
+
* · 找到了但没登录/缺 task 权限 → 黄「找到了〈路径〉,但还没登录或没拿到 task 域授权」+ 同一个按钮 + 官网链接;
|
|
1449
|
+
* · 就绪 → 绿「已登录且 task 域可写:〈路径〉(〈版本〉)」+ 同一个按钮 + 官网链接。
|
|
1450
|
+
* 官网行三档逐字显示「飞书CLI官网为:https://www.feishu.cn/feishu-cli」,显示成文字+点一下新窗口跳转。
|
|
1451
|
+
* 旧技能(回执无 `lark` 格)⇒ 只显示一行弱提示,不报错、不探测。 */
|
|
1452
|
+
function LarkStatus(props) {
|
|
1453
|
+
const lark = props.lark;
|
|
1454
|
+
if (lark === void 0) return react.createElement("div", { style: S.rows }, react.createElement("div", { style: S.label }, "飞书 CLI"), react.createElement("div", { style: S.muted }, "状态未知(技能回执无此格,请升级技能包)。"));
|
|
1455
|
+
const status = lark.tier === "missing" ? "没找到飞书 CLI" : lark.tier === "partial" ? "找到了 " + (lark.cliPath ?? "飞书 CLI") + ",但还没登录或没拿到 task 域授权" : "已登录且 task 域可写:" + (lark.cliPath ?? "") + (lark.version !== null ? "(" + lark.version + ")" : "");
|
|
1456
|
+
const statusStyle = lark.tier === "full" ? S.okText : lark.tier === "partial" ? S.muted : S.error;
|
|
1457
|
+
return react.createElement("div", { style: S.rows }, react.createElement("div", { style: S.label }, "飞书 CLI"), react.createElement("div", { style: statusStyle }, status), react.createElement("div", { style: S.bar }, react.createElement("button", {
|
|
1458
|
+
style: S.btn,
|
|
1459
|
+
type: "button",
|
|
1460
|
+
onClick: () => props.onCopy(lark.prompt)
|
|
1461
|
+
}, "复制安装指引"), react.createElement("a", {
|
|
1462
|
+
href: lark.websiteUrl,
|
|
1463
|
+
target: "_blank",
|
|
1464
|
+
rel: "noreferrer"
|
|
1465
|
+
}, lark.websiteLine)));
|
|
1466
|
+
}
|
|
1471
1467
|
/** 一行输入(四种控件对齐受限 YAML 子集:文本/数字/布尔/目录)。
|
|
1472
1468
|
*
|
|
1473
1469
|
* 目录档=文本框 + 一枚唤起系统文件夹选择器的按钮;`onBrowse` 缺席(命名空间拿不到、
|
|
1474
|
-
* 或这条路已被拒)时不画按钮,文本框照旧——那是该缝自己的契约(供不了就收起入口,不是失败)。
|
|
1470
|
+
* 或这条路已被拒)时不画按钮,文本框照旧——那是该缝自己的契约(供不了就收起入口,不是失败)。
|
|
1471
|
+
*
|
|
1472
|
+
* **只读行(#760,照 #749 样板)**:`item.readonly` 为真时控件一律 `disabled`(值只经技能侧解析后显示、
|
|
1473
|
+
* 不给改),`onChange` 不接(不给「改得动」留假象);目录行的浏览按钮**保留但不可点击**
|
|
1474
|
+
* (定稿:入口不作废,只是不能改)。控件文案**不出现省略号**(#746 处置 9)——按钮就写
|
|
1475
|
+
* 「选择文件夹」/「浏览」两个字面。 */
|
|
1475
1476
|
function Row(props) {
|
|
1476
1477
|
const { item } = props;
|
|
1478
|
+
const readonly = item.readonly === true;
|
|
1479
|
+
const disabled = props.disabled || readonly;
|
|
1480
|
+
const onChange = readonly ? void 0 : (e) => props.onChange(item.key, e.target.value);
|
|
1477
1481
|
const control = item.control === "switch" ? react.createElement("input", {
|
|
1478
1482
|
type: "checkbox",
|
|
1479
1483
|
checked: props.value === "true",
|
|
1480
|
-
disabled
|
|
1481
|
-
onChange: (e) => props.onChange(item.key, e.target.checked ? "true" : "false")
|
|
1484
|
+
disabled,
|
|
1485
|
+
onChange: readonly ? void 0 : (e) => props.onChange(item.key, e.target.checked ? "true" : "false")
|
|
1482
1486
|
}) : react.createElement("input", {
|
|
1483
1487
|
style: S.input,
|
|
1484
1488
|
type: item.control === "number" ? "number" : "text",
|
|
1485
1489
|
value: props.value,
|
|
1486
|
-
disabled
|
|
1490
|
+
disabled,
|
|
1487
1491
|
spellCheck: false,
|
|
1488
|
-
onChange
|
|
1492
|
+
onChange
|
|
1489
1493
|
});
|
|
1490
|
-
/** 三态入口:供不了(`none`/缺席)就不画,不摆一个点了没反应的死按钮。
|
|
1494
|
+
/** 三态入口:供不了(`none`/缺席)就不画,不摆一个点了没反应的死按钮。
|
|
1495
|
+
* 只读行照画(按钮保留),但 `disabled` ⇒ 点不动。 */
|
|
1491
1496
|
const entry = props.browser ?? null;
|
|
1492
1497
|
const browse = item.control === "directory" && entry !== null && entry.mode !== "none" ? react.createElement("button", {
|
|
1493
1498
|
style: S.btnPick,
|
|
1494
1499
|
type: "button",
|
|
1495
|
-
disabled
|
|
1500
|
+
disabled,
|
|
1496
1501
|
onClick: () => entry.onOpen(item.key)
|
|
1497
|
-
}, entry.mode === "native" ? "
|
|
1502
|
+
}, entry.mode === "native" ? "选择文件夹" : "浏览") : null;
|
|
1498
1503
|
return react.createElement("div", { style: S.row }, react.createElement("div", { style: S.label }, item.title), react.createElement("div", { style: S.hint }, item.hint), browse === null ? control : react.createElement("div", { style: S.pickRow }, control, browse));
|
|
1499
1504
|
}
|
|
1500
1505
|
/** 技能设置页:承载备忘录自己的全部可配置项(只配置,不干活)。
|
|
@@ -1600,7 +1605,17 @@ window.__ModuleLoader__.load({
|
|
|
1600
1605
|
onOpen: onOpenRow
|
|
1601
1606
|
};
|
|
1602
1607
|
const surface = state.kind === "ready" ? state.surface : null;
|
|
1603
|
-
|
|
1608
|
+
/** 脏值只看**可改行**(#760,照 #749 样板):只读行显示的是技能算好的绝对路径,拿它当「改动」
|
|
1609
|
+
* 会让打开面板就变「未保存」。 */
|
|
1610
|
+
const editableItems = CONFIG_ITEMS.filter((i) => i.readonly !== true);
|
|
1611
|
+
const dirty = surface !== null && editableItems.some((i) => (draft[i.key] ?? "") !== (toDraft(surface.values, surface)[i.key] ?? ""));
|
|
1612
|
+
/** 复制安装指引(面板「飞书 CLI」状态行那枚按钮):成功落字,失败指到下方的全文手动复制。 */
|
|
1613
|
+
const onCopyPrompt = react.useCallback(async (prompt) => {
|
|
1614
|
+
setNotice(null);
|
|
1615
|
+
setError(null);
|
|
1616
|
+
if (await copyPrompt(prompt)) setNotice("已复制,去粘贴给 AI");
|
|
1617
|
+
else setError("复制失败,长按选择下方文本手动复制");
|
|
1618
|
+
}, []);
|
|
1604
1619
|
/** 写完(保存/重置)之后重新读一份整面,读到了才敢提示「已完成」。 */
|
|
1605
1620
|
const writeThenReload = react.useCallback(async (done) => {
|
|
1606
1621
|
setBusy(true);
|
|
@@ -1639,7 +1654,7 @@ window.__ModuleLoader__.load({
|
|
|
1639
1654
|
else setError(r.message);
|
|
1640
1655
|
}, [props.getCall, writeThenReload]);
|
|
1641
1656
|
const head = react.createElement("div", null, react.createElement("div", { style: S.title }, `${SLOT_TITLE} · 配置`), surface !== null ? react.createElement("div", null, react.createElement("div", { style: S.info }, `配置文件 ${surface.path}`), react.createElement("div", { style: S.info }, `数据目录 ${surface.dataDir}`), surface.created ? react.createElement("div", { style: S.muted }, "(配置文件刚按默认值生成)") : null) : null);
|
|
1642
|
-
if (state.kind === "loading") return react.createElement("div", { style: S.card }, head, react.createElement("div", { style: S.muted }, "
|
|
1657
|
+
if (state.kind === "loading") return react.createElement("div", { style: S.card }, head, react.createElement("div", { style: S.muted }, "配置读取中"), react.createElement(VersionLine, null));
|
|
1643
1658
|
if (state.kind === "failed") return react.createElement("div", { style: S.card }, react.createElement("div", { style: S.title }, `${SLOT_TITLE} · 配置`), react.createElement("div", { style: S.error }, state.message), react.createElement("div", { style: S.bar }, react.createElement("button", {
|
|
1644
1659
|
style: S.btn,
|
|
1645
1660
|
type: "button",
|
|
@@ -1659,12 +1674,15 @@ window.__ModuleLoader__.load({
|
|
|
1659
1674
|
onChange,
|
|
1660
1675
|
browser: rowEntry
|
|
1661
1676
|
});
|
|
1662
|
-
return react.createElement("div", { style: S.card }, head, react.createElement("div", { style: S.rows }, common.map(renderRow)), 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))
|
|
1677
|
+
return react.createElement("div", { style: S.card }, head, react.createElement("div", { style: S.rows }, common.map(renderRow)), advanced.length > 0 ? 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)) : null, react.createElement(LarkStatus, {
|
|
1678
|
+
lark: surface?.lark,
|
|
1679
|
+
onCopy: (prompt) => void onCopyPrompt(prompt)
|
|
1680
|
+
}), react.createElement("div", { style: S.bar }, react.createElement("button", {
|
|
1663
1681
|
style: dirty ? S.btnPrimary : S.btn,
|
|
1664
1682
|
type: "button",
|
|
1665
1683
|
disabled: busy || !dirty,
|
|
1666
1684
|
onClick: () => void onSave()
|
|
1667
|
-
}, busy ? "
|
|
1685
|
+
}, busy ? "处理中" : "保存"), react.createElement("button", {
|
|
1668
1686
|
style: S.btn,
|
|
1669
1687
|
type: "button",
|
|
1670
1688
|
disabled: busy,
|
|
@@ -1685,7 +1703,7 @@ window.__ModuleLoader__.load({
|
|
|
1685
1703
|
go: "转到",
|
|
1686
1704
|
showHidden: (n) => "显示隐藏目录(" + n + ")",
|
|
1687
1705
|
empty: "这个目录里没有子目录。",
|
|
1688
|
-
loading: "
|
|
1706
|
+
loading: "正在读取",
|
|
1689
1707
|
newFolder: "新建文件夹",
|
|
1690
1708
|
createConfirm: "创建",
|
|
1691
1709
|
createCancel: "取消",
|
|
@@ -1693,8 +1711,7 @@ window.__ModuleLoader__.load({
|
|
|
1693
1711
|
selected: "已选",
|
|
1694
1712
|
open: "选定这个目录",
|
|
1695
1713
|
cancel: "取消",
|
|
1696
|
-
willPick: "将选定:"
|
|
1697
|
-
roots: "其他磁盘:"
|
|
1714
|
+
willPick: "将选定:"
|
|
1698
1715
|
}
|
|
1699
1716
|
}) : null, notice !== null ? react.createElement("div", { style: S.okText }, notice) : null, error !== null ? react.createElement("div", { style: S.error }, error) : null, react.createElement(VersionLine, null));
|
|
1700
1717
|
}
|
|
@@ -1751,8 +1768,10 @@ window.__ModuleLoader__.load({
|
|
|
1751
1768
|
}
|
|
1752
1769
|
}
|
|
1753
1770
|
//#endregion
|
|
1771
|
+
exports.LarkStatus = LarkStatus;
|
|
1754
1772
|
exports.Row = Row;
|
|
1755
1773
|
exports.apply = apply;
|
|
1774
|
+
exports.copyPrompt = copyPrompt;
|
|
1756
1775
|
exports.createBrowseHandler = createBrowseHandler;
|
|
1757
1776
|
exports.directoryEntryMode = directoryEntryMode;
|
|
1758
1777
|
exports.fetchConfigSurface = fetchConfigSurface;
|