dsh-dock 0.4.1 → 0.5.0
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/README.md +93 -8
- package/client.js +1779 -178
- package/features/animation/host.js +516 -0
- package/features/animation/view.jsx +1451 -0
- package/features/balance/view.js +66 -41
- package/features/modelconfig/view.js +7 -4
- package/index.js +5 -9
- package/package.json +2 -2
- package/screenshots/dock-animation.png +0 -0
- package/screenshots/dock-robot.png +0 -0
- package/src/client.jsx +110 -48
- package/src/host-core.js +28 -1
- package/src/shared.js +24 -3
package/client.js
CHANGED
|
@@ -41,7 +41,7 @@ __export(client_exports, {
|
|
|
41
41
|
inject: () => inject
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(client_exports);
|
|
44
|
-
var
|
|
44
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
45
45
|
|
|
46
46
|
// src/shared.js
|
|
47
47
|
var import_react = __toESM(require("react"), 1);
|
|
@@ -70,9 +70,29 @@ var stateListeners = /* @__PURE__ */ new Set();
|
|
|
70
70
|
function notifyState() {
|
|
71
71
|
for (const fn of stateListeners) fn();
|
|
72
72
|
}
|
|
73
|
+
var FEATURE_STORE_KEY = "dsh-dock/features/v1";
|
|
74
|
+
var featurePersist = { map: {} };
|
|
75
|
+
try {
|
|
76
|
+
if (typeof localStorage !== "undefined") {
|
|
77
|
+
const raw = localStorage.getItem(FEATURE_STORE_KEY);
|
|
78
|
+
const obj = raw ? JSON.parse(raw) : null;
|
|
79
|
+
if (obj && typeof obj === "object") featurePersist.map = obj;
|
|
80
|
+
}
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
function persistFeatureEnabled() {
|
|
84
|
+
try {
|
|
85
|
+
if (typeof localStorage !== "undefined") localStorage.setItem(FEATURE_STORE_KEY, JSON.stringify(featurePersist.map));
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
}
|
|
73
89
|
function initFeatureState(defs) {
|
|
74
90
|
for (const f of defs) {
|
|
75
|
-
if (
|
|
91
|
+
if (featureState.has(f.id)) continue;
|
|
92
|
+
let enabled = !f.planned && f.defaultEnabled !== false;
|
|
93
|
+
const saved = featurePersist.map[f.id];
|
|
94
|
+
if (typeof saved === "boolean") enabled = saved;
|
|
95
|
+
featureState.set(f.id, { enabled, error: null });
|
|
76
96
|
}
|
|
77
97
|
}
|
|
78
98
|
function stateOf(id) {
|
|
@@ -86,6 +106,8 @@ function stateOf(id) {
|
|
|
86
106
|
function toggleFeature(id) {
|
|
87
107
|
const st = stateOf(id);
|
|
88
108
|
st.enabled = !st.enabled;
|
|
109
|
+
featurePersist.map[id] = st.enabled;
|
|
110
|
+
persistFeatureEnabled();
|
|
89
111
|
notifyState();
|
|
90
112
|
}
|
|
91
113
|
function subscribeFeatureState(fn) {
|
|
@@ -1025,6 +1047,11 @@ function ModelsView() {
|
|
|
1025
1047
|
import_react3.default.createElement("span", { className: "dkm-badge" }, vpDraft.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
|
|
1026
1048
|
import_react3.default.createElement("span", { className: "dkm-sub" }, "\u7EAF\u6587\u672C\u6A21\u578B\u6536\u5230\u56FE\u7247\u65F6\u81EA\u52A8\u8C03\u7528\u6240\u9009\u89C6\u89C9\u6A21\u578B\u8BC6\u522B\uFF0C\u8BC6\u522B\u6587\u672C\u66FF\u6362\u56FE\u7247\uFF1B\u591A\u6A21\u6001\u6A21\u578B\u539F\u6837\u81EA\u8BC6\u522B")
|
|
1027
1049
|
),
|
|
1050
|
+
import_react3.default.createElement(
|
|
1051
|
+
"div",
|
|
1052
|
+
{ className: "dkm-note dkm-warn" },
|
|
1053
|
+
"\u26A0 \u672C\u529F\u80FD\u4F1A\u8C03\u7528\u89C6\u89C9\u6A21\u578B\u8BC6\u522B\u56FE\u7247\uFF0C\u6D88\u8017 token\uFF08\u6BCF\u6B21\u8BC6\u56FE\u6309\u89C6\u89C9\u6A21\u578B\u8BA1\u8D39\uFF09\u3002\u9ED8\u8BA4\u5173\u95ED\uFF1B\u4E0D\u5F00\u542F\u5219\u63D2\u4EF6\u5176\u4F59\u529F\u80FD\u5747\u4E0D\u6D88\u8017\u4EFB\u4F55 token\u3002"
|
|
1054
|
+
),
|
|
1028
1055
|
import_react3.default.createElement(
|
|
1029
1056
|
"div",
|
|
1030
1057
|
{ className: "dkm-checks" },
|
|
@@ -1182,6 +1209,7 @@ var feature2 = {
|
|
|
1182
1209
|
description: "\u7F16\u8F91\u5404 Provider \u6A21\u578B\u76EE\u5F55\uFF1A\u8F93\u5165\u7C7B\u578B\uFF08\u6587\u672C/\u56FE\u7247 + \u6807\u6CE8\uFF09\u4E0E\u601D\u8003\u5F3A\u5EA6\u6863\u4F4D\uFF1B\u5199\u56DE\u5B98\u65B9\u914D\u7F6E\u70ED\u751F\u6548\uFF0C\u4F1A\u8BDD\u6A21\u578B\u9009\u62E9\u5668\u5373\u65F6\u53EF\u9009",
|
|
1183
1210
|
css: [
|
|
1184
1211
|
".dkm-note{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
1212
|
+
".dkm-warn{color:var(--dsw-alias-state-warning-primary);}",
|
|
1185
1213
|
".dkm-error{color:var(--dsw-alias-state-error-primary);font-size:12px;}",
|
|
1186
1214
|
".dkm-chips{display:flex;flex-wrap:wrap;gap:6px;}",
|
|
1187
1215
|
".dkm-chip{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);border-radius:999px;padding:3px 12px;font-family:inherit;font-size:12px;}",
|
|
@@ -1302,7 +1330,6 @@ var CURATED_ACCENTS = {
|
|
|
1302
1330
|
anthropic: "#d97757",
|
|
1303
1331
|
"google-gemini": "#4285f4"
|
|
1304
1332
|
};
|
|
1305
|
-
var C_TOTAL = "#34d399";
|
|
1306
1333
|
var C_GRANTED = "#22d3ee";
|
|
1307
1334
|
var C_TOPUP = "#fbbf24";
|
|
1308
1335
|
var C_ERR = "#f87171";
|
|
@@ -1378,10 +1405,12 @@ function BalanceView(props) {
|
|
|
1378
1405
|
} else if (providers.length === 0) {
|
|
1379
1406
|
body.push(import_react6.default.createElement("div", { key: "empty", className: "dkb-note" }, "\u6CA1\u6709\u627E\u5230\u5DF2\u914D\u7F6E\u7684\u6A21\u578B Provider"));
|
|
1380
1407
|
} else {
|
|
1408
|
+
const rank = (p) => p.balance && p.balance.status === "ok" ? 0 : p.balance && p.balance.status === "login-required" ? 1 : 2;
|
|
1409
|
+
const sorted = providers.slice().sort((a, b) => rank(a) - rank(b));
|
|
1381
1410
|
body.push(import_react6.default.createElement(
|
|
1382
1411
|
"div",
|
|
1383
1412
|
{ key: "rows", className: "dkb-rows" },
|
|
1384
|
-
|
|
1413
|
+
sorted.map((p) => {
|
|
1385
1414
|
const accent = accentOf(p.id);
|
|
1386
1415
|
const b = p.balance;
|
|
1387
1416
|
let badge = ["\u672A\u77E5", ""];
|
|
@@ -1392,48 +1421,64 @@ function BalanceView(props) {
|
|
|
1392
1421
|
else if (b.status === "login-required") badge = ["\u9700\u767B\u5F55", "warn"];
|
|
1393
1422
|
else badge = ["\u67E5\u8BE2\u5931\u8D25", "err"];
|
|
1394
1423
|
}
|
|
1395
|
-
const sub = ["ID: " + p.id, p.api ? "api: " + p.api : null, p.baseURL ? p.baseURL : null].filter(Boolean).join(" \xB7 ");
|
|
1396
|
-
const cells = [];
|
|
1397
1424
|
let balBody = null;
|
|
1398
1425
|
if (b && b.status === "ok" && b.kind === "quota") {
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
import_react6.default.createElement(
|
|
1404
|
-
import_react6.default.createElement("span", { className: "dkb-part" }, "\u5DF2\u7528 " + fmt(b.used) + " / \u603B " + fmt(b.limit)),
|
|
1405
|
-
b.resetTime ? import_react6.default.createElement("span", { className: "dkb-part" }, "\u91CD\u7F6E " + String(b.resetTime).slice(0, 16)) : null
|
|
1406
|
-
));
|
|
1407
|
-
(Array.isArray(b.dims) ? b.dims : []).forEach((d, i) => {
|
|
1408
|
-
cells.push(import_react6.default.createElement(
|
|
1426
|
+
const dims = Array.isArray(b.dims) ? b.dims : [];
|
|
1427
|
+
balBody = import_react6.default.createElement(
|
|
1428
|
+
import_react6.default.Fragment,
|
|
1429
|
+
null,
|
|
1430
|
+
import_react6.default.createElement(
|
|
1409
1431
|
"div",
|
|
1410
|
-
{
|
|
1411
|
-
import_react6.default.createElement("span", { className: "dkb-
|
|
1412
|
-
import_react6.default.createElement("span", { className: "dkb-
|
|
1413
|
-
import_react6.default.createElement(
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1432
|
+
{ className: "dkb-main" },
|
|
1433
|
+
import_react6.default.createElement("span", { className: "dkb-main-label" }, "\u5269\u4F59\u989D\u5EA6"),
|
|
1434
|
+
import_react6.default.createElement("span", { className: "dkb-main-value" }, fmt(b.remaining) + (b.unit ? " " + b.unit : "")),
|
|
1435
|
+
import_react6.default.createElement(
|
|
1436
|
+
"span",
|
|
1437
|
+
{ className: "dkb-main-part" },
|
|
1438
|
+
"\u5DF2\u7528 " + fmt(b.used) + " / \u603B " + fmt(b.limit),
|
|
1439
|
+
b.resetTime ? import_react6.default.createElement("span", null, " \xB7 \u91CD\u7F6E " + String(b.resetTime).slice(0, 10)) : null
|
|
1440
|
+
)
|
|
1441
|
+
),
|
|
1442
|
+
dims.map((d, i) => import_react6.default.createElement(
|
|
1443
|
+
"div",
|
|
1444
|
+
{ key: "d" + i, className: "dkb-dim" },
|
|
1445
|
+
import_react6.default.createElement("span", { className: "dkb-dim-label" }, d.window === "weekly" ? "\u5468\u989D\u5EA6" : "\u5C0F\u65F6\u989D\u5EA6"),
|
|
1446
|
+
import_react6.default.createElement(
|
|
1447
|
+
"span",
|
|
1448
|
+
{ className: "dkb-dim-bar" },
|
|
1449
|
+
import_react6.default.createElement("span", { className: "dkb-dim-fill", style: { width: (d.limit > 0 ? Math.min(100, Math.round(d.remaining / d.limit * 100)) : 0) + "%" } })
|
|
1450
|
+
),
|
|
1451
|
+
import_react6.default.createElement("span", { className: "dkb-dim-text" }, "\u5269 " + fmt(d.remaining) + " / " + fmt(d.limit))
|
|
1452
|
+
))
|
|
1453
|
+
);
|
|
1417
1454
|
} else if (b && b.status === "ok") {
|
|
1418
1455
|
const infos = Array.isArray(b.infos) ? b.infos : [];
|
|
1419
|
-
|
|
1456
|
+
balBody = import_react6.default.createElement(
|
|
1420
1457
|
"div",
|
|
1421
|
-
{
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1458
|
+
{ className: "dkb-mains" },
|
|
1459
|
+
infos.map((i, idx) => import_react6.default.createElement(
|
|
1460
|
+
"div",
|
|
1461
|
+
{ key: idx, className: "dkb-main" },
|
|
1462
|
+
import_react6.default.createElement("span", { className: "dkb-main-label", style: { color: accent } }, i.currency),
|
|
1463
|
+
import_react6.default.createElement("span", { className: "dkb-main-value" }, fmt(i.totalBalance)),
|
|
1464
|
+
import_react6.default.createElement(
|
|
1465
|
+
"span",
|
|
1466
|
+
{ className: "dkb-main-parts" },
|
|
1467
|
+
i.grantedBalance != null ? import_react6.default.createElement("span", { className: "dkb-main-part", style: { color: C_GRANTED } }, "\u8D60\u9001 " + fmt(i.grantedBalance)) : null,
|
|
1468
|
+
i.toppedUpBalance != null ? import_react6.default.createElement("span", { className: "dkb-main-part", style: { color: C_TOPUP } }, "\u5145\u503C " + fmt(i.toppedUpBalance)) : null
|
|
1469
|
+
)
|
|
1470
|
+
))
|
|
1471
|
+
);
|
|
1427
1472
|
} else if (b && b.status === "login-required" && b.consoleUrl) {
|
|
1428
1473
|
balBody = import_react6.default.createElement(
|
|
1429
1474
|
"div",
|
|
1430
|
-
{ className: "dkb-
|
|
1475
|
+
{ className: "dkb-main" },
|
|
1431
1476
|
import_react6.default.createElement("a", { href: b.consoleUrl, target: "_blank", rel: "noreferrer", className: "dkb-link", style: { color: accent } }, "\u53BB\u63A7\u5236\u53F0\u67E5\u770B\u4F59\u989D \u2192")
|
|
1432
1477
|
);
|
|
1433
1478
|
} else {
|
|
1434
|
-
balBody = import_react6.default.createElement("div", { className: "dkb-note" }, b
|
|
1479
|
+
balBody = b && b.message ? import_react6.default.createElement("div", { className: "dkb-note" }, b.message) : import_react6.default.createElement("div", { className: "dkb-note" }, "\u8BE5 Provider \u6CA1\u6709\u5DF2\u77E5\u7684\u4F59\u989D\u67E5\u8BE2\u63A5\u53E3");
|
|
1435
1480
|
}
|
|
1436
|
-
|
|
1481
|
+
const sub = ["ID " + p.id, p.api, p.baseURL ? p.baseURL.replace(/^https?:\/\//, "") : null].filter(Boolean).join(" \xB7 ");
|
|
1437
1482
|
return import_react6.default.createElement(
|
|
1438
1483
|
"div",
|
|
1439
1484
|
{ key: p.id, className: "dkb-row", "data-dock-provider": p.id },
|
|
@@ -1443,7 +1488,17 @@ function BalanceView(props) {
|
|
|
1443
1488
|
import_react6.default.createElement("span", { className: "dkb-dot", style: { background: accent } }),
|
|
1444
1489
|
import_react6.default.createElement("span", { className: "dkb-name", style: { color: accent } }, p.displayName),
|
|
1445
1490
|
def === p.id ? import_react6.default.createElement("span", { className: "dkb-default" }, "\u9ED8\u8BA4") : null,
|
|
1446
|
-
import_react6.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0])
|
|
1491
|
+
import_react6.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0]),
|
|
1492
|
+
// 模型数折叠提示(点开展开 chips)
|
|
1493
|
+
p.models && p.models.length > 0 ? import_react6.default.createElement("button", {
|
|
1494
|
+
type: "button",
|
|
1495
|
+
className: "dkb-models-toggle",
|
|
1496
|
+
title: p.models.join(", "),
|
|
1497
|
+
onClick: (e) => {
|
|
1498
|
+
const row = e.currentTarget.closest(".dkb-row");
|
|
1499
|
+
if (row) row.classList.toggle("dkb-models-open");
|
|
1500
|
+
}
|
|
1501
|
+
}, p.models.length + " \u4E2A\u6A21\u578B \u25BE") : null
|
|
1447
1502
|
),
|
|
1448
1503
|
sub ? import_react6.default.createElement("div", { className: "dkb-sub" }, sub) : null,
|
|
1449
1504
|
p.apiKeyEnv ? import_react6.default.createElement("div", { className: "dkb-sub" }, "\u5BC6\u94A5: " + p.apiKeyEnv + (p.credentialConfigured ? " \u2713" : " \u2717")) : null,
|
|
@@ -1465,7 +1520,7 @@ function BalanceView(props) {
|
|
|
1465
1520
|
import_react6.default.createElement(
|
|
1466
1521
|
"div",
|
|
1467
1522
|
{ className: "dkb-note" },
|
|
1468
|
-
data && !snap.error && providers.length > 0 ? okCount + "/" + providers.length + " \u4E2A Provider \u53EF\u67E5\u4F59\u989D" : "\u6A21\u578B\u4F59\u989D \xB7 Host \u534A\u90E8\u5B9E\u65F6\u62C9\u53D6"
|
|
1523
|
+
data && !snap.error && providers.length > 0 ? okCount + "/" + providers.length + " \u4E2A Provider \u53EF\u67E5\u4F59\u989D\uFF08\u53EF\u67E5\u7684\u6392\u524D\u9762\uFF09" : "\u6A21\u578B\u4F59\u989D \xB7 Host \u534A\u90E8\u5B9E\u65F6\u62C9\u53D6"
|
|
1469
1524
|
),
|
|
1470
1525
|
body,
|
|
1471
1526
|
import_react6.default.createElement(
|
|
@@ -1571,8 +1626,9 @@ var feature5 = {
|
|
|
1571
1626
|
css: [
|
|
1572
1627
|
".dkb-note{color:var(--dsw-alias-label-secondary);font-size:12px;}",
|
|
1573
1628
|
".dkb-error{color:var(--dsw-alias-state-error-primary);}",
|
|
1574
|
-
".dkb-rows{display:flex;flex-direction:column;gap:
|
|
1575
|
-
|
|
1629
|
+
".dkb-rows{display:flex;flex-direction:column;gap:10px;}",
|
|
1630
|
+
// Provider 卡片:行距收窄、留白分层
|
|
1631
|
+
".dkb-row{border:1px solid var(--dsw-alias-border-l1);border-radius:10px;padding:10px 14px 12px;display:flex;flex-direction:column;gap:6px;}",
|
|
1576
1632
|
".dkb-row-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}",
|
|
1577
1633
|
".dkb-dot{width:8px;height:8px;border-radius:50%;flex:none;}",
|
|
1578
1634
|
".dkb-name{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);}",
|
|
@@ -1581,13 +1637,28 @@ var feature5 = {
|
|
|
1581
1637
|
".dkb-badge.ok{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
1582
1638
|
".dkb-badge.warn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor;}",
|
|
1583
1639
|
".dkb-badge.err{color:var(--dsw-alias-state-error-primary);border-color:currentColor;}",
|
|
1640
|
+
// 模型数折叠开关(点行头右侧"N 个模型 ▾"展开/收起 chips)
|
|
1641
|
+
".dkb-models-toggle{margin-left:auto;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);font-family:inherit;font-size:11px;padding:1px 6px;border-radius:6px;white-space:nowrap;}",
|
|
1642
|
+
".dkb-models-toggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
1643
|
+
".dkb-row:not(.dkb-models-open) .dkb-chips{display:none;}",
|
|
1644
|
+
'.dkb-row.dkb-models-open .dkb-models-toggle::after{content:"";}',
|
|
1645
|
+
// 连接信息弱化单行(省略 URL 协议头、超出省略号)
|
|
1584
1646
|
".dkb-sub{color:var(--dsw-alias-label-tertiary);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1585
|
-
".dkb-chips{display:flex;flex-wrap:wrap;gap:4px;}",
|
|
1647
|
+
".dkb-chips{display:flex;flex-wrap:wrap;gap:4px;padding:2px 0 4px;}",
|
|
1586
1648
|
".dkb-chip{font-size:10px;border-radius:6px;padding:1px 6px;}",
|
|
1587
|
-
|
|
1588
|
-
".dkb-
|
|
1589
|
-
".dkb-
|
|
1590
|
-
".dkb-
|
|
1649
|
+
// 余额主数字卡(大号数字 + 小字辅助信息;多币种横排多卡)
|
|
1650
|
+
".dkb-mains{display:flex;gap:12px;flex-wrap:wrap;}",
|
|
1651
|
+
".dkb-main{display:flex;flex-direction:column;gap:2px;padding:8px 12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);min-width:150px;}",
|
|
1652
|
+
".dkb-main-label{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
1653
|
+
".dkb-main-value{font-size:20px;font-weight:700;color:var(--dsw-alias-state-success-primary);font-variant-numeric:tabular-nums;line-height:1.2;}",
|
|
1654
|
+
".dkb-main-parts{display:flex;gap:10px;flex-wrap:wrap;}",
|
|
1655
|
+
".dkb-main-part{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
1656
|
+
// 配额维度条(周/小时额度:进度条 + 剩余/总量)
|
|
1657
|
+
".dkb-dim{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--dsw-alias-label-secondary);}",
|
|
1658
|
+
".dkb-dim-label{flex:none;min-width:44px;color:var(--dsw-alias-label-tertiary);}",
|
|
1659
|
+
".dkb-dim-bar{flex:1;max-width:220px;height:5px;border-radius:3px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);overflow:hidden;}",
|
|
1660
|
+
".dkb-dim-fill{display:block;height:100%;border-radius:3px;background:linear-gradient(90deg,var(--dsw-alias-state-success-primary),color-mix(in srgb,var(--dsw-alias-state-success-primary) 60%,#fff));}",
|
|
1661
|
+
".dkb-dim-text{flex:none;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;}",
|
|
1591
1662
|
".dkb-link{font-size:12px;text-decoration:none;}",
|
|
1592
1663
|
".dkb-link:hover{text-decoration:underline;}",
|
|
1593
1664
|
".dkb-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--dsw-alias-label-tertiary);font-size:12px;}",
|
|
@@ -1602,15 +1673,1473 @@ var feature5 = {
|
|
|
1602
1673
|
Chip: BalanceChip
|
|
1603
1674
|
};
|
|
1604
1675
|
|
|
1605
|
-
//
|
|
1606
|
-
var
|
|
1607
|
-
var
|
|
1608
|
-
|
|
1609
|
-
|
|
1676
|
+
// features/animation/view.jsx
|
|
1677
|
+
var import_react7 = require("react");
|
|
1678
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1679
|
+
function rpcCall2(method, args) {
|
|
1680
|
+
return fetch("/dsh-dock/animation/" + method, {
|
|
1681
|
+
method: "POST",
|
|
1682
|
+
headers: { "content-type": "application/json" },
|
|
1683
|
+
body: JSON.stringify(args === void 0 ? {} : args)
|
|
1684
|
+
}).then(async (res) => {
|
|
1685
|
+
const data = await res.json().catch(() => ({}));
|
|
1686
|
+
if (res.ok && data && data.ok === true) return data.data;
|
|
1687
|
+
if (res.status === 405 || res.status === 404) {
|
|
1688
|
+
throw new Error("\u5BBF\u4E3B\u8FDB\u7A0B\u662F\u65E7\u7248\u672C\uFF08\u6CA1\u6709\u4EFB\u52A1\u52A8\u753B\u8DEF\u7531\uFF09\uFF0C\u91CD\u542F dsh web \u540E\u91CD\u8BD5");
|
|
1689
|
+
}
|
|
1690
|
+
if (data && data.ok === false) throw new Error(data.error && data.error.message || "HTTP " + res.status);
|
|
1691
|
+
throw new Error("HTTP " + res.status + (data && data.error && data.error.message ? ": " + data.error.message : ""));
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
var EFFECT_MODES = [
|
|
1695
|
+
{ id: "flow", name: "\u6D41\u5149\u7EC6\u7EBF", desc: "\u9876\u90E8\u7EC6\u7EBF\u6D41\u5149\u5F80\u8FD4\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\u52A0\u5FEB" },
|
|
1696
|
+
{ id: "breathe", name: "\u547C\u5438\u5149\u70B9", desc: "\u72B6\u6001\u5FBD\u6807\u5706\u70B9\u547C\u5438\uFF0C\u8D8A\u5FD9\u547C\u5438\u8D8A\u5FEB" },
|
|
1697
|
+
{ id: "ring", name: "\u8F68\u9053\u5149\u73AF", desc: "\u7EC6\u73AF\u7ED5\u5706\u70B9\u65CB\u8F6C\uFF0C\u8F6C\u901F\u968F\u4EFB\u52A1\u901F\u5EA6" },
|
|
1698
|
+
{ id: "orbit", name: "\u73AF\u5C4F\u5DE1\u822A", desc: "\u4E00\u9897\u5149\u70B9\u6CBF\u5C4F\u5E55\u8FB9\u7F18\u5DE1\u822A\u6574\u5708\uFF0C\u9192\u76EE\u4E0D\u906E\u6321" },
|
|
1699
|
+
{ id: "robot", name: "\u684C\u9762\u4F19\u4F34", desc: "\u66F4\u5177\u8C61\u7684\u4EBA\u7269\u5750\u9547\u56DB\u5C4F\u5DE5\u4F4D\uFF1A\u601D\u8003\u3001\u8F93\u51FA\u3001\u67E5\u8D44\u6599\u968F\u4EFB\u52A1\u9636\u6BB5\u5207\u6362" },
|
|
1700
|
+
{ id: "matrix", name: "\u4EE3\u7801\u96E8", desc: "\u5B57\u7B26\u6CBF\u5C4F\u5E55\u7F13\u843D\u5982\u6570\u636E\u6D41\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\uFF0C\u514B\u5236\u7684\u4F4E\u900F\u660E\u5EA6" },
|
|
1701
|
+
{ id: "stars", name: "\u661F\u91CE", desc: "\u7EC6\u788E\u661F\u70B9\u7F13\u6162\u98D8\u79FB\u95EA\u70C1\uFF0C\u5B89\u9759\u8010\u770B\u7684\u80CC\u666F\u6C1B\u56F4" },
|
|
1702
|
+
{ id: "aurora", name: "\u6781\u5149", desc: "\u5C4F\u5E55\u9876\u90E8\u67D4\u5149\u5E26\u7F13\u6162\u547C\u5438\u6D41\u52A8\uFF0C\u50CF\u6781\u5149\u62C2\u8FC7" }
|
|
1610
1703
|
];
|
|
1611
|
-
var
|
|
1612
|
-
|
|
1704
|
+
var PHASE_LABELS = { think: "\u601D\u8003\u4E2D", write: "\u8F93\u51FA\u4E2D", code: "\u7F16\u5199\u4EE3\u7801", search: "\u67E5\u8D44\u6599" };
|
|
1705
|
+
function phaseLabel(p) {
|
|
1706
|
+
return PHASE_LABELS[p] || "\u5DE5\u4F5C\u4E2D";
|
|
1707
|
+
}
|
|
1708
|
+
var END_LABELS = {
|
|
1709
|
+
completed: { label: "\u5B8C\u6210", cls: "ok" },
|
|
1710
|
+
error: { label: "\u51FA\u9519", cls: "err" },
|
|
1711
|
+
aborted: { label: "\u5DF2\u4E2D\u6B62", cls: "warn" },
|
|
1712
|
+
blocked: { label: "\u53D7\u963B", cls: "warn" },
|
|
1713
|
+
"max-tokens": { label: "\u8FBE\u8F93\u51FA\u4E0A\u9650", cls: "warn" },
|
|
1714
|
+
interrupted: { label: "\u4E2D\u65AD", cls: "warn" }
|
|
1715
|
+
};
|
|
1716
|
+
function endInfo(reason) {
|
|
1717
|
+
return END_LABELS[reason] || END_LABELS.completed;
|
|
1718
|
+
}
|
|
1719
|
+
function isSuccessReason(reason) {
|
|
1720
|
+
return !reason || reason === "completed";
|
|
1721
|
+
}
|
|
1722
|
+
function fmtNum2(n) {
|
|
1723
|
+
return (Number(n) || 0).toLocaleString("en-US");
|
|
1724
|
+
}
|
|
1725
|
+
function fmtCompact2(n) {
|
|
1726
|
+
n = Number(n) || 0;
|
|
1727
|
+
if (n >= 1e6) return (n / 1e6).toFixed(2) + "M";
|
|
1728
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "K";
|
|
1729
|
+
return String(Math.round(n));
|
|
1730
|
+
}
|
|
1731
|
+
function fmtDur(ms) {
|
|
1732
|
+
const s = Math.max(0, Math.round((ms || 0) / 1e3));
|
|
1733
|
+
const h = Math.floor(s / 3600), m = Math.floor(s % 3600 / 60), sec = s % 60;
|
|
1734
|
+
if (h > 0) return h + "\u5C0F\u65F6" + m + "\u5206" + sec + "\u79D2";
|
|
1735
|
+
if (m > 0) return m + "\u5206" + sec + "\u79D2";
|
|
1736
|
+
return sec + "\u79D2";
|
|
1737
|
+
}
|
|
1738
|
+
function fmtClock(ms) {
|
|
1739
|
+
const s = Math.max(0, Math.floor((ms || 0) / 1e3));
|
|
1740
|
+
const h = Math.floor(s / 3600), m = Math.floor(s % 3600 / 60), sec = s % 60;
|
|
1741
|
+
const p = (x) => String(x).padStart(2, "0");
|
|
1742
|
+
return h > 0 ? h + ":" + p(m) + ":" + p(sec) : p(m) + ":" + p(sec);
|
|
1743
|
+
}
|
|
1744
|
+
function fmtTime2(ts) {
|
|
1745
|
+
if (!ts) return "";
|
|
1746
|
+
const d = new Date(ts);
|
|
1747
|
+
const p = (x) => String(x).padStart(2, "0");
|
|
1748
|
+
return p(d.getHours()) + ":" + p(d.getMinutes()) + ":" + p(d.getSeconds());
|
|
1749
|
+
}
|
|
1750
|
+
function truncate(str, max) {
|
|
1751
|
+
if (!str) return "";
|
|
1752
|
+
return String(str).length > max ? String(str).slice(0, max) + "\u2026" : str;
|
|
1753
|
+
}
|
|
1754
|
+
var animationStore = {
|
|
1755
|
+
snap: { status: null, loading: false, error: null },
|
|
1756
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
1757
|
+
subscribe(fn) {
|
|
1758
|
+
this.listeners.add(fn);
|
|
1759
|
+
return () => {
|
|
1760
|
+
this.listeners.delete(fn);
|
|
1761
|
+
};
|
|
1762
|
+
},
|
|
1763
|
+
emit() {
|
|
1764
|
+
for (const fn of this.listeners) fn();
|
|
1765
|
+
},
|
|
1766
|
+
applyConfig(cfg) {
|
|
1767
|
+
if (this.snap.status) {
|
|
1768
|
+
this.snap = Object.assign({}, this.snap, { status: Object.assign({}, this.snap.status, { config: cfg }) });
|
|
1769
|
+
this.emit();
|
|
1770
|
+
}
|
|
1771
|
+
},
|
|
1772
|
+
refresh() {
|
|
1773
|
+
if (this.snap.loading) return Promise.resolve();
|
|
1774
|
+
this.snap = Object.assign({}, this.snap, { loading: true });
|
|
1775
|
+
this.emit();
|
|
1776
|
+
return rpcCall2("status").then((data) => {
|
|
1777
|
+
this.snap = { status: data, loading: false, error: null };
|
|
1778
|
+
this.emit();
|
|
1779
|
+
}).catch((e) => {
|
|
1780
|
+
this.snap = Object.assign({}, this.snap, { loading: false, error: e && e.message || String(e) });
|
|
1781
|
+
this.emit();
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
function useAnimation() {
|
|
1786
|
+
const [snap, setSnap] = (0, import_react7.useState)(animationStore.snap);
|
|
1787
|
+
(0, import_react7.useEffect)(() => animationStore.subscribe(() => setSnap(animationStore.snap)), []);
|
|
1788
|
+
return snap;
|
|
1789
|
+
}
|
|
1790
|
+
function useTicker(ctx, active) {
|
|
1791
|
+
const [, bump] = (0, import_react7.useState)(0);
|
|
1792
|
+
(0, import_react7.useEffect)(() => {
|
|
1793
|
+
if (!active) return;
|
|
1794
|
+
if (ctx && typeof ctx.interval === "function") return ctx.interval(bump, 1e3);
|
|
1795
|
+
const t = setInterval(bump, 1e3);
|
|
1796
|
+
return () => clearInterval(t);
|
|
1797
|
+
}, [active]);
|
|
1798
|
+
}
|
|
1799
|
+
function Box3(props) {
|
|
1800
|
+
const w = props.w, h = props.h, d = props.d;
|
|
1801
|
+
const faces = [
|
|
1802
|
+
[w, h, "translate(-50%,-50%) translateZ(" + d / 2 + "px)"],
|
|
1803
|
+
[w, h, "translate(-50%,-50%) rotateY(180deg) translateZ(" + d / 2 + "px)"],
|
|
1804
|
+
[d, h, "translate(-50%,-50%) rotateY(90deg) translateZ(" + w / 2 + "px)"],
|
|
1805
|
+
[d, h, "translate(-50%,-50%) rotateY(-90deg) translateZ(" + w / 2 + "px)"],
|
|
1806
|
+
[w, d, "translate(-50%,-50%) rotateX(90deg) translateZ(" + h / 2 + "px)"],
|
|
1807
|
+
[w, d, "translate(-50%,-50%) rotateX(-90deg) translateZ(" + h / 2 + "px)"]
|
|
1808
|
+
];
|
|
1809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1810
|
+
"span",
|
|
1811
|
+
{
|
|
1812
|
+
className: "dk3-box " + (props.cls || ""),
|
|
1813
|
+
style: Object.assign(
|
|
1814
|
+
{ width: w, height: h, left: props.x - w / 2, top: props.y - h / 2 },
|
|
1815
|
+
props.z ? { transform: "translateZ(" + props.z + "px)" } : null,
|
|
1816
|
+
props.style
|
|
1817
|
+
),
|
|
1818
|
+
children: [
|
|
1819
|
+
faces.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-face", style: { width: f[0], height: f[1], transform: f[2] } }, i)),
|
|
1820
|
+
props.children
|
|
1821
|
+
]
|
|
1822
|
+
}
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1825
|
+
function Monitor3(props) {
|
|
1826
|
+
const w = props.w, h = props.h;
|
|
1827
|
+
const lines = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
|
|
1828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1829
|
+
"span",
|
|
1830
|
+
{
|
|
1831
|
+
className: "dk3-mon3 " + (props.cls || ""),
|
|
1832
|
+
style: { left: props.x - w / 2, top: props.y - h / 2, width: w, height: h, transform: "translateZ(" + (props.z || -3) + "px) rotateY(" + (props.ry || 0) + "deg)" },
|
|
1833
|
+
children: [
|
|
1834
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w, h, d: 5, cls: "dk3-frame", x: w / 2, y: h / 2 }),
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-screen", style: { width: w - 4, height: h - 4, transform: "translate(-50%,-50%) translateZ(3.1px)" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-code", children: [
|
|
1836
|
+
lines.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)),
|
|
1837
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-cur" })
|
|
1838
|
+
] }) })
|
|
1839
|
+
]
|
|
1840
|
+
}
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
function RobotScene(props) {
|
|
1844
|
+
const phase = props && props.phase ? props.phase : "code";
|
|
1845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-bot-scene", "data-phase": phase, "aria-hidden": "true", children: [
|
|
1846
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-world", children: [
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 150, h: 7, d: 40, cls: "dk3-desk", x: 115, y: 78 }),
|
|
1848
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 26, d: 32, cls: "dk3-metal dk3-leg", x: 48, y: 94 }),
|
|
1849
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 26, d: 32, cls: "dk3-metal dk3-leg", x: 182, y: 94 }),
|
|
1850
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 34, h: 24, x: 140, y: 60, ry: 24, cls: "left" }),
|
|
1851
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 40, h: 30, x: 168, y: 58, ry: 0, cls: "center" }),
|
|
1852
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 28, h: 21, x: 188, y: 62, ry: -24, cls: "right" }),
|
|
1853
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 30, h: 20, x: 168, y: 28, ry: 0, cls: "top" }),
|
|
1854
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 126, y: 73, z: 14 }),
|
|
1855
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 5, d: 4, cls: "dk3-mug", x: 140, y: 71, z: 14 }),
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-person", children: [
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 30, d: 22, cls: "dk3-chairback", x: 2, y: 42 }),
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 20, h: 4, d: 22, cls: "dk3-chairseat", x: 12, y: 58 }),
|
|
1859
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 12, d: 3, cls: "dk3-metal", x: 12, y: 68 }),
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 14, h: 2, d: 14, cls: "dk3-metal", x: 12, y: 74 }),
|
|
1861
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 13, h: 5, d: 9, cls: "dk3-pants", x: 20, y: 54 }),
|
|
1862
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 12, d: 4, cls: "dk3-pants", x: 26, y: 62 }),
|
|
1863
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 6, h: 3, d: 5, cls: "dk3-shoe", x: 28, y: 73 }),
|
|
1864
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 15, h: 20, d: 11, cls: "dk3-hood dk3-torso", x: 12, y: 36 }),
|
|
1865
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 8, d: 9, cls: "dk3-hood dk3-hoodbump", x: 5, y: 30 }),
|
|
1866
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 3, d: 4, cls: "dk3-skin", x: 14, y: 25 }),
|
|
1867
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-head3", children: [
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box3, { w: 13, h: 12, d: 12, cls: "dk3-skin dk3-headbox", x: 8, y: 10, children: [
|
|
1869
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-brows", style: { width: 10, height: 4, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.3px)" }, children: [
|
|
1870
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1872
|
+
] }),
|
|
1873
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-eyes", style: { width: 10, height: 7, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.2px)" }, children: [
|
|
1874
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1875
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1876
|
+
] }),
|
|
1877
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-nose", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.8px)" } }),
|
|
1878
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-mouth", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.2px)" } })
|
|
1879
|
+
] }),
|
|
1880
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 14, h: 6, d: 13, cls: "dk3-hair", x: 8, y: 4 }),
|
|
1881
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 13, cls: "dk3-hair", x: 2, y: 9 }),
|
|
1882
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-ear" })
|
|
1883
|
+
] }),
|
|
1884
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3", children: [
|
|
1885
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
|
|
1886
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
|
|
1887
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 11, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 6, y: 2 }),
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 12.5, y: 2 })
|
|
1889
|
+
] })
|
|
1890
|
+
] }),
|
|
1891
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-far", children: [
|
|
1892
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
|
|
1893
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 11, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 6, y: 2 }),
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 12.5, y: 2 })
|
|
1896
|
+
] })
|
|
1897
|
+
] })
|
|
1898
|
+
] })
|
|
1899
|
+
] }),
|
|
1900
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-bubble", children: [
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1902
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
1904
|
+
] })
|
|
1905
|
+
] });
|
|
1906
|
+
}
|
|
1907
|
+
var SOUND_LIBRARY = {
|
|
1908
|
+
chime: { name: "\u6E05\u8106\u53CC\u97F3", notes: { done: [[659.25, 0, 0.14], [880, 0.13, 0.24]], err: [[220, 0, 0.16], [164.81, 0.15, 0.3]] } },
|
|
1909
|
+
ding: { name: "\u53EE", notes: { done: [[987.77, 0, 0.35]], err: [[246.94, 0, 0.4]] } },
|
|
1910
|
+
coin: { name: "\u91D1\u5E01", notes: { done: [[988, 0, 0.08], [1319, 0.08, 0.35], [988, 0, 0.08, "square"], [1319, 0.08, 0.3, "square"]], err: [[196, 0, 0.12], [147, 0.11, 0.35]] } },
|
|
1911
|
+
bell: { name: "\u949F\u58F0", notes: { done: [[523.25, 0, 0.5], [659.25, 0.02, 0.45], [783.99, 0.04, 0.4]], err: [[174.61, 0, 0.5], [130.81, 0.05, 0.5]] } },
|
|
1912
|
+
pulse: { name: "\u8109\u51B2", notes: { done: [[440, 0, 0.09], [440, 0.14, 0.09], [440, 0.28, 0.16]], err: [[174.61, 0, 0.1], [174.61, 0.14, 0.1], [174.61, 0.28, 0.18]] } },
|
|
1913
|
+
arp: { name: "\u7436\u97F3", notes: { done: [[523.25, 0, 0.12], [659.25, 0.09, 0.12], [783.99, 0.18, 0.12], [1046.5, 0.27, 0.3]], err: [[392, 0, 0.12], [329.63, 0.1, 0.12], [261.63, 0.2, 0.12], [196, 0.3, 0.32]] } }
|
|
1914
|
+
};
|
|
1915
|
+
var soundCtx = null;
|
|
1916
|
+
function playTone(seq) {
|
|
1917
|
+
try {
|
|
1918
|
+
if (typeof window === "undefined" || !window.AudioContext && !window.webkitAudioContext) return;
|
|
1919
|
+
const AC = window.AudioContext || window.webkitAudioContext;
|
|
1920
|
+
if (!soundCtx) soundCtx = new AC();
|
|
1921
|
+
if (soundCtx.state === "suspended") {
|
|
1922
|
+
soundCtx.resume().catch(() => {
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
const t0 = soundCtx.currentTime;
|
|
1926
|
+
for (const [f, at, dur, wave] of seq) {
|
|
1927
|
+
const osc = soundCtx.createOscillator();
|
|
1928
|
+
const gain = soundCtx.createGain();
|
|
1929
|
+
osc.type = wave || "sine";
|
|
1930
|
+
osc.frequency.value = f;
|
|
1931
|
+
gain.gain.setValueAtTime(0, t0 + at);
|
|
1932
|
+
gain.gain.linearRampToValueAtTime(0.18, t0 + at + 0.015);
|
|
1933
|
+
gain.gain.exponentialRampToValueAtTime(1e-4, t0 + at + dur);
|
|
1934
|
+
osc.connect(gain).connect(soundCtx.destination);
|
|
1935
|
+
osc.start(t0 + at);
|
|
1936
|
+
osc.stop(t0 + at + dur + 0.05);
|
|
1937
|
+
}
|
|
1938
|
+
} catch {
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
function playDoneSound(success, effect) {
|
|
1942
|
+
const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
|
|
1943
|
+
playTone(success ? lib.notes.done : lib.notes.err);
|
|
1944
|
+
}
|
|
1945
|
+
function previewSound(effect) {
|
|
1946
|
+
const lib = SOUND_LIBRARY[effect] || SOUND_LIBRARY.chime;
|
|
1947
|
+
playTone(lib.notes.done);
|
|
1948
|
+
const delayed = lib.notes.err.map(([f, at, dur, wave]) => [f, at + 0.55, dur, wave]);
|
|
1949
|
+
playTone(delayed);
|
|
1950
|
+
}
|
|
1951
|
+
function Toast(props) {
|
|
1952
|
+
const t = props.t;
|
|
1953
|
+
const [closing, setClosing] = (0, import_react7.useState)(false);
|
|
1954
|
+
const close = (0, import_react7.useCallback)(() => {
|
|
1955
|
+
if (!closing) setClosing(true);
|
|
1956
|
+
}, [closing]);
|
|
1957
|
+
(0, import_react7.useEffect)(() => {
|
|
1958
|
+
if (!t.stayMs) return;
|
|
1959
|
+
const timer = setTimeout(close, t.stayMs);
|
|
1960
|
+
return () => clearTimeout(timer);
|
|
1961
|
+
}, []);
|
|
1962
|
+
(0, import_react7.useEffect)(() => {
|
|
1963
|
+
if (!closing) return;
|
|
1964
|
+
const timer = setTimeout(() => props.onClose(t.id), 240);
|
|
1965
|
+
return () => clearTimeout(timer);
|
|
1966
|
+
}, [closing]);
|
|
1967
|
+
const markColor = t.kind === "success" ? "var(--dsw-alias-state-success-primary,#34d399)" : t.kind === "error" ? "var(--dsw-alias-state-error-primary,#f87171)" : "var(--dsw-alias-state-warning-primary,#fbbf24)";
|
|
1968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast" + (closing ? " out" : ""), children: [
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-toast-head", children: [
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-toast-mark", style: { background: markColor } }),
|
|
1971
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-toast-title", title: t.title, children: t.title }),
|
|
1972
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-toast-close", "aria-label": "\u5173\u95ED", onClick: close, children: "\u2715" })
|
|
1973
|
+
] }),
|
|
1974
|
+
t.body ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-toast-body", children: t.body }) : null
|
|
1975
|
+
] });
|
|
1976
|
+
}
|
|
1977
|
+
function makeBits(n, fn) {
|
|
1978
|
+
const arr = [];
|
|
1979
|
+
for (let i = 0; i < n; i++) arr.push(fn(i));
|
|
1980
|
+
return arr;
|
|
1981
|
+
}
|
|
1982
|
+
function BurstLayer(props) {
|
|
1983
|
+
const bursts = props.bursts || [];
|
|
1984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-fxwrap", "aria-hidden": "true", children: bursts.map((b) => {
|
|
1985
|
+
if (b.type === "plane") {
|
|
1986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-plane", style: { left: b.x, top: b.y }, children: "\u27A4" }, b.id);
|
|
1987
|
+
}
|
|
1988
|
+
if (b.type === "spark") {
|
|
1989
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-spark", style: { left: b.x, top: b.y }, children: b.bits.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { style: { "--dx": p.dx + "px", "--dy": p.dy + "px", background: p.c, boxShadow: "0 0 6px " + p.c } }, i)) }, b.id);
|
|
1990
|
+
}
|
|
1991
|
+
if (b.type === "streak") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-streak" }, b.id);
|
|
1992
|
+
if (b.type === "flash") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-flash" }, b.id);
|
|
1993
|
+
if (b.type === "surge") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-surge" }, b.id);
|
|
1994
|
+
if (b.type === "confetti") {
|
|
1995
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-fx dkan-fx-confetti", children: b.bits.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { style: { left: p.l + "%", "--dx": p.dx + "px", "--r": p.r + "deg", background: p.c, boxShadow: "0 0 4px " + p.c, animationDelay: p.d + "s" } }, i)) }, b.id);
|
|
1996
|
+
}
|
|
1997
|
+
return null;
|
|
1998
|
+
}) });
|
|
1999
|
+
}
|
|
2000
|
+
var MATRIX_CHARS = "01</>;{}=+*#";
|
|
2001
|
+
function AmbientLayer(props) {
|
|
2002
|
+
const mode = props.mode;
|
|
2003
|
+
const speed = props.speed;
|
|
2004
|
+
const matrix = (0, import_react7.useMemo)(() => makeBits(34, () => ({
|
|
2005
|
+
l: Math.random() * 100,
|
|
2006
|
+
d: 4 + Math.random() * 6,
|
|
2007
|
+
delay: -Math.random() * 8,
|
|
2008
|
+
o: 0.28 + Math.random() * 0.34,
|
|
2009
|
+
s: 11 + Math.round(Math.random() * 4),
|
|
2010
|
+
c: MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)]
|
|
2011
|
+
})), []);
|
|
2012
|
+
const stars = (0, import_react7.useMemo)(() => makeBits(80, () => ({
|
|
2013
|
+
l: Math.random() * 100,
|
|
2014
|
+
t: Math.random() * 100,
|
|
2015
|
+
sz: 1.5 + Math.random() * 2,
|
|
2016
|
+
d: 2 + Math.random() * 4,
|
|
2017
|
+
delay: -Math.random() * 6,
|
|
2018
|
+
dx: (Math.random() - 0.5) * 40,
|
|
2019
|
+
dy: (Math.random() - 0.5) * 24
|
|
2020
|
+
})), []);
|
|
2021
|
+
if (mode === "matrix") {
|
|
2022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-amb dkan-matrix", style: { "--dkan-speed": speed }, "aria-hidden": "true", children: matrix.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { left: p.l + "%", animationDuration: "calc(" + p.d + "s / var(--dkan-speed,1))", animationDelay: p.delay + "s", opacity: p.o, fontSize: p.s }, children: p.c }, i)) });
|
|
2023
|
+
}
|
|
2024
|
+
if (mode === "stars") {
|
|
2025
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-amb dkan-stars", style: { "--dkan-speed": speed }, "aria-hidden": "true", children: [
|
|
2026
|
+
stars.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-star", style: { left: p.l + "%", top: p.t + "%", width: p.sz, height: p.sz, animationDuration: "calc(" + p.d + "s / var(--dkan-speed,1))", animationDelay: p.delay + "s", "--dx": p.dx + "px", "--dy": p.dy + "px" } }, i)),
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-moon" }),
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-meteor", style: { top: "12%", left: "72%", animationDelay: "0s" } }),
|
|
2029
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-meteor", style: { top: "28%", left: "88%", animationDelay: "2.8s" } }),
|
|
2030
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", { className: "dkan-meteor", style: { top: "6%", left: "42%", animationDelay: "5.6s" } })
|
|
2031
|
+
] });
|
|
2032
|
+
}
|
|
2033
|
+
if (mode === "aurora") {
|
|
2034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-amb dkan-aurora", style: { "--dkan-speed": speed }, "aria-hidden": "true", children: [
|
|
2035
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2036
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2037
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2038
|
+
] });
|
|
2039
|
+
}
|
|
2040
|
+
return null;
|
|
2041
|
+
}
|
|
2042
|
+
function AnimationOverlay(props) {
|
|
2043
|
+
const ctx = props && props.ctx;
|
|
2044
|
+
const snap = useAnimation();
|
|
2045
|
+
const [toasts, setToasts] = (0, import_react7.useState)([]);
|
|
2046
|
+
const [flourish, setFlourish] = (0, import_react7.useState)(null);
|
|
2047
|
+
const [bursts, setBursts] = (0, import_react7.useState)([]);
|
|
2048
|
+
const prevActiveRef = (0, import_react7.useRef)(null);
|
|
2049
|
+
const burstIdRef = (0, import_react7.useRef)(0);
|
|
2050
|
+
const pushBurst = (0, import_react7.useCallback)((type, x, y, bits) => {
|
|
2051
|
+
const id = ++burstIdRef.current;
|
|
2052
|
+
setBursts((prev) => prev.concat([{ id, type, x, y, bits }]).slice(-6));
|
|
2053
|
+
setTimeout(() => setBursts((prev) => prev.filter((b) => b.id !== id)), 2600);
|
|
2054
|
+
}, []);
|
|
2055
|
+
(0, import_react7.useEffect)(() => {
|
|
2056
|
+
if (typeof document === "undefined") return;
|
|
2057
|
+
const onClick = (e) => {
|
|
2058
|
+
const t = e.target;
|
|
2059
|
+
if (!t || !t.closest) return;
|
|
2060
|
+
const sendBtn = t.closest('button[aria-label="Send message"], button[aria-label*="\u53D1\u9001"]');
|
|
2061
|
+
const newSession = t.closest('button[aria-label*="New session"], button[aria-label*="\u65B0\u4F1A\u8BDD"], button[aria-label*="New Session"]');
|
|
2062
|
+
const workspace = t.closest('button[aria-label*="Choose workspace"], button[aria-label*="\u5DE5\u4F5C\u76EE\u5F55"], button[aria-label*="workspace"]');
|
|
2063
|
+
const sessionItem = t.closest('[role="treeitem"]');
|
|
2064
|
+
if (sendBtn) {
|
|
2065
|
+
pushBurst("plane", e.clientX, e.clientY);
|
|
2066
|
+
} else if (newSession) {
|
|
2067
|
+
pushBurst("spark", e.clientX, e.clientY, makeBits(10, () => ({
|
|
2068
|
+
dx: (Math.random() - 0.5) * 70,
|
|
2069
|
+
dy: (Math.random() - 0.5) * 70,
|
|
2070
|
+
c: ["#4d9fff", "#34d399", "#fbbf24", "#f472b6"][Math.floor(Math.random() * 4)]
|
|
2071
|
+
})));
|
|
2072
|
+
} else if (workspace) {
|
|
2073
|
+
pushBurst("flash");
|
|
2074
|
+
} else if (sessionItem) {
|
|
2075
|
+
pushBurst("streak");
|
|
2076
|
+
}
|
|
2077
|
+
};
|
|
2078
|
+
document.addEventListener("click", onClick, true);
|
|
2079
|
+
return () => document.removeEventListener("click", onClick, true);
|
|
2080
|
+
}, [pushBurst]);
|
|
2081
|
+
const taskCountRef = (0, import_react7.useRef)(0);
|
|
2082
|
+
(0, import_react7.useEffect)(() => {
|
|
2083
|
+
const st2 = snap.status;
|
|
2084
|
+
if (!st2 || !st2.active) return;
|
|
2085
|
+
const n = st2.active.length;
|
|
2086
|
+
if (n > taskCountRef.current) pushBurst("surge");
|
|
2087
|
+
taskCountRef.current = n;
|
|
2088
|
+
}, [snap.status, pushBurst]);
|
|
2089
|
+
(0, import_react7.useEffect)(() => {
|
|
2090
|
+
let stopped = false;
|
|
2091
|
+
let timer = null;
|
|
2092
|
+
const loop = async () => {
|
|
2093
|
+
await animationStore.refresh();
|
|
2094
|
+
if (stopped) return;
|
|
2095
|
+
const s = animationStore.snap;
|
|
2096
|
+
timer = setTimeout(loop, s.error ? 15e3 : s.status && s.status.active && s.status.active.length > 0 ? 2e3 : 6e3);
|
|
2097
|
+
};
|
|
2098
|
+
loop();
|
|
2099
|
+
const onVisible = () => {
|
|
2100
|
+
if (!stopped && typeof document !== "undefined" && document.visibilityState === "visible") animationStore.refresh();
|
|
2101
|
+
};
|
|
2102
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
2103
|
+
return () => {
|
|
2104
|
+
stopped = true;
|
|
2105
|
+
if (timer) clearTimeout(timer);
|
|
2106
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
2107
|
+
};
|
|
2108
|
+
}, []);
|
|
2109
|
+
(0, import_react7.useEffect)(() => {
|
|
2110
|
+
const st2 = snap.status;
|
|
2111
|
+
if (!st2 || !st2.active) return;
|
|
2112
|
+
const prev = prevActiveRef.current;
|
|
2113
|
+
if (prev) {
|
|
2114
|
+
const currIds = new Set(st2.active.map((x) => x.sessionId));
|
|
2115
|
+
for (const task of prev) {
|
|
2116
|
+
if (currIds.has(task.sessionId)) continue;
|
|
2117
|
+
const record = (st2.recent || []).find((r) => r.sessionId === task.sessionId) || null;
|
|
2118
|
+
handleTaskEnd(task, record, st2.config || {});
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
prevActiveRef.current = st2.active.slice();
|
|
2122
|
+
}, [snap.status]);
|
|
2123
|
+
const handleTaskEnd = (task, record, cfg2) => {
|
|
2124
|
+
const reason = record && record.endReason || "";
|
|
2125
|
+
const success = isSuccessReason(reason);
|
|
2126
|
+
const info = endInfo(reason);
|
|
2127
|
+
if (cfg2.animationEnabled) {
|
|
2128
|
+
setFlourish({ key: Date.now(), err: !success });
|
|
2129
|
+
if (success) {
|
|
2130
|
+
pushBurst("confetti", 0, 0, makeBits(18, (i) => ({
|
|
2131
|
+
l: 4 + i / 18 * 92 + Math.random() * 3,
|
|
2132
|
+
dx: (Math.random() - 0.5) * 60,
|
|
2133
|
+
r: Math.random() * 720 - 360,
|
|
2134
|
+
d: Math.random() * 0.35,
|
|
2135
|
+
c: ["#4d9fff", "#34d399", "#fbbf24", "#f472b6", "#a78bfa"][i % 5]
|
|
2136
|
+
})));
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
if (!cfg2.notifyEnabled) return;
|
|
2140
|
+
const wanted = success ? cfg2.notifyOnComplete : cfg2.notifyOnError;
|
|
2141
|
+
if (!wanted) return;
|
|
2142
|
+
const models = record && record.models && record.models.length ? record.models.join(", ") : task.models && task.models.length ? task.models.join(", ") : "\u672A\u77E5\u6A21\u578B";
|
|
2143
|
+
const provider = record && record.provider || task.provider || "";
|
|
2144
|
+
const startTs = record && record.startTime || task.startTime;
|
|
2145
|
+
const endTs = record && record.endTime || Date.now();
|
|
2146
|
+
const lines = [
|
|
2147
|
+
"\u4EFB\u52A1\uFF1A" + (record && record.title || task.title || "(\u65E0\u6807\u9898)"),
|
|
2148
|
+
"\u6A21\u578B\uFF1A" + models + (provider ? "\uFF08" + provider + "\uFF09" : ""),
|
|
2149
|
+
"\u8017\u65F6\uFF1A" + fmtDur(record && record.duration || endTs - startTs) + "\uFF08" + fmtTime2(startTs) + " \u2192 " + fmtTime2(endTs) + "\uFF09",
|
|
2150
|
+
"\u56DE\u5408 " + (record && record.turns || task.turns || 0) + " \xB7 \u6B65\u9AA4 " + (record && record.steps || task.steps || 0) + (record && record.toolCalls || task.toolCalls ? " \xB7 \u5DE5\u5177 " + (record && record.toolCalls || task.toolCalls) + " \u6B21" : ""),
|
|
2151
|
+
"Token\uFF1A\u8F93\u5165 " + fmtNum2(record && record.inputTokens || task.inputTokens) + " / \u8F93\u51FA " + fmtNum2(record && record.outputTokens || task.outputTokens)
|
|
2152
|
+
];
|
|
2153
|
+
if (record && record.lastText) lines.push("\u6458\u8981\uFF1A" + truncate(record.lastText, 140));
|
|
2154
|
+
if (!success && record && record.errorMessage) lines.push("\u9519\u8BEF\uFF1A" + truncate(record.errorMessage, 120));
|
|
2155
|
+
const title = success ? "\u4EFB\u52A1\u5B8C\u6210" : "\u4EFB\u52A1" + info.label;
|
|
2156
|
+
const toast = {
|
|
2157
|
+
id: Date.now() + Math.random(),
|
|
2158
|
+
kind: success ? "success" : info.cls === "err" ? "error" : "warn",
|
|
2159
|
+
title,
|
|
2160
|
+
body: lines.join("\n"),
|
|
2161
|
+
stayMs: typeof cfg2.notifyStayMs === "number" ? cfg2.notifyStayMs : 8e3
|
|
2162
|
+
};
|
|
2163
|
+
setToasts((prev) => prev.concat([toast]).slice(-4));
|
|
2164
|
+
if (cfg2.soundNotify !== false) playDoneSound(success, cfg2.soundEffect);
|
|
2165
|
+
if (cfg2.systemNotify && typeof document !== "undefined" && document.hidden && typeof Notification !== "undefined" && Notification.permission === "granted") {
|
|
2166
|
+
try {
|
|
2167
|
+
new Notification("dsh " + title, {
|
|
2168
|
+
body: (record && record.title || task.title || "(\u65E0\u6807\u9898)") + " \xB7 " + fmtDur(record && record.duration || endTs - startTs),
|
|
2169
|
+
tag: "dsh-dock-animation-" + task.sessionId
|
|
2170
|
+
});
|
|
2171
|
+
} catch {
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
const st = snap.status;
|
|
2176
|
+
const cfg = st && st.config;
|
|
2177
|
+
const active = st && st.active ? st.active : [];
|
|
2178
|
+
const animOn = !!(cfg && cfg.animationEnabled && active.length > 0);
|
|
2179
|
+
const mode = cfg && cfg.effectMode ? cfg.effectMode : "flow";
|
|
2180
|
+
useTicker(ctx, animOn);
|
|
2181
|
+
const now = Date.now();
|
|
2182
|
+
const elapsed = active.length > 0 ? fmtClock(now - Math.min(...active.map((x) => x.startTime || now))) : "";
|
|
2183
|
+
const [panelOpen, setPanelOpen2] = (0, import_react7.useState)(false);
|
|
2184
|
+
(0, import_react7.useEffect)(() => {
|
|
2185
|
+
setPanelOpen2(panelNav.open);
|
|
2186
|
+
return subscribePanel(() => setPanelOpen2(panelNav.open));
|
|
2187
|
+
}, []);
|
|
2188
|
+
const [speed, setSpeed] = (0, import_react7.useState)(1);
|
|
2189
|
+
const speedRef = (0, import_react7.useRef)({ tokens: -1, at: 0 });
|
|
2190
|
+
(0, import_react7.useEffect)(() => {
|
|
2191
|
+
if (!st || active.length === 0) {
|
|
2192
|
+
speedRef.current = { tokens: -1, at: 0 };
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
const total = active.reduce((a, x) => a + (x.totalTokens || 0), 0);
|
|
2196
|
+
const t = Date.now();
|
|
2197
|
+
const prev = speedRef.current;
|
|
2198
|
+
if (prev.tokens < 0 || t - prev.at < 500) {
|
|
2199
|
+
speedRef.current = { tokens: total, at: t };
|
|
2200
|
+
return;
|
|
2201
|
+
}
|
|
2202
|
+
const rate = Math.max(0, (total - prev.tokens) / ((t - prev.at) / 1e3));
|
|
2203
|
+
setSpeed(Math.max(0.7, Math.min(3, 0.7 + rate / 45)));
|
|
2204
|
+
speedRef.current = { tokens: total, at: t };
|
|
2205
|
+
}, [snap.status]);
|
|
2206
|
+
const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
|
|
2207
|
+
const ambientOn = animOn && !panelOpen;
|
|
2208
|
+
const robotScaleFromConfig = Math.max(0.85, Math.min(2.2, Number(cfg && cfg.robotScale) || 1.35));
|
|
2209
|
+
const speedStyle = { "--dkan-speed": Number(speed).toFixed(2) };
|
|
2210
|
+
const saveRobotScale = (0, import_react7.useCallback)((robotScale) => {
|
|
2211
|
+
rpcCall2("config", { robotScale }).then((d) => animationStore.applyConfig(d && d.config)).catch(() => {
|
|
2212
|
+
});
|
|
2213
|
+
}, []);
|
|
2214
|
+
const [botPos, setBotPos] = (0, import_react7.useState)(null);
|
|
2215
|
+
const botPosRef = (0, import_react7.useRef)(null);
|
|
2216
|
+
const botDragRef = (0, import_react7.useRef)(null);
|
|
2217
|
+
const botResizeRef = (0, import_react7.useRef)(null);
|
|
2218
|
+
const [botScaleDraft, setBotScaleDraft] = (0, import_react7.useState)(null);
|
|
2219
|
+
const botClickBlockRef = (0, import_react7.useRef)(false);
|
|
2220
|
+
(0, import_react7.useEffect)(() => {
|
|
2221
|
+
try {
|
|
2222
|
+
if (typeof localStorage === "undefined") return;
|
|
2223
|
+
const raw = localStorage.getItem("dsh-dock/anim/robot-pos/v1");
|
|
2224
|
+
const p = raw ? JSON.parse(raw) : null;
|
|
2225
|
+
if (p && typeof p.x === "number" && typeof p.y === "number" && typeof window !== "undefined") {
|
|
2226
|
+
const card = document.querySelector(".dkan-botcard");
|
|
2227
|
+
const w = card ? card.offsetWidth : 200, h = card ? card.offsetHeight : 160;
|
|
2228
|
+
const x = Math.min(Math.max(8, p.x), Math.max(8, window.innerWidth - w - 8));
|
|
2229
|
+
const y = Math.min(Math.max(8, p.y), Math.max(8, window.innerHeight - h - 8));
|
|
2230
|
+
botPosRef.current = { x, y };
|
|
2231
|
+
setBotPos({ x, y });
|
|
2232
|
+
}
|
|
2233
|
+
} catch {
|
|
2234
|
+
}
|
|
2235
|
+
}, []);
|
|
2236
|
+
const onBotPointerDown = (e) => {
|
|
2237
|
+
if (e.button !== 0) return;
|
|
2238
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
2239
|
+
botDragRef.current = { sx: e.clientX, sy: e.clientY, ox: r.left, oy: r.top, moved: false };
|
|
2240
|
+
try {
|
|
2241
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2242
|
+
} catch {
|
|
2243
|
+
}
|
|
2244
|
+
};
|
|
2245
|
+
const onBotPointerMove = (e) => {
|
|
2246
|
+
const d = botDragRef.current;
|
|
2247
|
+
if (!d || typeof window === "undefined") return;
|
|
2248
|
+
const dx = e.clientX - d.sx, dy = e.clientY - d.sy;
|
|
2249
|
+
if (!d.moved && Math.hypot(dx, dy) < 4) return;
|
|
2250
|
+
d.moved = true;
|
|
2251
|
+
const el = e.currentTarget;
|
|
2252
|
+
const w = el.offsetWidth || 200, h = el.offsetHeight || 160;
|
|
2253
|
+
const x = Math.min(Math.max(8, d.ox + dx), window.innerWidth - w - 8);
|
|
2254
|
+
const y = Math.min(Math.max(8, d.oy + dy), window.innerHeight - h - 8);
|
|
2255
|
+
botPosRef.current = { x, y };
|
|
2256
|
+
setBotPos({ x, y });
|
|
2257
|
+
};
|
|
2258
|
+
const onBotPointerUp = () => {
|
|
2259
|
+
const d = botDragRef.current;
|
|
2260
|
+
botDragRef.current = null;
|
|
2261
|
+
if (d && d.moved) {
|
|
2262
|
+
try {
|
|
2263
|
+
if (typeof localStorage !== "undefined") localStorage.setItem("dsh-dock/anim/robot-pos/v1", JSON.stringify(botPosRef.current));
|
|
2264
|
+
} catch {
|
|
2265
|
+
}
|
|
2266
|
+
botClickBlockRef.current = true;
|
|
2267
|
+
setTimeout(() => {
|
|
2268
|
+
botClickBlockRef.current = false;
|
|
2269
|
+
}, 0);
|
|
2270
|
+
}
|
|
2271
|
+
};
|
|
2272
|
+
const onBotResizePointerDown = (e) => {
|
|
2273
|
+
if (e.button !== 0) return;
|
|
2274
|
+
e.preventDefault();
|
|
2275
|
+
e.stopPropagation();
|
|
2276
|
+
botResizeRef.current = { sx: e.clientX, sy: e.clientY, scale: botScaleDraft == null ? robotScaleFromConfig : botScaleDraft };
|
|
2277
|
+
try {
|
|
2278
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
2279
|
+
} catch {
|
|
2280
|
+
}
|
|
2281
|
+
};
|
|
2282
|
+
const onBotResizePointerMove = (e) => {
|
|
2283
|
+
const d = botResizeRef.current;
|
|
2284
|
+
if (!d) return;
|
|
2285
|
+
e.preventDefault();
|
|
2286
|
+
e.stopPropagation();
|
|
2287
|
+
const delta = (e.clientX - d.sx + (e.clientY - d.sy)) / 2;
|
|
2288
|
+
const next = Math.max(0.85, Math.min(2.2, Math.round((d.scale + delta / 220) * 100) / 100));
|
|
2289
|
+
setBotScaleDraft(next);
|
|
2290
|
+
if (botPosRef.current && typeof window !== "undefined") {
|
|
2291
|
+
const w = 220 * next + 24, h = 132 * next + 46;
|
|
2292
|
+
const x = Math.min(Math.max(8, botPosRef.current.x), Math.max(8, window.innerWidth - w - 8));
|
|
2293
|
+
const y = Math.min(Math.max(8, botPosRef.current.y), Math.max(8, window.innerHeight - h - 8));
|
|
2294
|
+
botPosRef.current = { x, y };
|
|
2295
|
+
setBotPos({ x, y });
|
|
2296
|
+
}
|
|
2297
|
+
};
|
|
2298
|
+
const onBotResizePointerUp = (e) => {
|
|
2299
|
+
if (!botResizeRef.current) return;
|
|
2300
|
+
e.preventDefault();
|
|
2301
|
+
e.stopPropagation();
|
|
2302
|
+
const next = botScaleDraft == null ? robotScaleFromConfig : botScaleDraft;
|
|
2303
|
+
botResizeRef.current = null;
|
|
2304
|
+
saveRobotScale(next);
|
|
2305
|
+
try {
|
|
2306
|
+
if (botPosRef.current && typeof localStorage !== "undefined") localStorage.setItem("dsh-dock/anim/robot-pos/v1", JSON.stringify(botPosRef.current));
|
|
2307
|
+
} catch {
|
|
2308
|
+
}
|
|
2309
|
+
setBotScaleDraft(null);
|
|
2310
|
+
};
|
|
2311
|
+
const onBotClick = () => {
|
|
2312
|
+
if (botClickBlockRef.current) return;
|
|
2313
|
+
openPanel("animation");
|
|
2314
|
+
};
|
|
2315
|
+
const displayRobotScale = botScaleDraft == null ? robotScaleFromConfig : botScaleDraft;
|
|
2316
|
+
const botCardStyle = botPos ? Object.assign({}, speedStyle, { "--dkan-bot-scale": displayRobotScale, left: botPos.x, top: botPos.y, right: "auto", bottom: "auto" }) : Object.assign({}, speedStyle, { "--dkan-bot-scale": displayRobotScale });
|
|
2317
|
+
if (!st) return null;
|
|
2318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2319
|
+
ambientOn && mode === "flow" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-line", style: speedStyle, "aria-hidden": "true" }) : null,
|
|
2320
|
+
ambientOn && (mode === "matrix" || mode === "stars" || mode === "aurora") ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AmbientLayer, { mode, speed: Number(speed).toFixed(2) }) : null,
|
|
2321
|
+
ambientOn && mode === "orbit" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-orbit", style: speedStyle, "aria-hidden": "true" }) : null,
|
|
2322
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BurstLayer, { bursts }),
|
|
2323
|
+
ambientOn && mode === "robot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2324
|
+
"div",
|
|
2325
|
+
{
|
|
2326
|
+
className: "dkan-botcard",
|
|
2327
|
+
role: "button",
|
|
2328
|
+
tabIndex: 0,
|
|
2329
|
+
style: botCardStyle,
|
|
2330
|
+
title: active.length + " \u4E2A\u4EFB\u52A1 \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875 \xB7 \u53EF\u62D6\u52A8\u5230\u4EFB\u610F\u4F4D\u7F6E",
|
|
2331
|
+
onPointerDown: onBotPointerDown,
|
|
2332
|
+
onPointerMove: onBotPointerMove,
|
|
2333
|
+
onPointerUp: onBotPointerUp,
|
|
2334
|
+
onPointerCancel: onBotPointerUp,
|
|
2335
|
+
onClick: onBotClick,
|
|
2336
|
+
onKeyDown: (e) => {
|
|
2337
|
+
if (e.target === e.currentTarget && (e.key === "Enter" || e.key === " ")) {
|
|
2338
|
+
e.preventDefault();
|
|
2339
|
+
onBotClick();
|
|
2340
|
+
}
|
|
2341
|
+
},
|
|
2342
|
+
children: [
|
|
2343
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase }),
|
|
2344
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-bot-cap", children: [
|
|
2345
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
|
|
2346
|
+
" \u4E2A\u4EFB\u52A1",
|
|
2347
|
+
elapsed ? " \xB7 " + elapsed : "",
|
|
2348
|
+
" \xB7 ",
|
|
2349
|
+
phaseLabel(phase)
|
|
2350
|
+
] }),
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2352
|
+
"button",
|
|
2353
|
+
{
|
|
2354
|
+
type: "button",
|
|
2355
|
+
className: "dkan-bot-resize",
|
|
2356
|
+
"aria-label": "\u8C03\u6574\u684C\u9762\u4F19\u4F34\u5927\u5C0F",
|
|
2357
|
+
title: "\u62D6\u52A8\u8C03\u6574\u684C\u9762\u4F19\u4F34\u5927\u5C0F",
|
|
2358
|
+
onPointerDown: onBotResizePointerDown,
|
|
2359
|
+
onPointerMove: onBotResizePointerMove,
|
|
2360
|
+
onPointerUp: onBotResizePointerUp,
|
|
2361
|
+
onPointerCancel: onBotResizePointerUp,
|
|
2362
|
+
onClick: (e) => e.stopPropagation(),
|
|
2363
|
+
onKeyDown: (e) => {
|
|
2364
|
+
if (e.key !== "ArrowUp" && e.key !== "ArrowRight" && e.key !== "ArrowDown" && e.key !== "ArrowLeft") return;
|
|
2365
|
+
e.preventDefault();
|
|
2366
|
+
e.stopPropagation();
|
|
2367
|
+
const d = e.key === "ArrowUp" || e.key === "ArrowRight" ? 0.05 : -0.05;
|
|
2368
|
+
saveRobotScale(Math.max(0.85, Math.min(2.2, Math.round((displayRobotScale + d) * 100) / 100)));
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
)
|
|
2372
|
+
]
|
|
2373
|
+
}
|
|
2374
|
+
) : null,
|
|
2375
|
+
ambientOn && mode !== "robot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2376
|
+
"button",
|
|
2377
|
+
{
|
|
2378
|
+
type: "button",
|
|
2379
|
+
className: "dkan-badge",
|
|
2380
|
+
style: speedStyle,
|
|
2381
|
+
title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
|
|
2382
|
+
onClick: () => openPanel("animation"),
|
|
2383
|
+
children: [
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
|
|
2385
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
|
|
2386
|
+
mode === "ring" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-ring" }) : null
|
|
2387
|
+
] }),
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-badge-txt", children: [
|
|
2389
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
|
|
2390
|
+
" \u4E2A\u4EFB\u52A1",
|
|
2391
|
+
elapsed ? " \xB7 " + elapsed : ""
|
|
2392
|
+
] })
|
|
2393
|
+
]
|
|
2394
|
+
}
|
|
2395
|
+
) : null,
|
|
2396
|
+
flourish ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2397
|
+
"div",
|
|
2398
|
+
{
|
|
2399
|
+
className: "dkan-done" + (flourish.err ? " err" : ""),
|
|
2400
|
+
onAnimationEnd: () => setFlourish(null),
|
|
2401
|
+
"aria-hidden": "true"
|
|
2402
|
+
},
|
|
2403
|
+
flourish.key
|
|
2404
|
+
) : null,
|
|
2405
|
+
toasts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-toasts", children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Toast, { t, onClose: (id) => setToasts((prev) => prev.filter((x) => x.id !== id)) }, t.id)) }) : null
|
|
2406
|
+
] });
|
|
2407
|
+
}
|
|
2408
|
+
function ModePreview({ id }) {
|
|
2409
|
+
if (id === "flow") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev-flow" }) });
|
|
2410
|
+
if (id === "ring") {
|
|
2411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
|
|
2412
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
|
|
2413
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-ring" })
|
|
2414
|
+
] }) });
|
|
2415
|
+
}
|
|
2416
|
+
if (id === "orbit") {
|
|
2417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev dkan-prev-box", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev-orbit" }) });
|
|
2418
|
+
}
|
|
2419
|
+
if (id === "matrix") {
|
|
2420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-prev dkan-prev-matrix", children: [
|
|
2421
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2425
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2426
|
+
] });
|
|
2427
|
+
}
|
|
2428
|
+
if (id === "stars") {
|
|
2429
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-prev dkan-prev-stars", children: [
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2431
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2435
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2436
|
+
] });
|
|
2437
|
+
}
|
|
2438
|
+
if (id === "aurora") {
|
|
2439
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-prev dkan-prev-aurora", children: [
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
|
|
2442
|
+
] });
|
|
2443
|
+
}
|
|
2444
|
+
if (id === "robot") {
|
|
2445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev dkan-prev-bot", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase: "code" }) });
|
|
2446
|
+
}
|
|
2447
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dotwrap dkan-breathe", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }) }) });
|
|
2448
|
+
}
|
|
2449
|
+
function TaskRow(props) {
|
|
2450
|
+
const t = props.t;
|
|
2451
|
+
const info = endInfo(t.endReason);
|
|
2452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task", children: [
|
|
2453
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task-head", children: [
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-task-title", title: t.title, children: t.title || "(\u65E0\u6807\u9898)" }),
|
|
2455
|
+
props.done ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag " + info.cls, children: info.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-tag on", children: phaseLabel(t.phase) })
|
|
2456
|
+
] }),
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-task-meta", children: [
|
|
2458
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: (t.models && t.models.length ? t.models.join(", ") : "\u672A\u77E5") + (t.provider ? "\uFF08" + t.provider + "\uFF09" : "") }),
|
|
2459
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: props.done ? fmtDur(t.duration) : fmtClock(t.elapsed) }),
|
|
2460
|
+
"turns" in t ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u56DE\u5408 " + (t.turns || 0) + " \xB7 \u6B65\u9AA4 " + (t.steps || 0) + (t.toolCalls ? " \xB7 \u5DE5\u5177 " + t.toolCalls : "") }) : null,
|
|
2461
|
+
t.totalTokens ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u21A7" + fmtCompact2(t.inputTokens) + " \u21A5" + fmtCompact2(t.outputTokens) }) : null,
|
|
2462
|
+
props.done && t.endTime ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: fmtTime2(t.endTime) }) : null
|
|
2463
|
+
] }),
|
|
2464
|
+
props.done && t.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-task-err", children: truncate(t.errorMessage, 120) }) : null
|
|
2465
|
+
] });
|
|
2466
|
+
}
|
|
2467
|
+
function AnimationView(props) {
|
|
2468
|
+
const ctx = props && props.ctx;
|
|
2469
|
+
const snap = useAnimation(ctx);
|
|
2470
|
+
const [cfg, setCfg] = (0, import_react7.useState)(null);
|
|
2471
|
+
const [saveErr, setSaveErr] = (0, import_react7.useState)("");
|
|
2472
|
+
const [testing, setTesting] = (0, import_react7.useState)(false);
|
|
2473
|
+
const [testState, setTestState] = (0, import_react7.useState)(null);
|
|
2474
|
+
const cfgRef = (0, import_react7.useRef)(null);
|
|
2475
|
+
const pendingSavesRef = (0, import_react7.useRef)(0);
|
|
2476
|
+
const editingWebhookRef = (0, import_react7.useRef)(false);
|
|
2477
|
+
(0, import_react7.useEffect)(() => {
|
|
2478
|
+
const c = snap.status && snap.status.config;
|
|
2479
|
+
if (!c) return;
|
|
2480
|
+
if (pendingSavesRef.current > 0 || editingWebhookRef.current) return;
|
|
2481
|
+
if (c !== cfgRef.current) {
|
|
2482
|
+
cfgRef.current = c;
|
|
2483
|
+
setCfg(Object.assign({}, c));
|
|
2484
|
+
}
|
|
2485
|
+
}, [snap.status]);
|
|
2486
|
+
(0, import_react7.useEffect)(() => {
|
|
2487
|
+
if (!animationStore.snap.status) animationStore.refresh();
|
|
2488
|
+
}, []);
|
|
2489
|
+
const patch = (p) => {
|
|
2490
|
+
setSaveErr("");
|
|
2491
|
+
setCfg(Object.assign({}, cfg, p));
|
|
2492
|
+
pendingSavesRef.current++;
|
|
2493
|
+
return rpcCall2("config", p).then((d) => {
|
|
2494
|
+
pendingSavesRef.current--;
|
|
2495
|
+
animationStore.applyConfig(d && d.config);
|
|
2496
|
+
}).catch((e) => {
|
|
2497
|
+
pendingSavesRef.current--;
|
|
2498
|
+
setSaveErr("\u4FDD\u5B58\u5931\u8D25\uFF1A" + (e && e.message || String(e)));
|
|
2499
|
+
});
|
|
2500
|
+
};
|
|
2501
|
+
const saveWebhook = async () => {
|
|
2502
|
+
if (!editingWebhookRef.current) return;
|
|
2503
|
+
const hook = String(cfg.dingtalkWebhook || "").trim();
|
|
2504
|
+
await patch({ dingtalkWebhook: hook });
|
|
2505
|
+
editingWebhookRef.current = false;
|
|
2506
|
+
const c = animationStore.snap.status && animationStore.snap.status.config;
|
|
2507
|
+
if (c && c !== cfgRef.current) {
|
|
2508
|
+
cfgRef.current = c;
|
|
2509
|
+
setCfg(Object.assign({}, c));
|
|
2510
|
+
}
|
|
2511
|
+
};
|
|
2512
|
+
const runDingtalkTest = async () => {
|
|
2513
|
+
setTesting(true);
|
|
2514
|
+
setTestState(null);
|
|
2515
|
+
try {
|
|
2516
|
+
if (editingWebhookRef.current) {
|
|
2517
|
+
const hook = String(cfg.dingtalkWebhook || "").trim();
|
|
2518
|
+
if (!hook) throw new Error("\u8BF7\u5148\u586B\u5199 Webhook \u5730\u5740");
|
|
2519
|
+
const d = await rpcCall2("config", { dingtalkWebhook: hook });
|
|
2520
|
+
animationStore.applyConfig(d && d.config);
|
|
2521
|
+
editingWebhookRef.current = false;
|
|
2522
|
+
cfgRef.current = d && d.config || cfgRef.current;
|
|
2523
|
+
setCfg(Object.assign({}, cfg, { dingtalkWebhook: hook }));
|
|
2524
|
+
}
|
|
2525
|
+
const r = await rpcCall2("test");
|
|
2526
|
+
setTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
|
|
2527
|
+
} catch (e) {
|
|
2528
|
+
setTestState({ ok: false, msg: e && e.message || String(e) });
|
|
2529
|
+
} finally {
|
|
2530
|
+
setTesting(false);
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
const enableSystemNotify = async (next) => {
|
|
2534
|
+
if (next && typeof Notification !== "undefined" && Notification.permission !== "granted") {
|
|
2535
|
+
try {
|
|
2536
|
+
const perm = await Notification.requestPermission();
|
|
2537
|
+
if (perm !== "granted") {
|
|
2538
|
+
setSaveErr("\u6D4F\u89C8\u5668\u672A\u6388\u6743\u7CFB\u7EDF\u901A\u77E5\uFF08\u53EF\u5728\u5730\u5740\u680F\u6743\u9650\u8BBE\u7F6E\u91CC\u91CD\u65B0\u5141\u8BB8\uFF09");
|
|
2539
|
+
return;
|
|
2540
|
+
}
|
|
2541
|
+
} catch {
|
|
2542
|
+
setSaveErr("\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u7CFB\u7EDF\u901A\u77E5");
|
|
2543
|
+
return;
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
patch({ systemNotify: next });
|
|
2547
|
+
};
|
|
2548
|
+
const st = snap.status;
|
|
2549
|
+
const active = st && st.active ? st.active : [];
|
|
2550
|
+
const recent = st && st.recent ? st.recent.slice(0, 6) : [];
|
|
2551
|
+
const permNote = typeof Notification === "undefined" ? "\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u7CFB\u7EDF\u901A\u77E5" : Notification.permission === "granted" ? "\u5DF2\u6388\u6743 \xB7 \u4EC5\u9875\u9762\u540E\u53F0\u65F6\u63A8\u9001" : Notification.permission === "denied" ? "\u5DF2\u88AB\u6D4F\u89C8\u5668\u62D2\u7EDD\uFF08\u9700\u5728\u6D4F\u89C8\u5668\u6743\u9650\u8BBE\u7F6E\u91CC\u91CD\u65B0\u5141\u8BB8\uFF09" : "\u672A\u6388\u6743 \xB7 \u5F00\u542F\u65F6\u4F1A\u8BF7\u6C42\u6388\u6743\uFF0C\u4EC5\u9875\u9762\u540E\u53F0\u65F6\u63A8\u9001";
|
|
2552
|
+
const rows = [];
|
|
2553
|
+
if (!cfg) {
|
|
2554
|
+
rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: snap.error ? "\u72B6\u6001\u4E0D\u53EF\u7528\uFF1A" + snap.error : snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4EFB\u52A1\u72B6\u6001\u2026" : "\u7B49\u5F85\u4EFB\u52A1\u72B6\u6001" }, "load"));
|
|
2555
|
+
} else {
|
|
2556
|
+
rows.push(
|
|
2557
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u8FD0\u884C\u52A8\u753B" }),
|
|
2560
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u8FDB\u884C\u4E2D\u624D\u51FA\u73B0\uFF1B\u514B\u5236\u7684\u52A8\u6548\uFF0C\u6697/\u4EAE\u8272\u81EA\u9002\u5E94" }),
|
|
2561
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2562
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.animationEnabled ? " on" : ""), children: cfg.animationEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2563
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2564
|
+
"button",
|
|
2565
|
+
{
|
|
2566
|
+
type: "button",
|
|
2567
|
+
className: "dock-sw" + (cfg.animationEnabled ? " on" : ""),
|
|
2568
|
+
role: "switch",
|
|
2569
|
+
"aria-checked": cfg.animationEnabled,
|
|
2570
|
+
"aria-label": "\u5F00\u5173\u8FD0\u884C\u52A8\u753B",
|
|
2571
|
+
title: cfg.animationEnabled ? "\u5173\u95ED\u8FD0\u884C\u52A8\u753B" : "\u5F00\u542F\u8FD0\u884C\u52A8\u753B",
|
|
2572
|
+
onClick: () => patch({ animationEnabled: !cfg.animationEnabled })
|
|
2573
|
+
}
|
|
2574
|
+
)
|
|
2575
|
+
] })
|
|
2576
|
+
] }),
|
|
2577
|
+
cfg.animationEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-modes", children: EFFECT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2579
|
+
"button",
|
|
2580
|
+
{
|
|
2581
|
+
type: "button",
|
|
2582
|
+
className: "dkan-mode" + (cfg.effectMode === m.id ? " on" : ""),
|
|
2583
|
+
onClick: () => patch({ effectMode: m.id }),
|
|
2584
|
+
children: [
|
|
2585
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-mode-name", children: m.name }),
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ModePreview, { id: m.id }),
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-mode-desc", children: m.desc })
|
|
2588
|
+
]
|
|
2589
|
+
},
|
|
2590
|
+
m.id
|
|
2591
|
+
)) }),
|
|
2592
|
+
cfg.effectMode === "robot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-robot-controls", children: [
|
|
2593
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-robot-controls-head", children: [
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u684C\u9762\u4F19\u4F34\u5927\u5C0F" }),
|
|
2595
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("strong", { children: [
|
|
2596
|
+
Math.round((Number(cfg.robotScale) || 1.35) * 100),
|
|
2597
|
+
"%"
|
|
2598
|
+
] })
|
|
2599
|
+
] }),
|
|
2600
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-robot-size-options", role: "group", "aria-label": "\u684C\u9762\u4F19\u4F34\u5927\u5C0F\u9884\u8BBE", children: [[1, "\u7D27\u51D1"], [1.35, "\u9ED8\u8BA4"], [1.7, "\u52A0\u5927"], [2.1, "\u7279\u5927"]].map(([scale, label]) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2601
|
+
"button",
|
|
2602
|
+
{
|
|
2603
|
+
type: "button",
|
|
2604
|
+
className: Math.abs((Number(cfg.robotScale) || 1.35) - scale) < 0.03 ? "on" : "",
|
|
2605
|
+
onClick: () => patch({ robotScale: scale }),
|
|
2606
|
+
children: label
|
|
2607
|
+
},
|
|
2608
|
+
scale
|
|
2609
|
+
)) }),
|
|
2610
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-robot-slider-row", children: [
|
|
2611
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2612
|
+
"input",
|
|
2613
|
+
{
|
|
2614
|
+
type: "range",
|
|
2615
|
+
min: "0.85",
|
|
2616
|
+
max: "2.2",
|
|
2617
|
+
step: "0.05",
|
|
2618
|
+
value: Number(cfg.robotScale) || 1.35,
|
|
2619
|
+
"aria-label": "\u684C\u9762\u4F19\u4F34\u5927\u5C0F\u767E\u5206\u6BD4",
|
|
2620
|
+
onChange: (e) => patch({ robotScale: Number(e.target.value) })
|
|
2621
|
+
}
|
|
2622
|
+
),
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u6D6E\u5C42\u53F3\u4E0B\u89D2\u4E5F\u53EF\u76F4\u63A5\u62D6\u52A8\u7F29\u653E\uFF0C\u5927\u5C0F\u4F1A\u81EA\u52A8\u4FDD\u5B58\u3002" })
|
|
2624
|
+
] })
|
|
2625
|
+
] }) : null
|
|
2626
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u52A8\u753B\u5DF2\u5173\u95ED\u2014\u2014\u53EA\u4FDD\u7559\u901A\u77E5\uFF08\u6216\u5168\u90E8\u5173\u95ED\uFF09\u65F6\uFF0C\u9875\u9762\u4E0D\u4F1A\u6709\u4EFB\u4F55\u52A8\u6548\u3002" })
|
|
2627
|
+
] }, "anim"),
|
|
2628
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2629
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2630
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u5B8C\u6210\u901A\u77E5" }),
|
|
2631
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4E0E\u52A8\u753B\u4E92\u4E0D\u4F9D\u8D56\uFF0C\u53EF\u5355\u72EC\u5F00\u542F" }),
|
|
2632
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2633
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.notifyEnabled ? " on" : ""), children: cfg.notifyEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2634
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2635
|
+
"button",
|
|
2636
|
+
{
|
|
2637
|
+
type: "button",
|
|
2638
|
+
className: "dock-sw" + (cfg.notifyEnabled ? " on" : ""),
|
|
2639
|
+
role: "switch",
|
|
2640
|
+
"aria-checked": cfg.notifyEnabled,
|
|
2641
|
+
"aria-label": "\u5F00\u5173\u5B8C\u6210\u901A\u77E5",
|
|
2642
|
+
title: cfg.notifyEnabled ? "\u5173\u95ED\u5B8C\u6210\u901A\u77E5" : "\u5F00\u542F\u5B8C\u6210\u901A\u77E5",
|
|
2643
|
+
onClick: () => patch({ notifyEnabled: !cfg.notifyEnabled })
|
|
2644
|
+
}
|
|
2645
|
+
)
|
|
2646
|
+
] })
|
|
2647
|
+
] }),
|
|
2648
|
+
cfg.notifyEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
|
|
2649
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2650
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u5B8C\u6210\u901A\u77E5" }),
|
|
2651
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2652
|
+
"button",
|
|
2653
|
+
{
|
|
2654
|
+
type: "button",
|
|
2655
|
+
className: "dkm-miniswitch" + (cfg.notifyOnComplete ? " on" : ""),
|
|
2656
|
+
onClick: () => patch({ notifyOnComplete: !cfg.notifyOnComplete }),
|
|
2657
|
+
children: cfg.notifyOnComplete ? "\u5F00" : "\u5173"
|
|
2658
|
+
}
|
|
2659
|
+
),
|
|
2660
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u4EFB\u52A1\u6B63\u5E38\u5B8C\u6210\u65F6\u901A\u77E5" })
|
|
2661
|
+
] }),
|
|
2662
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2663
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u5F02\u5E38\u901A\u77E5" }),
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2665
|
+
"button",
|
|
2666
|
+
{
|
|
2667
|
+
type: "button",
|
|
2668
|
+
className: "dkm-miniswitch" + (cfg.notifyOnError ? " on" : ""),
|
|
2669
|
+
onClick: () => patch({ notifyOnError: !cfg.notifyOnError }),
|
|
2670
|
+
children: cfg.notifyOnError ? "\u5F00" : "\u5173"
|
|
2671
|
+
}
|
|
2672
|
+
),
|
|
2673
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u51FA\u9519 / \u4E2D\u6B62 / \u8FBE\u8F93\u51FA\u4E0A\u9650\u65F6\u901A\u77E5" })
|
|
2674
|
+
] }),
|
|
2675
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2676
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u505C\u7559\u65F6\u957F" }),
|
|
2677
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2678
|
+
"select",
|
|
2679
|
+
{
|
|
2680
|
+
className: "dkan-select",
|
|
2681
|
+
value: String(cfg.notifyStayMs),
|
|
2682
|
+
onChange: (e) => patch({ notifyStayMs: Number(e.target.value) }),
|
|
2683
|
+
children: [
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "4000", children: "4 \u79D2" }),
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "8000", children: "8 \u79D2" }),
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "15000", children: "15 \u79D2" }),
|
|
2687
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "30000", children: "30 \u79D2" }),
|
|
2688
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "0", children: "\u5E38\u9A7B\uFF08\u624B\u52A8\u5173\u95ED\uFF09" })
|
|
2689
|
+
]
|
|
2690
|
+
}
|
|
2691
|
+
)
|
|
2692
|
+
] }),
|
|
2693
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2694
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u7CFB\u7EDF\u901A\u77E5" }),
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2696
|
+
"button",
|
|
2697
|
+
{
|
|
2698
|
+
type: "button",
|
|
2699
|
+
className: "dkm-miniswitch" + (cfg.systemNotify ? " on" : ""),
|
|
2700
|
+
onClick: () => enableSystemNotify(!cfg.systemNotify),
|
|
2701
|
+
children: cfg.systemNotify ? "\u5F00" : "\u5173"
|
|
2702
|
+
}
|
|
2703
|
+
),
|
|
2704
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: permNote })
|
|
2705
|
+
] }),
|
|
2706
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2707
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u63D0\u793A\u97F3" }),
|
|
2708
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2709
|
+
"button",
|
|
2710
|
+
{
|
|
2711
|
+
type: "button",
|
|
2712
|
+
className: "dkm-miniswitch" + (cfg.soundNotify !== false ? " on" : ""),
|
|
2713
|
+
onClick: () => patch({ soundNotify: cfg.soundNotify === false }),
|
|
2714
|
+
children: cfg.soundNotify !== false ? "\u5F00" : "\u5173"
|
|
2715
|
+
}
|
|
2716
|
+
),
|
|
2717
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u65F6\u64AD\u653E\uFF08\u8BD5\u542C\u4E3A\u5148\u64AD\u5B8C\u6210\u97F3\u3001\u540E\u64AD\u5F02\u5E38\u97F3\uFF09" })
|
|
2718
|
+
] }),
|
|
2719
|
+
cfg.soundNotify !== false ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-sounds", children: Object.keys(SOUND_LIBRARY).map((key) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2720
|
+
"button",
|
|
2721
|
+
{
|
|
2722
|
+
type: "button",
|
|
2723
|
+
className: "dkan-sound" + (cfg.soundEffect === key ? " on" : ""),
|
|
2724
|
+
onClick: () => patch({ soundEffect: key }),
|
|
2725
|
+
children: [
|
|
2726
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sound-name", children: [
|
|
2727
|
+
SOUND_LIBRARY[key].name,
|
|
2728
|
+
cfg.soundEffect === key ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sound-cur", children: "\u2713" }) : null
|
|
2729
|
+
] }),
|
|
2730
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2731
|
+
"span",
|
|
2732
|
+
{
|
|
2733
|
+
className: "dkan-sound-play",
|
|
2734
|
+
role: "button",
|
|
2735
|
+
tabIndex: 0,
|
|
2736
|
+
title: "\u8BD5\u542C " + SOUND_LIBRARY[key].name,
|
|
2737
|
+
onClick: (e) => {
|
|
2738
|
+
e.stopPropagation();
|
|
2739
|
+
previewSound(key);
|
|
2740
|
+
},
|
|
2741
|
+
onKeyDown: (e) => {
|
|
2742
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2743
|
+
e.preventDefault();
|
|
2744
|
+
e.stopPropagation();
|
|
2745
|
+
previewSound(key);
|
|
2746
|
+
}
|
|
2747
|
+
},
|
|
2748
|
+
children: "\u25B6"
|
|
2749
|
+
}
|
|
2750
|
+
)
|
|
2751
|
+
]
|
|
2752
|
+
},
|
|
2753
|
+
key
|
|
2754
|
+
)) }) : null
|
|
2755
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u901A\u77E5\u5DF2\u5173\u95ED\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u65F6\u65E2\u4E0D\u5F39\u5361\u7247\u4E5F\u4E0D\u63A8\u7CFB\u7EDF\u901A\u77E5\u3002" })
|
|
2756
|
+
] }, "notify"),
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2758
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2759
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u9489\u9489\u63A8\u9001" }),
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u9489\u9489\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
|
|
2761
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.dingtalkEnabled ? " on" : ""), children: cfg.dingtalkEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
|
|
2763
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2764
|
+
"button",
|
|
2765
|
+
{
|
|
2766
|
+
type: "button",
|
|
2767
|
+
className: "dock-sw" + (cfg.dingtalkEnabled ? " on" : ""),
|
|
2768
|
+
role: "switch",
|
|
2769
|
+
"aria-checked": cfg.dingtalkEnabled,
|
|
2770
|
+
"aria-label": "\u5F00\u5173\u9489\u9489\u63A8\u9001",
|
|
2771
|
+
title: cfg.dingtalkEnabled ? "\u5173\u95ED\u9489\u9489\u63A8\u9001" : "\u5F00\u542F\u9489\u9489\u63A8\u9001",
|
|
2772
|
+
onClick: () => patch({ dingtalkEnabled: !cfg.dingtalkEnabled })
|
|
2773
|
+
}
|
|
2774
|
+
)
|
|
2775
|
+
] })
|
|
2776
|
+
] }),
|
|
2777
|
+
cfg.dingtalkEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
|
|
2778
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row dkan-row-webhook", children: [
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "Webhook" }),
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2781
|
+
"input",
|
|
2782
|
+
{
|
|
2783
|
+
type: "text",
|
|
2784
|
+
className: "dkan-input",
|
|
2785
|
+
spellCheck: false,
|
|
2786
|
+
value: cfg.dingtalkWebhook || "",
|
|
2787
|
+
placeholder: "https://oapi.dingtalk.com/robot/send?access_token=\u2026",
|
|
2788
|
+
onChange: (e) => {
|
|
2789
|
+
editingWebhookRef.current = true;
|
|
2790
|
+
setCfg(Object.assign({}, cfg, { dingtalkWebhook: e.target.value }));
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
),
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2795
|
+
"button",
|
|
2796
|
+
{
|
|
2797
|
+
type: "button",
|
|
2798
|
+
className: "dkan-btn",
|
|
2799
|
+
disabled: !editingWebhookRef.current,
|
|
2800
|
+
onClick: saveWebhook,
|
|
2801
|
+
children: editingWebhookRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
|
|
2802
|
+
}
|
|
2803
|
+
)
|
|
2804
|
+
] }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
|
|
2806
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-btn", disabled: testing, onClick: runDingtalkTest, children: testing ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
|
|
2808
|
+
testState ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-row-sub" + (testState.ok ? " dkan-ok" : " dkan-err"), children: [
|
|
2809
|
+
testState.ok ? "\u2713 " : "\u2717 ",
|
|
2810
|
+
testState.msg
|
|
2811
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
|
|
2812
|
+
] }),
|
|
2813
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u9489\u9489\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u667A\u80FD\u7FA4\u52A9\u624B \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\uFF08Webhook\uFF09\uFF0C \u5B89\u5168\u8BBE\u7F6E\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
|
|
2814
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u9489\u9489\u3002" })
|
|
2815
|
+
] }, "dingtalk")
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
if (saveErr) rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note dkan-err", children: saveErr }, "err"));
|
|
2819
|
+
rows.push(
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
|
|
2822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u8FD0\u884C\u72B6\u6001" }),
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: snap.error ? "\u72B6\u6001\u62C9\u53D6\u5931\u8D25\uFF1A" + snap.error : active.length > 0 ? active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D" : recent.length > 0 ? "\u7A7A\u95F2 \xB7 \u663E\u793A\u6700\u8FD1\u5B8C\u6210" : "\u7A7A\u95F2 \xB7 \u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55" }),
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-refresh", onClick: () => animationStore.refresh(), children: snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0" })
|
|
2825
|
+
] }),
|
|
2826
|
+
active.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-tasks", children: active.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TaskRow, { t }, t.sessionId)) }) : null,
|
|
2827
|
+
active.length === 0 && recent.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u53D1\u8D77\u65B0\u4F1A\u8BDD\u4EFB\u52A1\u540E\uFF0C\u8FD9\u91CC\u4F1A\u663E\u793A\u8FDB\u884C\u4E2D\u4E0E\u6700\u8FD1\u5B8C\u6210\u7684\u4EFB\u52A1\uFF1B\u52A8\u753B\u4E0E\u901A\u77E5\u540C\u65F6\u5728\u9875\u9762\u751F\u6548\u3002" }) : null,
|
|
2828
|
+
recent.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-tasks dkan-tasks-done", children: recent.map((t) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TaskRow, { t, done: true }, t.sessionId + ":" + t.endTime)) }) : null
|
|
2829
|
+
] }, "state")
|
|
2830
|
+
);
|
|
2831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-root", children: rows });
|
|
2832
|
+
}
|
|
2833
|
+
function AnimationStat(props) {
|
|
2834
|
+
const snap = useAnimation(props && props.ctx);
|
|
2835
|
+
const st = snap.status;
|
|
2836
|
+
if (snap.error) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-err", children: "\u4EFB\u52A1\u72B6\u6001\u4E0D\u53EF\u7528\uFF08\u5BBF\u4E3B\u9700\u91CD\u542F\u52A0\u8F7D\u52A8\u753B\u8DEF\u7531\uFF09" });
|
|
2837
|
+
if (!st) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u7B49\u5F85\u4EFB\u52A1\u72B6\u6001\u2026" });
|
|
2838
|
+
if (st.active && st.active.length > 0) {
|
|
2839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: st.active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + fmtDur(Math.max(...st.active.map((x) => x.elapsed || 0))) });
|
|
2840
|
+
}
|
|
2841
|
+
const last = st.recent && st.recent[0];
|
|
2842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: last ? "\u7A7A\u95F2 \xB7 \u6700\u8FD1\u5B8C\u6210 " + truncate(last.title, 24) : "\u7A7A\u95F2 \xB7 \u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55" });
|
|
2843
|
+
}
|
|
2844
|
+
var css2 = [
|
|
2845
|
+
// 顶部流光细线(3px,比首版更醒目)
|
|
2846
|
+
".dkan-line{position:fixed;top:0;left:0;right:0;height:3px;z-index:9990;pointer-events:none;background:color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 30%,transparent);}",
|
|
2847
|
+
'.dkan-line::after{content:"";position:absolute;top:0;bottom:0;left:-42%;width:42%;background:linear-gradient(90deg,transparent,var(--dsw-alias-accent,#4d9fff) 60%,#fff);box-shadow:0 0 10px 1px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 70%,transparent);animation:dkan-flow calc(1.9s / var(--dkan-speed,1)) linear infinite;}',
|
|
2848
|
+
"@keyframes dkan-flow{to{left:100%}}",
|
|
2849
|
+
// 完成瞬间的一次性流光(成功绿 / 异常红),动画结束自动清场
|
|
2850
|
+
".dkan-done{position:fixed;top:0;left:0;right:0;height:3px;z-index:9991;pointer-events:none;background:linear-gradient(90deg,transparent,var(--dsw-alias-state-success-primary,#34d399) 50%,#fff);background-size:50% 100%;background-repeat:no-repeat;animation:dkan-done 1.1s var(--ds-ease-in-out) forwards;}",
|
|
2851
|
+
".dkan-done.err{background-image:linear-gradient(90deg,transparent,var(--dsw-alias-state-error-primary,#f87171) 50%,#fff);}",
|
|
2852
|
+
"@keyframes dkan-done{0%{background-position:-60% 0;opacity:0}25%{opacity:1}100%{background-position:160% 0;opacity:0}}",
|
|
2853
|
+
// 环屏巡航:光点沿屏幕边缘转一整圈
|
|
2854
|
+
".dkan-orbit{position:fixed;top:0;left:0;width:12px;height:12px;z-index:9990;pointer-events:none;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 14px 4px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 60%,transparent),0 0 30px 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 25%,transparent);animation:dkan-orbit calc(14s / var(--dkan-speed,1)) linear infinite;}",
|
|
2855
|
+
"@keyframes dkan-orbit{0%{top:0;left:0}25%{top:0;left:calc(100vw - 12px)}50%{top:calc(100vh - 12px);left:calc(100vw - 12px)}75%{top:calc(100vh - 12px);left:0}100%{top:0;left:0}}",
|
|
2856
|
+
// ===== 氛围动效 =====
|
|
2857
|
+
".dkan-amb{position:fixed;inset:0;z-index:9989;pointer-events:none;overflow:hidden;}",
|
|
2858
|
+
// 代码雨:字符列缓落(提亮加大,速度随吞吐)
|
|
2859
|
+
".dkan-matrix span{position:absolute;top:-12%;writing-mode:vertical-rl;font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-accent,#4d9fff);text-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 60%,transparent);animation:dkan-fall linear infinite;will-change:transform;}",
|
|
2860
|
+
"@keyframes dkan-fall{to{transform:translateY(125vh)}}",
|
|
2861
|
+
// 星野:星点缓慢飘移 + 闪烁(加亮加发光)+ 月亮 + 流星
|
|
2862
|
+
".dkan-stars .dkan-star{position:absolute;border-radius:50%;background:#cfe3ff;box-shadow:0 0 4px 1px color-mix(in srgb,#8ab6ff 55%,transparent);animation:dkan-star ease-in-out infinite alternate;}",
|
|
2863
|
+
"@keyframes dkan-star{0%{opacity:.3;transform:translate(0,0)}50%{opacity:1}100%{opacity:.45;transform:translate(var(--dx),var(--dy))}}",
|
|
2864
|
+
// 月亮:右上弯月(radial-gradient 咬出月牙,透明区不遮挡背景;外圈柔光晕)
|
|
2865
|
+
".dkan-moon{position:absolute;top:9%;right:10%;width:36px;height:36px;border-radius:50%;background:radial-gradient(circle at 66% 34%,transparent 0 44%,#fdf6d8 46%,#e8d9a0 78%,#d8c78a);box-shadow:0 0 18px 4px color-mix(in srgb,#fdf6d8 35%,transparent),0 0 44px 12px color-mix(in srgb,#fdf6d8 15%,transparent);}",
|
|
2866
|
+
// 流星:斜向划过的光带(亮头 + 渐隐尾),周期出现
|
|
2867
|
+
".dkan-meteor{position:absolute;width:110px;height:2px;border-radius:2px;background:linear-gradient(90deg,#fff,color-mix(in srgb,#8ab6ff 60%,transparent) 40%,transparent);transform:rotate(35deg);transform-origin:left center;opacity:0;animation:dkan-meteor 8.4s linear infinite;}",
|
|
2868
|
+
'.dkan-meteor::before{content:"";position:absolute;left:-2px;top:-2px;width:6px;height:6px;border-radius:50%;background:#fff;box-shadow:0 0 8px 2px color-mix(in srgb,#cfe3ff 70%,transparent);}',
|
|
2869
|
+
"@keyframes dkan-meteor{0%{opacity:0;transform:rotate(35deg) translateX(0)}3%{opacity:1}10%{opacity:0;transform:rotate(35deg) translateX(46vh)}100%{opacity:0;transform:rotate(35deg) translateX(46vh)}}",
|
|
2870
|
+
// 极光:顶部柔光带呼吸流动(加浓)
|
|
2871
|
+
".dkan-aurora i{position:absolute;top:-40%;left:-20%;width:70%;height:80%;border-radius:50%;filter:blur(50px);opacity:.32;animation:dkan-aurora ease-in-out infinite alternate;}",
|
|
2872
|
+
".dkan-aurora i:nth-child(1){background:#4d9fff;}",
|
|
2873
|
+
".dkan-aurora i:nth-child(2){background:#34d399;left:20%;animation-delay:-2s;}",
|
|
2874
|
+
".dkan-aurora i:nth-child(3){background:#a78bfa;left:55%;animation-delay:-4s;}",
|
|
2875
|
+
"@keyframes dkan-aurora{0%{transform:translateX(-8%) scaleY(1)}100%{transform:translateX(10%) scaleY(1.3)}}",
|
|
2876
|
+
// ===== 交互反馈层 =====
|
|
2877
|
+
".dkan-fxwrap{position:fixed;inset:0;z-index:9992;pointer-events:none;overflow:hidden;}",
|
|
2878
|
+
".dkan-fx{position:absolute;}",
|
|
2879
|
+
// 纸飞机:从点击处向右上飞出淡出(加大加亮)
|
|
2880
|
+
".dkan-fx-plane{color:var(--dsw-alias-accent,#4d9fff);font-size:24px;text-shadow:0 0 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 70%,transparent);animation:dkan-plane 1.2s var(--ds-ease-in-out) forwards;}",
|
|
2881
|
+
"@keyframes dkan-plane{0%{opacity:0;transform:translate(0,0) rotate(-20deg) scale(.6)}15%{opacity:1;transform:translate(20px,-14px) rotate(-20deg) scale(1.1)}100%{opacity:0;transform:translate(240px,-160px) rotate(-20deg) scale(1)}}",
|
|
2882
|
+
// 火花:粒子四散(加大加多散得更开)
|
|
2883
|
+
".dkan-fx-spark i{position:absolute;width:7px;height:7px;border-radius:50%;box-shadow:0 0 6px currentColor;animation:dkan-spark .9s var(--ds-ease-in-out) forwards;}",
|
|
2884
|
+
"@keyframes dkan-spark{0%{opacity:1;transform:translate(0,0) scale(1)}100%{opacity:0;transform:translate(var(--dx),var(--dy)) scale(.4)}}",
|
|
2885
|
+
// 流光:横向扫过(切会话,加高加亮)
|
|
2886
|
+
".dkan-fx-streak{top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,transparent,var(--dsw-alias-accent,#4d9fff) 50%,#fff);background-size:45% 100%;background-repeat:no-repeat;box-shadow:0 0 12px 2px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 50%,transparent);animation:dkan-streak 1s var(--ds-ease-in-out) forwards;}",
|
|
2887
|
+
"@keyframes dkan-streak{0%{background-position:-50% 0;opacity:0}20%{opacity:1}100%{background-position:150% 0;opacity:0}}",
|
|
2888
|
+
// 微光:全屏柔光一闪(切工作目录,加浓)
|
|
2889
|
+
".dkan-fx-flash{inset:0;background:radial-gradient(ellipse at center,color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 26%,transparent),transparent 75%);animation:dkan-flash .8s var(--ds-ease-in-out) forwards;}",
|
|
2890
|
+
"@keyframes dkan-flash{0%{opacity:0}30%{opacity:1}100%{opacity:0}}",
|
|
2891
|
+
// 光涌:底部向上涌起(任务开始,加高加浓)
|
|
2892
|
+
".dkan-fx-surge{left:0;right:0;bottom:0;height:42%;background:linear-gradient(0deg,color-mix(in srgb,var(--dsw-alias-state-success-primary,#34d399) 38%,transparent),transparent);animation:dkan-surge 1.2s var(--ds-ease-in-out) forwards;}",
|
|
2893
|
+
"@keyframes dkan-surge{0%{opacity:0;transform:translateY(45%)}30%{opacity:1}100%{opacity:0;transform:translateY(-35%)}}",
|
|
2894
|
+
// 彩带:顶部飘落(任务完成庆祝,加大加多)
|
|
2895
|
+
".dkan-fx-confetti{inset:0;}",
|
|
2896
|
+
".dkan-fx-confetti i{position:absolute;top:-14px;width:8px;height:13px;border-radius:2px;box-shadow:0 0 4px currentColor;animation:dkan-confetti 2s var(--ds-ease-in-out) forwards;}",
|
|
2897
|
+
"@keyframes dkan-confetti{0%{opacity:1;transform:translateY(0) rotate(0)}100%{opacity:0;transform:translateY(75vh) translateX(var(--dx)) rotate(var(--r))}}",
|
|
2898
|
+
// 右下角状态徽标(玻璃拟态,可点击);抬到 dsh 输入卡上方避免重叠错位
|
|
2899
|
+
".dkan-badge{position:fixed;right:20px;bottom:calc(var(--dsh-composer-height,152px) + 20px);z-index:9990;display:inline-flex;align-items:center;gap:8px;padding:7px 14px;border-radius:999px;cursor:pointer;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 78%,transparent);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 6px 24px rgb(0 0 0 / .16);color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;line-height:18px;pointer-events:auto;animation:dkan-rise .3s var(--ds-ease-in-out);transition:color .15s var(--ds-ease-in-out);}",
|
|
2900
|
+
".dkan-badge:hover{color:var(--dsw-alias-label-primary);}",
|
|
2901
|
+
".dkan-badge .n{color:var(--dsw-alias-label-primary);font-weight:600;}",
|
|
2902
|
+
"@keyframes dkan-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}",
|
|
2903
|
+
// 徽标圆点与两种动效(呼吸 / 轨道环)
|
|
2904
|
+
".dkan-dotwrap{position:relative;width:16px;height:16px;flex:none;display:inline-flex;align-items:center;justify-content:center;}",
|
|
2905
|
+
".dkan-dot{width:9px;height:9px;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 55%,transparent);}",
|
|
2906
|
+
".dkan-breathe .dkan-dot{animation:dkan-breathe calc(2.6s / var(--dkan-speed,1)) ease-in-out infinite;}",
|
|
2907
|
+
"@keyframes dkan-breathe{0%,100%{transform:scale(1);opacity:.55}50%{transform:scale(1.6);opacity:1}}",
|
|
2908
|
+
".dkan-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 68%,var(--dsw-alias-accent,#4d9fff) 92%,#fff);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));animation:dkan-spin calc(2.2s / var(--dkan-speed,1)) linear infinite;opacity:.9;}",
|
|
2909
|
+
"@keyframes dkan-spin{to{transform:rotate(360deg)}}",
|
|
2910
|
+
// 通知卡片栈(右上角)
|
|
2911
|
+
".dkan-toasts{position:fixed;top:16px;right:16px;z-index:9995;display:flex;flex-direction:column;gap:8px;width:min(380px,calc(100vw - 32px));}",
|
|
2912
|
+
".dkan-toast{border-radius:12px;padding:12px 14px;pointer-events:auto;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 88%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--dsw-alias-border-l1);box-shadow:0 10px 36px rgb(0 0 0 / .22);animation:dkan-toast-in .32s var(--ds-ease-in-out);}",
|
|
2913
|
+
".dkan-toast.out{animation:dkan-toast-out .24s var(--ds-ease-in-out) forwards;}",
|
|
2914
|
+
"@keyframes dkan-toast-in{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}",
|
|
2915
|
+
"@keyframes dkan-toast-out{to{opacity:0;transform:translateX(10px)}}",
|
|
2916
|
+
".dkan-toast-head{display:flex;align-items:center;gap:8px;margin-bottom:4px;}",
|
|
2917
|
+
".dkan-toast-mark{width:8px;height:8px;border-radius:50%;flex:none;}",
|
|
2918
|
+
".dkan-toast-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
2919
|
+
".dkan-toast-close{cursor:pointer;flex:none;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:6px;width:22px;height:22px;font-size:11px;line-height:1;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;}",
|
|
2920
|
+
".dkan-toast-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
|
|
2921
|
+
".dkan-toast-body{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.7;white-space:pre-line;word-break:break-word;}",
|
|
2922
|
+
// 面板页布局
|
|
2923
|
+
".dkan-root{display:flex;flex-direction:column;gap:10px;}",
|
|
2924
|
+
".dkan-note{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;}",
|
|
2925
|
+
".dkan-err{color:var(--dsw-alias-state-error-primary);}",
|
|
2926
|
+
".dkan-sec{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;padding:10px 12px;display:flex;flex-direction:column;gap:8px;}",
|
|
2927
|
+
".dkan-sec-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}",
|
|
2928
|
+
".dkan-sec-title{font-weight:600;font-size:13px;color:var(--dsw-alias-label-primary);flex:none;}",
|
|
2929
|
+
".dkan-sec-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);flex:1;min-width:120px;}",
|
|
2930
|
+
".dkan-sec-sw{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:8px;}",
|
|
2931
|
+
".dkan-sec-swlabel{font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;}",
|
|
2932
|
+
".dkan-sec-swlabel.on{color:var(--dsw-alias-state-success-primary);}",
|
|
2933
|
+
".dkan-refresh{cursor:pointer;flex:none;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:2px 10px;font-family:inherit;font-size:12px;}",
|
|
2934
|
+
".dkan-refresh:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
2935
|
+
// 模式选择卡(带缩微预览)
|
|
2936
|
+
".dkan-modes{display:flex;gap:8px;flex-wrap:wrap;}",
|
|
2937
|
+
".dkan-mode{flex:1;min-width:150px;display:flex;flex-direction:column;gap:6px;padding:10px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-2);cursor:pointer;font-family:inherit;text-align:left;transition:border-color .15s var(--ds-ease-in-out);}",
|
|
2938
|
+
".dkan-mode:hover{border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
2939
|
+
".dkan-mode.on{border-color:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 0 1px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 40%,transparent);}",
|
|
2940
|
+
".dkan-mode-name{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:6px;}",
|
|
2941
|
+
'.dkan-mode.on .dkan-mode-name::after{content:"\u2713";color:var(--dsw-alias-accent,#4d9fff);}',
|
|
2942
|
+
".dkan-mode-desc{font-size:11px;color:var(--dsw-alias-label-tertiary);line-height:1.5;}",
|
|
2943
|
+
".dkan-robot-controls{display:flex;flex-direction:column;gap:8px;padding:9px 10px;border:1px solid color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 28%,var(--dsw-alias-border-l1));border-radius:9px;background:color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 5%,var(--dsw-alias-bg-layer-2));}",
|
|
2944
|
+
".dkan-robot-controls-head{display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--dsw-alias-label-primary);}",
|
|
2945
|
+
".dkan-robot-controls-head strong{font-variant-numeric:tabular-nums;color:var(--dsw-alias-accent,#4d9fff);}",
|
|
2946
|
+
".dkan-robot-size-options{display:flex;gap:6px;flex-wrap:wrap;}",
|
|
2947
|
+
".dkan-robot-size-options button{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:7px;padding:3px 10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:inherit;font-size:11px;}",
|
|
2948
|
+
".dkan-robot-size-options button:hover,.dkan-robot-size-options button.on{border-color:var(--dsw-alias-accent,#4d9fff);color:var(--dsw-alias-label-primary);}",
|
|
2949
|
+
".dkan-robot-slider-row{display:flex;align-items:center;gap:9px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
2950
|
+
".dkan-robot-slider-row input{accent-color:var(--dsw-alias-accent,#4d9fff);width:min(240px,100%);}",
|
|
2951
|
+
".dkan-prev{height:30px;border-radius:6px;background:var(--dsw-alias-bg-layer-1);position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;}",
|
|
2952
|
+
".dkan-prev-flow{position:absolute;top:0;left:0;right:0;height:3px;background:color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 30%,transparent);}",
|
|
2953
|
+
'.dkan-prev-flow::after{content:"";position:absolute;top:0;bottom:0;left:-40%;width:40%;background:linear-gradient(90deg,transparent,var(--dsw-alias-accent,#4d9fff));animation:dkan-flow 1.9s linear infinite;}',
|
|
2954
|
+
".dkan-prev-box{--dkan-speed:1;}",
|
|
2955
|
+
".dkan-prev-orbit{position:absolute;top:3px;left:3px;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 7px 2px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 55%,transparent);animation:dkan-prev-orbit 3s linear infinite;}",
|
|
2956
|
+
"@keyframes dkan-prev-orbit{0%{top:3px;left:3px}25%{top:3px;left:calc(100% - 10px)}50%{top:calc(100% - 10px);left:calc(100% - 10px)}75%{top:calc(100% - 10px);left:3px}100%{top:3px;left:3px}}",
|
|
2957
|
+
// 预览:代码雨(字符列下落)
|
|
2958
|
+
".dkan-prev-matrix i{position:absolute;top:-100%;writing-mode:vertical-rl;font-size:8px;font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-accent,#4d9fff);opacity:.5;animation:dkan-prev-fall 2.2s linear infinite;}",
|
|
2959
|
+
".dkan-prev-matrix i:nth-child(1){left:12%;}",
|
|
2960
|
+
".dkan-prev-matrix i:nth-child(2){left:32%;animation-delay:-.6s;}",
|
|
2961
|
+
".dkan-prev-matrix i:nth-child(3){left:52%;animation-delay:-1.2s;}",
|
|
2962
|
+
".dkan-prev-matrix i:nth-child(4){left:72%;animation-delay:-.3s;}",
|
|
2963
|
+
".dkan-prev-matrix i:nth-child(5){left:88%;animation-delay:-1.6s;}",
|
|
2964
|
+
'.dkan-prev-matrix i::after{content:"01</>";}',
|
|
2965
|
+
"@keyframes dkan-prev-fall{to{transform:translateY(300%)}}",
|
|
2966
|
+
// 预览:星野(星点闪烁)
|
|
2967
|
+
".dkan-prev-stars i{position:absolute;width:2px;height:2px;border-radius:50%;background:var(--dsw-alias-label-secondary);animation:dkan-prev-star 1.6s ease-in-out infinite alternate;}",
|
|
2968
|
+
".dkan-prev-stars i:nth-child(1){left:15%;top:25%;}",
|
|
2969
|
+
".dkan-prev-stars i:nth-child(2){left:40%;top:60%;animation-delay:-.4s;}",
|
|
2970
|
+
".dkan-prev-stars i:nth-child(3){left:60%;top:30%;animation-delay:-.8s;}",
|
|
2971
|
+
".dkan-prev-stars i:nth-child(4){left:80%;top:55%;animation-delay:-1.2s;}",
|
|
2972
|
+
".dkan-prev-stars i:nth-child(5){left:28%;top:70%;animation-delay:-.6s;}",
|
|
2973
|
+
".dkan-prev-stars i:nth-child(6){left:70%;top:75%;animation-delay:-1s;}",
|
|
2974
|
+
"@keyframes dkan-prev-star{0%{opacity:.2}100%{opacity:.9}}",
|
|
2975
|
+
// 预览:极光(柔光带呼吸)
|
|
2976
|
+
".dkan-prev-aurora i{position:absolute;top:-30%;width:60%;height:120%;border-radius:50%;filter:blur(8px);opacity:.35;animation:dkan-prev-aurora 2.4s ease-in-out infinite alternate;}",
|
|
2977
|
+
".dkan-prev-aurora i:nth-child(1){left:5%;background:#4d9fff;}",
|
|
2978
|
+
".dkan-prev-aurora i:nth-child(2){left:45%;background:#34d399;animation-delay:-1.2s;}",
|
|
2979
|
+
"@keyframes dkan-prev-aurora{0%{transform:translateX(-10%)}100%{transform:translateX(15%)}}",
|
|
2980
|
+
".dkan-prev-bot{height:92px;justify-content:center;}",
|
|
2981
|
+
".dkan-prev-bot .dkan-bot-scene{--dkan-bot-scale:1;transform:scale(.56);transform-origin:center;}",
|
|
2982
|
+
// ===== 桌面伙伴:具象人物 + 四屏工位(尺寸可调,整卡可拖拽) =====
|
|
2983
|
+
// 卡片:玻璃拟态;默认停泊右下(dsh 输入卡上方),拖动后位置持久化、可放屏幕任意处
|
|
2984
|
+
".dkan-botcard{--dkan-bot-scale:1.35;position:fixed;right:20px;bottom:calc(var(--dsh-composer-height,152px) + 20px);z-index:9990;display:flex;flex-direction:column;gap:6px;padding:10px 12px;border-radius:16px;cursor:grab;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 86%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 12px 36px rgb(0 0 0 / .22);color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;pointer-events:auto;touch-action:none;user-select:none;animation:dkan-rise .3s var(--ds-ease-in-out);}",
|
|
2985
|
+
".dkan-botcard:hover,.dkan-botcard:focus-visible{border-color:var(--dsw-alias-accent,#4d9fff);outline:none;}",
|
|
2986
|
+
".dkan-botcard.dkan-dragging{cursor:grabbing;animation:none;}",
|
|
2987
|
+
".dkan-botcard .n{color:var(--dsw-alias-label-primary);font-weight:600;}",
|
|
2988
|
+
".dkan-bot-cap{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-right:18px;}",
|
|
2989
|
+
".dkan-bot-resize{position:absolute;right:7px;bottom:7px;width:15px;height:15px;padding:0;border:0;border-radius:4px;background:linear-gradient(135deg,transparent 0 42%,var(--dsw-alias-label-tertiary) 44% 51%,transparent 53% 62%,var(--dsw-alias-label-tertiary) 64% 71%,transparent 73%);cursor:nwse-resize;touch-action:none;opacity:.72;}",
|
|
2990
|
+
".dkan-bot-resize:hover,.dkan-bot-resize:focus-visible{opacity:1;outline:1px solid var(--dsw-alias-accent,#4d9fff);outline-offset:1px;}",
|
|
2991
|
+
// ===== 3D 场景(CSS 长方体拼装:世界层统一 3/4 视角——俯视 + 侧身面向镜头) =====
|
|
2992
|
+
".dkan-bot-scene{position:relative;width:calc(220px * var(--dkan-bot-scale,1));height:calc(132px * var(--dkan-bot-scale,1));perspective:calc(620px * var(--dkan-bot-scale,1));perspective-origin:55% 18%;--dk3-side:#7c8ba0;--dk3-side-hi:#a9b8ca;--dk3-side-dk:#4c5870;--dk3-screen:#0d1526;--dkan-code-a:#4ade80;--dkan-code-b:#60a5fa;--dkan-code-c:#fbbf24;}",
|
|
2993
|
+
".dk3-world{position:absolute;left:0;top:0;width:220px;height:132px;transform-style:preserve-3d;transform-origin:top left;transform:scale(var(--dkan-bot-scale,1)) rotateX(-15deg) rotateY(-30deg);}",
|
|
2994
|
+
".dk3-box{position:absolute;transform-style:preserve-3d;}",
|
|
2995
|
+
".dk3-face{position:absolute;left:50%;top:50%;display:block;background:var(--dk3-side);backface-visibility:hidden;border-radius:1px;}",
|
|
2996
|
+
// 金属件着色:顶面亮、底面暗,正/侧面中调(3D 光感)
|
|
2997
|
+
".dk3-metal .dk3-face{background:linear-gradient(180deg,#93a5ba,#71809a);}",
|
|
2998
|
+
".dk3-metal .dk3-face:nth-child(5){background:linear-gradient(180deg,var(--dk3-side-hi),#9dadc2);}",
|
|
2999
|
+
".dk3-metal .dk3-face:nth-child(6){background:var(--dk3-side-dk);}",
|
|
3000
|
+
// 书桌与桌腿
|
|
3001
|
+
".dk3-desk .dk3-face{background:linear-gradient(180deg,#9db0c6,#7f92aa);}",
|
|
3002
|
+
".dk3-desk .dk3-face:nth-child(5){background:#c3d2e2;}",
|
|
3003
|
+
// 显示器(薄盒 + 贴在前面的屏幕;组内扇形微转,整组后撤出桌沿)
|
|
3004
|
+
".dk3-mon3{position:absolute;transform-style:preserve-3d;}",
|
|
3005
|
+
".dk3-frame .dk3-face{background:#3a465b;}",
|
|
3006
|
+
".dk3-frame .dk3-face:nth-child(5){background:#55647d;}",
|
|
3007
|
+
".dk3-screen{position:absolute;left:50%;top:50%;background:var(--dk3-screen);border-radius:2px;overflow:hidden;transition:opacity .4s var(--ds-ease-in-out),box-shadow .4s var(--ds-ease-in-out);}",
|
|
3008
|
+
// 屏幕内容:代码块整体向上滚动(10 行=5 行×2 循环,滚半程无缝接回)+ 闪烁光标,速度随 --dkan-speed
|
|
3009
|
+
".dk3-code{position:absolute;left:0;top:0;right:0;display:block;animation:dk3-scroll calc(5s / var(--dkan-speed,1)) linear infinite;}",
|
|
3010
|
+
".dk3-code i{display:block;height:2px;border-radius:1px;margin:2px 3px 0;background:var(--dkan-code-b);opacity:.55;}",
|
|
3011
|
+
".dk3-code i:nth-child(5n+1){width:58%;background:var(--dkan-code-a);}",
|
|
3012
|
+
".dk3-code i:nth-child(5n+2){width:82%;}",
|
|
3013
|
+
".dk3-code i:nth-child(5n+3){width:46%;background:var(--dkan-code-c);}",
|
|
3014
|
+
".dk3-code i:nth-child(5n+4){width:72%;}",
|
|
3015
|
+
".dk3-code i:nth-child(5n){width:54%;background:var(--dkan-code-a);}",
|
|
3016
|
+
".dk3-cur{position:absolute;left:3px;bottom:2px;width:4px;height:2px;background:var(--dkan-code-b);animation:dkan-blink3 1s steps(1) infinite;}",
|
|
3017
|
+
"@keyframes dk3-scroll{to{transform:translateY(-50%)}}",
|
|
3018
|
+
// 人物组(坐在桌子中间近镜头侧 z=30,侧身面朝 +X 三屏;不会被桌体遮挡)
|
|
3019
|
+
".dk3-person{position:absolute;left:96px;top:14px;width:44px;height:64px;transform-style:preserve-3d;transform:translateZ(30px);}",
|
|
3020
|
+
// 动漫人物配色:皮肤/头发/卫衣/裤子
|
|
3021
|
+
".dk3-skin .dk3-face{background:linear-gradient(180deg,#ffd9b8,#f3b98d);}",
|
|
3022
|
+
".dk3-skin .dk3-face:nth-child(5){background:#ffe3c9;}",
|
|
3023
|
+
".dk3-hair .dk3-face{background:linear-gradient(180deg,#5b4632,#3f3021);}",
|
|
3024
|
+
".dk3-hair .dk3-face:nth-child(5){background:#6b543c;}",
|
|
3025
|
+
".dk3-hood .dk3-face{background:linear-gradient(180deg,#7c8ba0,#5b6a80);}",
|
|
3026
|
+
".dk3-hood .dk3-face:nth-child(5){background:#93a5ba;}",
|
|
3027
|
+
".dk3-pants .dk3-face{background:linear-gradient(180deg,#3d4a5c,#2c3646);}",
|
|
3028
|
+
".dk3-pants .dk3-face:nth-child(5){background:#4a5a70;}",
|
|
3029
|
+
// 人物细节:圆角 + 鞋 + 咖啡杯 + 嘴
|
|
3030
|
+
".dk3-headbox .dk3-face{border-radius:3px;}",
|
|
3031
|
+
".dk3-torso .dk3-face{border-radius:3px;}",
|
|
3032
|
+
".dk3-hair .dk3-face{border-radius:2px;}",
|
|
3033
|
+
".dk3-shoe .dk3-face{background:#20262f;border-radius:2px;}",
|
|
3034
|
+
".dk3-mug .dk3-face{background:#c2703d;border-radius:1px;}",
|
|
3035
|
+
".dk3-mug .dk3-face:nth-child(5){background:#e08a52;}",
|
|
3036
|
+
".dk3-mouth{position:absolute;left:50%;top:78%;width:5px;height:1.5px;border-radius:1px;background:#b5766a;}",
|
|
3037
|
+
// 椅子
|
|
3038
|
+
".dk3-chairback .dk3-face{background:linear-gradient(180deg,#3f4c60,#2c3648);}",
|
|
3039
|
+
".dk3-chairseat .dk3-face{background:#33415a;}",
|
|
3040
|
+
// 头组(俯仰=rotateZ,左右看=rotateY);眼睛贴在 +X 面板上
|
|
3041
|
+
".dk3-head3{position:absolute;left:14px;top:2px;width:17px;height:20px;transform-style:preserve-3d;transform-origin:50% 85%;transition:transform .25s var(--ds-ease-in-out);}",
|
|
3042
|
+
".dk3-brows{position:absolute;left:50%;top:30%;display:flex;gap:3px;align-items:center;justify-content:center;}",
|
|
3043
|
+
".dk3-brows i{width:3px;height:1px;border-radius:2px;background:#4a3428;}",
|
|
3044
|
+
".dk3-eyes{position:absolute;left:50%;top:52%;display:flex;gap:3px;align-items:center;justify-content:center;}",
|
|
3045
|
+
".dk3-eyes i{width:3px;height:4px;border-radius:50%;background:radial-gradient(circle at 60% 35%,#fff 0 .5px,#2b3442 .8px);animation:dkan-blink3 4.6s infinite;}",
|
|
3046
|
+
".dk3-nose{position:absolute;left:50%;top:64%;width:2px;height:2px;border-radius:50%;background:#d99277;}",
|
|
3047
|
+
".dk3-ear{position:absolute;left:-1px;top:11px;width:3px;height:5px;border-radius:50%;background:#f3b98d;transform:translateZ(2px);}",
|
|
3048
|
+
"@keyframes dkan-blink3{0%,91%,100%{transform:scaleY(1)}94%{transform:scaleY(.15)}}",
|
|
3049
|
+
// 手臂:肩组挂躯干前上,肘组在其下端(前臂+手伸向键盘);write/code 时肘部高频敲击
|
|
3050
|
+
".dk3-arm3{position:absolute;left:20px;top:30px;width:16px;height:16px;transform-style:preserve-3d;}",
|
|
3051
|
+
".dk3-elbow{position:absolute;left:0;top:10px;width:15px;height:5px;transform-style:preserve-3d;transform-origin:2px 2px;}",
|
|
3052
|
+
".dk3-far{transform:translateZ(-8px);filter:brightness(.62);}",
|
|
3053
|
+
// 思考泡泡(贴镜头 2D 层,think 阶段显示)
|
|
3054
|
+
".dkan-bubble{position:absolute;left:80px;top:4px;display:none;gap:3px;padding:4px 6px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);box-shadow:0 2px 6px rgb(0 0 0 / .15);z-index:3;}",
|
|
3055
|
+
".dkan-bubble i{width:4px;height:4px;border-radius:50%;background:var(--dsw-alias-label-tertiary);animation:dkan-bubdot 1.2s ease-in-out infinite;}",
|
|
3056
|
+
".dkan-bubble i:nth-child(2){animation-delay:.2s;}",
|
|
3057
|
+
".dkan-bubble i:nth-child(3){animation-delay:.4s;}",
|
|
3058
|
+
"@keyframes dkan-bubdot{0%,100%{opacity:.25;transform:translateY(0)}50%{opacity:1;transform:translateY(-2px)}}",
|
|
3059
|
+
// ===== 阶段驱动(data-phase 四态,host 由 chunk 流实时同步) =====
|
|
3060
|
+
// think:屏幕调暗 + 仰头苦想 + 泡泡浮现
|
|
3061
|
+
".dkan-bot-scene[data-phase=think] .dk3-screen{opacity:.32;}",
|
|
3062
|
+
".dkan-bot-scene[data-phase=think] .dkan-bubble{display:inline-flex;}",
|
|
3063
|
+
".dkan-bot-scene[data-phase=think] .dk3-head3{animation:dkan-think-head 1.8s ease-in-out infinite alternate;}",
|
|
3064
|
+
".dkan-bot-scene[data-phase=think] .dk3-arm3:not(.dk3-far){animation:dkan-think-arm 1.8s ease-in-out infinite alternate;}",
|
|
3065
|
+
".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-far{animation:dkan-think-arm-far 1.8s ease-in-out infinite alternate;}",
|
|
3066
|
+
"@keyframes dkan-think-head{from{transform:rotateZ(-12deg) translateY(-1px)}to{transform:rotateZ(-22deg) translate(3px,-4px)}}",
|
|
3067
|
+
"@keyframes dkan-think-arm{from{transform:rotateZ(-4deg)}to{transform:rotateZ(-34deg) translate(1px,-8px)}}",
|
|
3068
|
+
"@keyframes dkan-think-arm-far{from{transform:translateZ(-8px) rotateZ(-2deg)}to{transform:translateZ(-8px) rotateZ(-24deg) translate(1px,-7px)}}",
|
|
3069
|
+
// write/code:中屏高亮代码滚动 + 肘部高频敲击 + 低头专注
|
|
3070
|
+
".dkan-bot-scene[data-phase=write] .dk3-mon3.center .dk3-screen,.dkan-bot-scene[data-phase=code] .dk3-mon3.center .dk3-screen{opacity:1;box-shadow:0 0 10px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 45%,transparent);}",
|
|
3071
|
+
".dkan-bot-scene[data-phase=write] .dk3-mon3.center .dk3-code,.dkan-bot-scene[data-phase=code] .dk3-mon3.center .dk3-code{animation-duration:calc(2.2s / var(--dkan-speed,1));}",
|
|
3072
|
+
".dkan-bot-scene[data-phase=write] .dk3-arm3:not(.dk3-far),.dkan-bot-scene[data-phase=code] .dk3-arm3:not(.dk3-far){animation:dkan-output-arm calc(.46s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
|
|
3073
|
+
".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far{animation:dkan-output-arm-far calc(.46s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
|
|
3074
|
+
".dkan-bot-scene[data-phase=write] .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-elbow{animation:dkan-type3 calc(.22s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
|
|
3075
|
+
".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far .dk3-elbow{animation-delay:.11s;}",
|
|
3076
|
+
"@keyframes dkan-type3{from{transform:rotate(12deg) translateY(-1px)}to{transform:rotate(-14deg) translateY(2px)}}",
|
|
3077
|
+
"@keyframes dkan-output-arm{from{transform:rotateZ(7deg) translateY(0)}to{transform:rotateZ(-13deg) translateY(4px)}}",
|
|
3078
|
+
"@keyframes dkan-output-arm-far{from{transform:translateZ(-8px) rotateZ(5deg)}to{transform:translateZ(-8px) rotateZ(-11deg) translateY(4px)}}",
|
|
3079
|
+
".dkan-bot-scene[data-phase=write] .dk3-head3,.dkan-bot-scene[data-phase=code] .dk3-head3{animation:dkan-output-head calc(.8s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
|
|
3080
|
+
"@keyframes dkan-output-head{from{transform:rotateZ(4deg) translateY(0)}to{transform:rotateZ(10deg) translate(2px,2px)}}",
|
|
3081
|
+
// search:侧屏高亮 + 滚动加速 + 头部左右扫视(一会忙这个一会看那个)
|
|
3082
|
+
".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-phase=search] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--dkan-code-a,#4ade80) 40%,transparent);}",
|
|
3083
|
+
".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-phase=search] .dk3-mon3.right .dk3-code{animation-duration:calc(1.6s / var(--dkan-speed,1));}",
|
|
3084
|
+
".dkan-bot-scene[data-phase=search] .dk3-head3{animation:dkan-scan3 3.4s ease-in-out infinite;}",
|
|
3085
|
+
"@keyframes dkan-scan3{0%,16%{transform:rotateZ(3deg) rotateY(-38deg)}30%,48%{transform:rotateZ(3deg) rotateY(6deg)}62%,80%{transform:rotateZ(3deg) rotateY(38deg)}100%{transform:rotateZ(3deg) rotateY(-38deg)}}",
|
|
3086
|
+
"@media (prefers-reduced-motion:reduce){.dkan-botcard *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;}}",
|
|
3087
|
+
// 通知子选项行
|
|
3088
|
+
".dkan-rows-narrow{display:flex;flex-direction:column;gap:6px;}",
|
|
3089
|
+
".dkan-row{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary);flex-wrap:wrap;}",
|
|
3090
|
+
".dkan-row-label{flex:none;min-width:60px;color:var(--dsw-alias-label-primary);}",
|
|
3091
|
+
".dkan-row-sub{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3092
|
+
".dkm-miniswitch{cursor:pointer;flex:none;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 12px;font-family:inherit;font-size:11px;line-height:18px;}",
|
|
3093
|
+
".dkm-miniswitch.on{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
3094
|
+
".dkan-select{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:3px 8px;font-size:12px;font-family:inherit;}",
|
|
3095
|
+
// 音效选择卡(名称 + 播放键;选中态描边)
|
|
3096
|
+
".dkan-sounds{display:flex;gap:6px;flex-wrap:wrap;}",
|
|
3097
|
+
".dkan-sound{flex:1;min-width:104px;display:flex;align-items:center;justify-content:space-between;gap:6px;padding:6px 10px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2);cursor:pointer;font-family:inherit;transition:border-color .15s var(--ds-ease-in-out);}",
|
|
3098
|
+
".dkan-sound:hover{border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3099
|
+
".dkan-sound.on{border-color:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 0 1px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 40%,transparent);}",
|
|
3100
|
+
".dkan-sound-name{font-size:12px;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:5px;}",
|
|
3101
|
+
".dkan-sound-cur{color:var(--dsw-alias-accent,#4d9fff);font-size:11px;}",
|
|
3102
|
+
".dkan-sound-play{flex:none;cursor:pointer;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:1;border-radius:50%;width:20px;height:20px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--dsw-alias-border-l2);}",
|
|
3103
|
+
".dkan-sound-play:hover{color:var(--dsw-alias-label-primary);border-color:currentColor;}",
|
|
3104
|
+
".dkan-input{flex:1;min-width:220px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:4px 8px;font-size:12px;font-family:inherit;}",
|
|
3105
|
+
".dkan-input:focus{outline:none;border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3106
|
+
".dkan-row-webhook{flex-wrap:nowrap;}",
|
|
3107
|
+
".dkan-row-webhook .dkan-input{min-width:0;}",
|
|
3108
|
+
".dkan-btn{cursor:pointer;flex:none;color:var(--dsw-alias-label-primary);background:transparent;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:4px 12px;font-family:inherit;font-size:12px;}",
|
|
3109
|
+
".dkan-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
|
|
3110
|
+
".dkan-btn[disabled]{opacity:.5;cursor:default;}",
|
|
3111
|
+
".dkan-ok{color:var(--dsw-alias-state-success-primary);}",
|
|
3112
|
+
// 任务列表
|
|
3113
|
+
".dkan-tasks{display:flex;flex-direction:column;gap:6px;}",
|
|
3114
|
+
".dkan-tasks-done{border-top:1px dashed var(--dsw-alias-border-l2);padding-top:6px;}",
|
|
3115
|
+
".dkan-task{border:1px solid var(--dsw-alias-border-l1);border-radius:8px;padding:6px 10px;display:flex;flex-direction:column;gap:3px;}",
|
|
3116
|
+
".dkan-task-head{display:flex;align-items:center;gap:8px;min-width:0;}",
|
|
3117
|
+
".dkan-task-title{font-size:12px;font-weight:600;color:var(--dsw-alias-label-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
3118
|
+
".dkan-task-meta{display:flex;gap:10px;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3119
|
+
".dkan-task-err{font-size:11px;color:var(--dsw-alias-state-error-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
3120
|
+
".dkan-tag{flex:none;font-size:10px;border-radius:999px;padding:0 8px;color:var(--dsw-alias-label-tertiary);border:1px solid var(--dsw-alias-border-l2);}",
|
|
3121
|
+
".dkan-tag.on{color:var(--dsw-alias-accent,#4d9fff);border-color:currentColor;}",
|
|
3122
|
+
".dkan-tag.ok{color:var(--dsw-alias-state-success-primary);border-color:currentColor;}",
|
|
3123
|
+
".dkan-tag.err{color:var(--dsw-alias-state-error-primary);border-color:currentColor;}",
|
|
3124
|
+
".dkan-tag.warn{color:var(--dsw-alias-state-warning-primary);border-color:currentColor;}"
|
|
3125
|
+
].join("\n");
|
|
3126
|
+
var feature6 = {
|
|
3127
|
+
id: "animation",
|
|
3128
|
+
name: "\u4EFB\u52A1\u52A8\u753B",
|
|
3129
|
+
order: 130,
|
|
3130
|
+
accent: "#f472b6",
|
|
3131
|
+
description: "\u4EFB\u52A1\u8FD0\u884C\u52A8\u753B\uFF08\u6D41\u5149\u7EC6\u7EBF/\u547C\u5438\u5149\u70B9/\u8F68\u9053\u5149\u73AF\uFF09\u4E0E\u5B8C\u6210\u901A\u77E5\uFF0C\u4E24\u7EC4\u5F00\u5173\u72EC\u7ACB\u3001\u914D\u7F6E\u6301\u4E45\u5316",
|
|
3132
|
+
css: css2,
|
|
3133
|
+
View: AnimationView,
|
|
3134
|
+
HomeStat: AnimationStat,
|
|
3135
|
+
Overlay: AnimationOverlay
|
|
1613
3136
|
};
|
|
3137
|
+
|
|
3138
|
+
// src/client.jsx
|
|
3139
|
+
var DOCK_VERSION = "0.5.0";
|
|
3140
|
+
var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6];
|
|
3141
|
+
var PLANNED_FEATURES = [];
|
|
3142
|
+
var PLANNED_NOTES = {};
|
|
1614
3143
|
var externalDefs = [];
|
|
1615
3144
|
var externalListeners = /* @__PURE__ */ new Set();
|
|
1616
3145
|
function notifyExternal() {
|
|
@@ -1633,6 +3162,7 @@ var dockBridge = {
|
|
|
1633
3162
|
css: typeof def.css === "string" ? def.css : "",
|
|
1634
3163
|
View: def.View,
|
|
1635
3164
|
HomeStat: typeof def.HomeStat === "function" ? def.HomeStat : null,
|
|
3165
|
+
Overlay: typeof def.Overlay === "function" ? def.Overlay : null,
|
|
1636
3166
|
external: true,
|
|
1637
3167
|
package: typeof def.package === "string" ? def.package : ""
|
|
1638
3168
|
};
|
|
@@ -1717,9 +3247,22 @@ var SHELL_CSS = [
|
|
|
1717
3247
|
".dockh-card:hover,.dockh-card:focus-visible{border-color:var(--dsw-alias-accent,#4d9fff);outline:none;}",
|
|
1718
3248
|
".dockh-head{display:flex;align-items:center;gap:8px;}",
|
|
1719
3249
|
".dockh-name{font-weight:600;flex:none;}",
|
|
1720
|
-
".dockh-badge{
|
|
1721
|
-
|
|
1722
|
-
".dockh-
|
|
3250
|
+
".dockh-badge{flex:none;font-size:11px;border-radius:999px;padding:0 8px;color:var(--dsw-alias-label-tertiary);border:1px solid var(--dsw-alias-border-l2);}",
|
|
3251
|
+
// 状态标识(非交互:圆点+文字,与可点的开关一眼区分)
|
|
3252
|
+
".dockh-status{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--dsw-alias-label-tertiary);white-space:nowrap;}",
|
|
3253
|
+
".dockh-sdot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--dsw-alias-state-success-primary,#34d399);box-shadow:0 0 4px color-mix(in srgb,var(--dsw-alias-state-success-primary,#34d399) 55%,transparent);}",
|
|
3254
|
+
".dockh-status.off .dockh-sdot{background:transparent;border:1.5px solid var(--dsw-alias-label-tertiary);box-shadow:none;opacity:.75;}",
|
|
3255
|
+
".dockh-status.plan .dockh-sdot{background:transparent;border:1.5px dashed var(--dsw-alias-label-tertiary);box-shadow:none;}",
|
|
3256
|
+
// iOS 风滑动开关(首页卡片 / 弹层页脚 / 设置页共用的启停控件)
|
|
3257
|
+
".dock-sw{flex:none;position:relative;width:34px;height:19px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;padding:0;transition:background .18s var(--ds-ease-in-out),border-color .18s var(--ds-ease-in-out);}",
|
|
3258
|
+
'.dock-sw::after{content:"";position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgb(0 0 0 / .35);transition:transform .18s var(--ds-ease-in-out);}',
|
|
3259
|
+
".dock-sw:hover{border-color:var(--dsw-alias-accent,#4d9fff);}",
|
|
3260
|
+
".dock-sw.on{background:var(--dsw-alias-state-success-primary,#34d399);border-color:transparent;}",
|
|
3261
|
+
".dock-sw.on::after{transform:translateX(15px);}",
|
|
3262
|
+
// 弹层页脚:文字标签 + 开关 成组
|
|
3263
|
+
".dockm-foot-sw{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:8px;}",
|
|
3264
|
+
".dockm-foot-swlabel{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
|
|
3265
|
+
".dockm-foot-swlabel.on{color:var(--dsw-alias-state-success-primary);}",
|
|
1723
3266
|
".dockh-desc{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;}",
|
|
1724
3267
|
".dockh-stat{color:var(--dsw-alias-label-tertiary);font-size:12px;border-top:1px solid var(--dsw-alias-border-l1);padding-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
|
|
1725
3268
|
".dockh-foot{display:flex;align-items:center;gap:8px;}",
|
|
@@ -1756,8 +3299,8 @@ function ensureCss() {
|
|
|
1756
3299
|
}
|
|
1757
3300
|
}
|
|
1758
3301
|
function useExternalVersion() {
|
|
1759
|
-
const [, bump] =
|
|
1760
|
-
|
|
3302
|
+
const [, bump] = import_react8.default.useReducer((n) => n + 1, 0);
|
|
3303
|
+
import_react8.default.useEffect(() => {
|
|
1761
3304
|
externalListeners.add(bump);
|
|
1762
3305
|
return () => {
|
|
1763
3306
|
externalListeners.delete(bump);
|
|
@@ -1766,20 +3309,20 @@ function useExternalVersion() {
|
|
|
1766
3309
|
}
|
|
1767
3310
|
var lastGeom = { x: null, y: null, w: null, h: null };
|
|
1768
3311
|
function DockIcon() {
|
|
1769
|
-
return
|
|
3312
|
+
return import_react8.default.createElement(
|
|
1770
3313
|
"svg",
|
|
1771
3314
|
{ width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
3315
|
+
import_react8.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
|
|
3316
|
+
import_react8.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
|
|
3317
|
+
import_react8.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
|
|
3318
|
+
import_react8.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
|
|
1776
3319
|
);
|
|
1777
3320
|
}
|
|
1778
3321
|
function DockEntry(props) {
|
|
1779
3322
|
const wide = !!props.wide;
|
|
1780
|
-
const [open, setOpen] =
|
|
1781
|
-
|
|
1782
|
-
return
|
|
3323
|
+
const [open, setOpen] = import_react8.default.useState(panelNav.open);
|
|
3324
|
+
import_react8.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
|
|
3325
|
+
return import_react8.default.createElement("button", {
|
|
1783
3326
|
type: "button",
|
|
1784
3327
|
className: "docke2-btn" + (open ? " docke2-on" : ""),
|
|
1785
3328
|
style: wide ? { marginLeft: "auto", transform: "translateY(46px)", zIndex: 1, height: 42, lineHeight: "42px", padding: "0 12px" } : { transform: "translateY(44px)", zIndex: 1, width: 36, height: 36, justifyContent: "center", padding: 0 },
|
|
@@ -1787,20 +3330,20 @@ function DockEntry(props) {
|
|
|
1787
3330
|
"aria-label": "\u529F\u80FD\u575E",
|
|
1788
3331
|
"aria-expanded": open,
|
|
1789
3332
|
onClick: () => setPanelOpen(!open)
|
|
1790
|
-
},
|
|
3333
|
+
}, import_react8.default.createElement(DockIcon, null), wide ? import_react8.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
|
|
1791
3334
|
}
|
|
1792
3335
|
function DockModal() {
|
|
1793
|
-
const [nav, setNav] =
|
|
1794
|
-
|
|
3336
|
+
const [nav, setNav] = import_react8.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
|
|
3337
|
+
import_react8.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
|
|
1795
3338
|
const open = nav.open || typeof document === "undefined";
|
|
1796
3339
|
const active = nav.active;
|
|
1797
3340
|
const setActive = navigatePanel;
|
|
1798
3341
|
const navParams = nav.params;
|
|
1799
|
-
const [, force] =
|
|
3342
|
+
const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
|
|
1800
3343
|
useExternalVersion();
|
|
1801
|
-
const [win, setWin] =
|
|
1802
|
-
const dlgRef =
|
|
1803
|
-
|
|
3344
|
+
const [win, setWin] = import_react8.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
|
|
3345
|
+
const dlgRef = import_react8.default.useRef(null);
|
|
3346
|
+
import_react8.default.useEffect(() => {
|
|
1804
3347
|
if (lastGeom.w) setWin({ mode: "normal", x: lastGeom.x, y: lastGeom.y, w: lastGeom.w, h: lastGeom.h });
|
|
1805
3348
|
}, []);
|
|
1806
3349
|
function beginDrag(e, type) {
|
|
@@ -1838,13 +3381,13 @@ function DockModal() {
|
|
|
1838
3381
|
const mod = isHome ? null : MODULES.find((m) => m.id === active) || MODULES[0];
|
|
1839
3382
|
const st = mod ? stateOf(mod.id) : null;
|
|
1840
3383
|
const View = mod ? mod.View : null;
|
|
1841
|
-
const viewNode = mod && View ?
|
|
3384
|
+
const viewNode = mod && View ? import_react8.default.createElement(
|
|
1842
3385
|
"div",
|
|
1843
3386
|
{ className: "dockm-view" },
|
|
1844
|
-
|
|
1845
|
-
mod.external ? FeatureBoundary :
|
|
3387
|
+
import_react8.default.createElement(
|
|
3388
|
+
mod.external ? FeatureBoundary : import_react8.default.Fragment,
|
|
1846
3389
|
null,
|
|
1847
|
-
|
|
3390
|
+
import_react8.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
|
|
1848
3391
|
)
|
|
1849
3392
|
) : null;
|
|
1850
3393
|
const enabledCount = MODULES.filter((m) => {
|
|
@@ -1858,10 +3401,10 @@ function DockModal() {
|
|
|
1858
3401
|
width: win.w != null ? win.w : void 0,
|
|
1859
3402
|
height: win.mode === "min" ? "auto" : win.h != null ? win.h : void 0
|
|
1860
3403
|
} : null;
|
|
1861
|
-
return
|
|
3404
|
+
return import_react8.default.createElement(
|
|
1862
3405
|
"div",
|
|
1863
3406
|
{ className: "dockm-backdrop", onClick: () => setPanelOpen(false) },
|
|
1864
|
-
|
|
3407
|
+
import_react8.default.createElement(
|
|
1865
3408
|
"div",
|
|
1866
3409
|
{
|
|
1867
3410
|
className: "dockm-dialog" + (win.mode === "max" ? " dockm-max" : "") + (win.mode === "min" ? " dockm-min" : ""),
|
|
@@ -1869,41 +3412,41 @@ function DockModal() {
|
|
|
1869
3412
|
ref: dlgRef,
|
|
1870
3413
|
onClick: (e) => e.stopPropagation()
|
|
1871
3414
|
},
|
|
1872
|
-
|
|
3415
|
+
import_react8.default.createElement(
|
|
1873
3416
|
"div",
|
|
1874
3417
|
{
|
|
1875
3418
|
className: "dockm-head",
|
|
1876
3419
|
onPointerDown: (e) => beginDrag(e, "move"),
|
|
1877
3420
|
onDoubleClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
|
|
1878
3421
|
},
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
3422
|
+
import_react8.default.createElement(DockIcon, null),
|
|
3423
|
+
import_react8.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
|
|
3424
|
+
import_react8.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
|
|
3425
|
+
import_react8.default.createElement(
|
|
1883
3426
|
"span",
|
|
1884
3427
|
{ className: "dockm-ctrls" },
|
|
1885
|
-
|
|
3428
|
+
import_react8.default.createElement("button", {
|
|
1886
3429
|
type: "button",
|
|
1887
3430
|
className: "dockm-win",
|
|
1888
3431
|
title: win.mode === "min" ? "\u8FD8\u539F" : "\u6700\u5C0F\u5316",
|
|
1889
3432
|
onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "min" ? "normal" : "min" }))
|
|
1890
3433
|
}, "\u2581"),
|
|
1891
|
-
|
|
3434
|
+
import_react8.default.createElement("button", {
|
|
1892
3435
|
type: "button",
|
|
1893
3436
|
className: "dockm-win",
|
|
1894
3437
|
title: win.mode === "max" ? "\u8FD8\u539F" : "\u6700\u5927\u5316",
|
|
1895
3438
|
onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
|
|
1896
3439
|
}, win.mode === "max" ? "\u2750" : "\u25A2"),
|
|
1897
|
-
|
|
3440
|
+
import_react8.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
|
|
1898
3441
|
)
|
|
1899
3442
|
),
|
|
1900
|
-
|
|
3443
|
+
import_react8.default.createElement(
|
|
1901
3444
|
"div",
|
|
1902
3445
|
{ className: "dockm-body" },
|
|
1903
|
-
|
|
3446
|
+
import_react8.default.createElement(
|
|
1904
3447
|
"nav",
|
|
1905
3448
|
{ className: "dockm-nav", "aria-label": "\u529F\u80FD\u6A21\u5757" },
|
|
1906
|
-
|
|
3449
|
+
import_react8.default.createElement(
|
|
1907
3450
|
"button",
|
|
1908
3451
|
{
|
|
1909
3452
|
type: "button",
|
|
@@ -1911,10 +3454,10 @@ function DockModal() {
|
|
|
1911
3454
|
className: "dockm-nav-item" + (isHome ? " on" : ""),
|
|
1912
3455
|
onClick: () => setActive("home")
|
|
1913
3456
|
},
|
|
1914
|
-
|
|
1915
|
-
|
|
3457
|
+
import_react8.default.createElement("span", { className: "dockm-navhome" }, import_react8.default.createElement(DockIcon, null)),
|
|
3458
|
+
import_react8.default.createElement("span", null, "\u9996\u9875")
|
|
1916
3459
|
),
|
|
1917
|
-
MODULES.map((m) =>
|
|
3460
|
+
MODULES.map((m) => import_react8.default.createElement(
|
|
1918
3461
|
"button",
|
|
1919
3462
|
{
|
|
1920
3463
|
type: "button",
|
|
@@ -1922,81 +3465,98 @@ function DockModal() {
|
|
|
1922
3465
|
className: "dockm-nav-item" + (m.id === active ? " on" : ""),
|
|
1923
3466
|
onClick: () => setActive(m.id)
|
|
1924
3467
|
},
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
m.planned ?
|
|
1928
|
-
m.external ?
|
|
3468
|
+
import_react8.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
|
|
3469
|
+
import_react8.default.createElement("span", null, m.name),
|
|
3470
|
+
m.planned ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
|
|
3471
|
+
m.external ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
|
|
1929
3472
|
))
|
|
1930
3473
|
),
|
|
1931
|
-
|
|
3474
|
+
import_react8.default.createElement(
|
|
1932
3475
|
"div",
|
|
1933
3476
|
{ className: "dockm-content" },
|
|
1934
|
-
|
|
3477
|
+
import_react8.default.createElement(
|
|
1935
3478
|
"div",
|
|
1936
3479
|
{ className: "dockm-content-head" },
|
|
1937
|
-
|
|
3480
|
+
import_react8.default.createElement(
|
|
1938
3481
|
"div",
|
|
1939
3482
|
{ className: "dockm-name" },
|
|
1940
|
-
isHome ?
|
|
3483
|
+
isHome ? import_react8.default.createElement("span", { className: "dockm-navhome" }, import_react8.default.createElement(DockIcon, null)) : import_react8.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
|
|
1941
3484
|
isHome ? "\u9996\u9875" : mod.name,
|
|
1942
|
-
!isHome && mod.planned ?
|
|
1943
|
-
!isHome && mod.external ?
|
|
3485
|
+
!isHome && mod.planned ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
|
|
3486
|
+
!isHome && mod.external ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
|
|
1944
3487
|
),
|
|
1945
|
-
|
|
3488
|
+
import_react8.default.createElement(
|
|
1946
3489
|
"div",
|
|
1947
3490
|
{ className: "dockm-desc" },
|
|
1948
3491
|
isHome ? "\u6240\u6709\u5B50\u529F\u80FD\u603B\u63FD\uFF1A\u8FD0\u884C\u72B6\u6001\u3001\u6982\u8981\u4E0E\u5FEB\u6377\u5F00\u5173\uFF0C\u70B9\u51FB\u5361\u7247\u8FDB\u5165\u5BF9\u5E94\u529F\u80FD\u9875\u3002" : mod.description
|
|
1949
3492
|
)
|
|
1950
3493
|
),
|
|
1951
|
-
isHome ?
|
|
1952
|
-
|
|
3494
|
+
isHome ? import_react8.default.createElement("div", { className: "dockm-view" }, import_react8.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react8.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react8.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react8.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
|
|
3495
|
+
import_react8.default.createElement(
|
|
1953
3496
|
"div",
|
|
1954
3497
|
{ className: "dockm-foot" },
|
|
1955
|
-
|
|
1956
|
-
!isHome && mod && !mod.planned && st ?
|
|
1957
|
-
|
|
1958
|
-
className: "dockm-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
}
|
|
1972
|
-
|
|
3498
|
+
import_react8.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
|
|
3499
|
+
!isHome && mod && !mod.planned && st ? import_react8.default.createElement(
|
|
3500
|
+
"span",
|
|
3501
|
+
{ className: "dockm-foot-sw" },
|
|
3502
|
+
import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
|
|
3503
|
+
import_react8.default.createElement("button", {
|
|
3504
|
+
type: "button",
|
|
3505
|
+
className: "dock-sw" + (st.enabled ? " on" : ""),
|
|
3506
|
+
role: "switch",
|
|
3507
|
+
"aria-checked": !!st.enabled,
|
|
3508
|
+
"aria-label": (st.enabled ? "\u505C\u7528" : "\u542F\u7528") + mod.name,
|
|
3509
|
+
title: st.enabled ? "\u505C\u7528\u300C" + mod.name + "\u300D" : "\u542F\u7528\u300C" + mod.name + "\u300D",
|
|
3510
|
+
onClick: () => {
|
|
3511
|
+
toggleFeature(mod.id);
|
|
3512
|
+
force();
|
|
3513
|
+
}
|
|
3514
|
+
})
|
|
3515
|
+
) : null,
|
|
3516
|
+
!isHome && mod && typeof mod.Chip === "function" ? import_react8.default.createElement(
|
|
3517
|
+
"span",
|
|
3518
|
+
{ className: "dockm-foot-sw" },
|
|
3519
|
+
import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
|
|
3520
|
+
import_react8.default.createElement("button", {
|
|
3521
|
+
type: "button",
|
|
3522
|
+
className: "dock-sw" + (chipShown(mod.id) ? " on" : ""),
|
|
3523
|
+
role: "switch",
|
|
3524
|
+
"aria-checked": chipShown(mod.id),
|
|
3525
|
+
"aria-label": (chipShown(mod.id) ? "\u9690\u85CF" : "\u663E\u793A") + mod.name + "\u7684\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6",
|
|
3526
|
+
title: "\u63A7\u5236\u4F1A\u8BDD\u8F93\u5165\u533A\uFF08\u6A21\u578B\u9009\u62E9\u5668\u5DE6\u4FA7\uFF09\u662F\u5426\u663E\u793A\u672C\u529F\u80FD\u7684\u968F\u8EAB\u5C0F\u63A7\u4EF6",
|
|
3527
|
+
onClick: () => {
|
|
3528
|
+
setChipShown(mod.id, !chipShown(mod.id));
|
|
3529
|
+
force();
|
|
3530
|
+
}
|
|
3531
|
+
})
|
|
3532
|
+
) : null
|
|
1973
3533
|
)
|
|
1974
3534
|
)
|
|
1975
3535
|
),
|
|
1976
|
-
win.mode === "normal" ?
|
|
3536
|
+
win.mode === "normal" ? import_react8.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
|
|
1977
3537
|
)
|
|
1978
3538
|
);
|
|
1979
3539
|
}
|
|
1980
3540
|
function HomeView(props) {
|
|
1981
3541
|
const ctx = props && props.ctx;
|
|
1982
|
-
const [, force] =
|
|
3542
|
+
const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
|
|
1983
3543
|
useExternalVersion();
|
|
1984
3544
|
const open = (id) => {
|
|
1985
3545
|
if (props && typeof props.onOpen === "function") props.onOpen(id);
|
|
1986
3546
|
};
|
|
1987
|
-
return
|
|
3547
|
+
return import_react8.default.createElement(
|
|
1988
3548
|
"div",
|
|
1989
3549
|
{ className: "dockh-grid" },
|
|
1990
3550
|
allModules().map((m) => {
|
|
1991
3551
|
const st = stateOf(m.id);
|
|
1992
3552
|
const enabled = !!(st && st.enabled);
|
|
1993
3553
|
const Stat = m.HomeStat;
|
|
1994
|
-
const statNode = m.planned ?
|
|
1995
|
-
m.external ? FeatureBoundary :
|
|
3554
|
+
const statNode = m.planned ? import_react8.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react8.default.createElement(
|
|
3555
|
+
m.external ? FeatureBoundary : import_react8.default.Fragment,
|
|
1996
3556
|
null,
|
|
1997
|
-
|
|
1998
|
-
) :
|
|
1999
|
-
return
|
|
3557
|
+
import_react8.default.createElement(Stat, { ctx })
|
|
3558
|
+
) : import_react8.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
|
|
3559
|
+
return import_react8.default.createElement(
|
|
2000
3560
|
"div",
|
|
2001
3561
|
{
|
|
2002
3562
|
key: m.id,
|
|
@@ -2011,34 +3571,41 @@ function HomeView(props) {
|
|
|
2011
3571
|
}
|
|
2012
3572
|
}
|
|
2013
3573
|
},
|
|
2014
|
-
|
|
3574
|
+
import_react8.default.createElement(
|
|
2015
3575
|
"div",
|
|
2016
3576
|
{ className: "dockh-head" },
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
m.external ?
|
|
2020
|
-
|
|
3577
|
+
import_react8.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
|
|
3578
|
+
import_react8.default.createElement("span", { className: "dockh-name" }, m.name),
|
|
3579
|
+
m.external ? import_react8.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
|
|
3580
|
+
// 状态标识:圆点 + 文字(纯展示,与开关视觉区分)
|
|
3581
|
+
import_react8.default.createElement(
|
|
2021
3582
|
"span",
|
|
2022
|
-
{ className: "dockh-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
import_react7.default.createElement(
|
|
2029
|
-
"div",
|
|
2030
|
-
{ className: "dockh-foot" },
|
|
2031
|
-
import_react7.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192"),
|
|
2032
|
-
m.planned ? null : import_react7.default.createElement("button", {
|
|
3583
|
+
{ className: "dockh-status" + (m.planned ? " plan" : enabled ? "" : " off") },
|
|
3584
|
+
import_react8.default.createElement("span", { className: "dockh-sdot" }),
|
|
3585
|
+
import_react8.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
|
|
3586
|
+
),
|
|
3587
|
+
// 启停开关(规划中的功能不显示)
|
|
3588
|
+
m.planned ? null : import_react8.default.createElement("button", {
|
|
2033
3589
|
type: "button",
|
|
2034
|
-
className: "
|
|
3590
|
+
className: "dock-sw" + (enabled ? " on" : ""),
|
|
3591
|
+
role: "switch",
|
|
3592
|
+
"aria-checked": enabled,
|
|
3593
|
+
"aria-label": (enabled ? "\u505C\u7528" : "\u542F\u7528") + m.name,
|
|
3594
|
+
title: enabled ? "\u505C\u7528\u300C" + m.name + "\u300D" : "\u542F\u7528\u300C" + m.name + "\u300D",
|
|
2035
3595
|
onClick: (e) => {
|
|
2036
3596
|
e.stopPropagation();
|
|
2037
3597
|
toggleFeature(m.id);
|
|
2038
3598
|
if (props && typeof props.onToggle === "function") props.onToggle();
|
|
2039
3599
|
force();
|
|
2040
3600
|
}
|
|
2041
|
-
}
|
|
3601
|
+
})
|
|
3602
|
+
),
|
|
3603
|
+
import_react8.default.createElement("div", { className: "dockh-desc" }, m.description),
|
|
3604
|
+
import_react8.default.createElement("div", { className: "dockh-stat" }, statNode),
|
|
3605
|
+
import_react8.default.createElement(
|
|
3606
|
+
"div",
|
|
3607
|
+
{ className: "dockh-foot" },
|
|
3608
|
+
import_react8.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
|
|
2042
3609
|
)
|
|
2043
3610
|
);
|
|
2044
3611
|
})
|
|
@@ -2046,16 +3613,16 @@ function HomeView(props) {
|
|
|
2046
3613
|
}
|
|
2047
3614
|
function DockPanel() {
|
|
2048
3615
|
const ctx = ctxRef.current;
|
|
2049
|
-
const [, force] =
|
|
3616
|
+
const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
|
|
2050
3617
|
useExternalVersion();
|
|
2051
3618
|
const toggle = (id) => {
|
|
2052
3619
|
toggleFeature(id);
|
|
2053
3620
|
force();
|
|
2054
3621
|
};
|
|
2055
|
-
return
|
|
3622
|
+
return import_react8.default.createElement(
|
|
2056
3623
|
"div",
|
|
2057
3624
|
{ className: "dock-root" },
|
|
2058
|
-
|
|
3625
|
+
import_react8.default.createElement(
|
|
2059
3626
|
"div",
|
|
2060
3627
|
{ className: "dock-intro" },
|
|
2061
3628
|
"\u529F\u80FD\u575E\uFF08dsh-dock\uFF09\xB7 \u6240\u6709\u5C0F\u529F\u80FD\u96C6\u4E2D\u5728\u8FD9\u4E00\u4E2A\u9762\u677F\u91CC\u7BA1\u7406\u3002v0.4.0 \u8D77\u6BCF\u4E2A\u529F\u80FD\u662F\u72EC\u7ACB\u6A21\u5757\uFF08features/<id>/\uFF09\uFF0C",
|
|
@@ -2064,50 +3631,64 @@ function DockPanel() {
|
|
|
2064
3631
|
allModules().map((f) => {
|
|
2065
3632
|
const st = stateOf(f.id);
|
|
2066
3633
|
const View = f.View;
|
|
2067
|
-
const viewNode = !f.planned && st.enabled && View ?
|
|
3634
|
+
const viewNode = !f.planned && st.enabled && View ? import_react8.default.createElement(
|
|
2068
3635
|
"div",
|
|
2069
3636
|
{ className: "dock-body" },
|
|
2070
|
-
|
|
2071
|
-
f.external ? FeatureBoundary :
|
|
3637
|
+
import_react8.default.createElement(
|
|
3638
|
+
f.external ? FeatureBoundary : import_react8.default.Fragment,
|
|
2072
3639
|
null,
|
|
2073
|
-
|
|
3640
|
+
import_react8.default.createElement(View, { ctx, feature: f })
|
|
2074
3641
|
)
|
|
2075
3642
|
) : null;
|
|
2076
|
-
return
|
|
3643
|
+
return import_react8.default.createElement(
|
|
2077
3644
|
"div",
|
|
2078
3645
|
{ className: "dock-card", key: f.id },
|
|
2079
|
-
|
|
3646
|
+
import_react8.default.createElement(
|
|
2080
3647
|
"div",
|
|
2081
3648
|
{ className: "dock-card-head" },
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
f.planned ?
|
|
2086
|
-
|
|
3649
|
+
import_react8.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
|
|
3650
|
+
import_react8.default.createElement("span", { className: "dock-name" }, f.name),
|
|
3651
|
+
import_react8.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
|
|
3652
|
+
f.planned ? import_react8.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react8.default.createElement("button", {
|
|
3653
|
+
type: "button",
|
|
3654
|
+
className: "dock-sw" + (st.enabled ? " on" : ""),
|
|
3655
|
+
role: "switch",
|
|
3656
|
+
"aria-checked": st.enabled,
|
|
3657
|
+
"aria-label": (st.enabled ? "\u505C\u7528" : "\u542F\u7528") + f.name,
|
|
3658
|
+
title: st.enabled ? "\u505C\u7528\u300C" + f.name + "\u300D" : "\u542F\u7528\u300C" + f.name + "\u300D",
|
|
2087
3659
|
onClick: () => toggle(f.id)
|
|
2088
|
-
}
|
|
2089
|
-
!f.planned && typeof f.Chip === "function" ?
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
3660
|
+
}),
|
|
3661
|
+
!f.planned && typeof f.Chip === "function" ? import_react8.default.createElement(
|
|
3662
|
+
"span",
|
|
3663
|
+
{ className: "dockm-foot-sw" },
|
|
3664
|
+
import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
|
|
3665
|
+
import_react8.default.createElement("button", {
|
|
3666
|
+
type: "button",
|
|
3667
|
+
className: "dock-sw" + (chipShown(f.id) ? " on" : ""),
|
|
3668
|
+
role: "switch",
|
|
3669
|
+
"aria-checked": chipShown(f.id),
|
|
3670
|
+
"aria-label": (chipShown(f.id) ? "\u9690\u85CF" : "\u663E\u793A") + f.name + "\u7684\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6",
|
|
3671
|
+
title: "\u63A7\u5236\u4F1A\u8BDD\u8F93\u5165\u533A\uFF08\u6A21\u578B\u9009\u62E9\u5668\u5DE6\u4FA7\uFF09\u662F\u5426\u663E\u793A\u672C\u529F\u80FD\u7684\u968F\u8EAB\u5C0F\u63A7\u4EF6",
|
|
3672
|
+
onClick: () => {
|
|
3673
|
+
setChipShown(f.id, !chipShown(f.id));
|
|
3674
|
+
force();
|
|
3675
|
+
}
|
|
3676
|
+
})
|
|
3677
|
+
) : null
|
|
2097
3678
|
),
|
|
2098
|
-
f.planned ?
|
|
3679
|
+
f.planned ? import_react8.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react8.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
|
|
2099
3680
|
viewNode
|
|
2100
3681
|
);
|
|
2101
3682
|
})
|
|
2102
3683
|
);
|
|
2103
3684
|
}
|
|
2104
3685
|
function DockChips(props) {
|
|
2105
|
-
const [, force] =
|
|
2106
|
-
|
|
3686
|
+
const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
|
|
3687
|
+
import_react8.default.useEffect(() => subscribeFeatureState(() => force()), []);
|
|
2107
3688
|
const items = [];
|
|
2108
3689
|
for (const f of allModules()) {
|
|
2109
3690
|
if (f.planned || !stateOf(f.id).enabled || !chipShown(f.id) || typeof f.Chip !== "function") continue;
|
|
2110
|
-
items.push(
|
|
3691
|
+
items.push(import_react8.default.createElement(f.Chip, {
|
|
2111
3692
|
key: f.id,
|
|
2112
3693
|
ctx: props.ctx,
|
|
2113
3694
|
feature: f,
|
|
@@ -2117,7 +3698,23 @@ function DockChips(props) {
|
|
|
2117
3698
|
}));
|
|
2118
3699
|
}
|
|
2119
3700
|
if (items.length === 0) return null;
|
|
2120
|
-
return
|
|
3701
|
+
return import_react8.default.createElement("div", { className: "dockchip-row" }, items);
|
|
3702
|
+
}
|
|
3703
|
+
function FeatureOverlays() {
|
|
3704
|
+
const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
|
|
3705
|
+
useExternalVersion();
|
|
3706
|
+
import_react8.default.useEffect(() => subscribeFeatureState(() => force()), []);
|
|
3707
|
+
const items = [];
|
|
3708
|
+
for (const f of allModules()) {
|
|
3709
|
+
if (f.planned || !stateOf(f.id).enabled || typeof f.Overlay !== "function") continue;
|
|
3710
|
+
items.push(import_react8.default.createElement(
|
|
3711
|
+
FeatureBoundary,
|
|
3712
|
+
{ key: f.id },
|
|
3713
|
+
import_react8.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
|
|
3714
|
+
));
|
|
3715
|
+
}
|
|
3716
|
+
if (items.length === 0) return null;
|
|
3717
|
+
return import_react8.default.createElement(import_react8.default.Fragment, null, items);
|
|
2121
3718
|
}
|
|
2122
3719
|
var ctxRef = { current: null };
|
|
2123
3720
|
function apply(ctx) {
|
|
@@ -2128,19 +3725,23 @@ function apply(ctx) {
|
|
|
2128
3725
|
if (slots === void 0) return;
|
|
2129
3726
|
slots.inject("sidebar.footer.action", () => slots.register(
|
|
2130
3727
|
{ name: "sidebar.footer.action", id: "dsh-dock", order: 1, label: "\u529F\u80FD\u575E" },
|
|
2131
|
-
(props) =>
|
|
3728
|
+
(props) => import_react8.default.createElement(DockEntry, props)
|
|
2132
3729
|
));
|
|
2133
3730
|
slots.inject("shell.overlay", () => slots.register(
|
|
2134
3731
|
{ name: "shell.overlay", id: "dsh-dock-panel", order: 21, label: "\u529F\u80FD\u575E\u9762\u677F" },
|
|
2135
|
-
() =>
|
|
3732
|
+
() => import_react8.default.createElement(DockModal, null)
|
|
3733
|
+
));
|
|
3734
|
+
slots.inject("shell.overlay", () => slots.register(
|
|
3735
|
+
{ name: "shell.overlay", id: "dsh-dock-feature-overlays", order: 22, label: "\u529F\u80FD\u575E\u5168\u5C40\u6D6E\u5C42" },
|
|
3736
|
+
() => import_react8.default.createElement(FeatureOverlays, null)
|
|
2136
3737
|
));
|
|
2137
3738
|
slots.inject("settings.section", () => slots.register(
|
|
2138
3739
|
{ name: "settings.section", id: "dsh-dock", order: 90, label: "\u529F\u80FD\u575E" },
|
|
2139
|
-
() =>
|
|
3740
|
+
() => import_react8.default.createElement(DockPanel, null)
|
|
2140
3741
|
));
|
|
2141
3742
|
slots.inject("conversation.input.left", () => slots.register(
|
|
2142
3743
|
{ name: "conversation.input.left", id: "dsh-dock-chips", order: 10, label: "\u529F\u80FD\u575E" },
|
|
2143
|
-
(zone) =>
|
|
3744
|
+
(zone) => import_react8.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
|
|
2144
3745
|
));
|
|
2145
3746
|
}
|
|
2146
3747
|
var inject = ["timer"];
|