@cychien/ezdesign 0.9.2 → 0.11.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 +209 -550
- package/dist/cli.mjs +2640 -655
- package/dist/constants.d.ts +8 -4
- package/dist/extension/g/0.11.0-75c3fbebc3/dialog.js +1 -0
- package/dist/extension/g/0.11.0-75c3fbebc3/media.js +1 -0
- package/dist/extension/g/0.11.0-75c3fbebc3/page.js +44 -0
- package/dist/extension/g/0.11.0-75c3fbebc3/worker.js +57 -0
- package/dist/extension/manifest.json +15 -12
- package/dist/home.css +4706 -0
- package/dist/home.js +440 -0
- package/dist/native-host.mjs +33804 -115
- package/dist/overlay.css +5 -1
- package/dist/overlay.js +73 -22
- package/dist/shell.css +297 -1
- package/dist/shell.js +1230 -358
- package/dist/video-digest.js +16388 -0
- package/dist/vite.mjs +5 -1
- package/package.json +4 -3
- package/skills/ezdesign/SKILL.md +7 -3
- package/skills/ezdesign/reference/start.md +2 -1
- package/dist/extension/g/0.9.2-d9aee83dae/dialog.js +0 -1
- package/dist/extension/g/0.9.2-d9aee83dae/media.js +0 -1
- package/dist/extension/g/0.9.2-d9aee83dae/page.js +0 -39
- package/dist/extension/g/0.9.2-d9aee83dae/worker.js +0 -57
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/dialog.css +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/dialog.html +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-128.png +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-16.png +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-32.png +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/icon-48.png +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/media.html +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/setup.css +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/setup.html +0 -0
- /package/dist/extension/g/{0.9.2-d9aee83dae → 0.11.0-75c3fbebc3}/setup.js +0 -0
package/dist/shell.js
CHANGED
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
["path", { d: "M18 6L6.00081 17.9992M17.9992 18L6 6.00085", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }]
|
|
10
10
|
];
|
|
11
11
|
|
|
12
|
+
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/SidebarLeftIcon.js
|
|
13
|
+
var SidebarLeftIcon = [
|
|
14
|
+
["path", { d: "M2 12C2 8.31087 2 6.4663 2.81382 5.15877C3.1149 4.67502 3.48891 4.25427 3.91891 3.91554C5.08116 3 6.72077 3 10 3H14C17.2792 3 18.9188 3 20.0811 3.91554C20.5111 4.25427 20.8851 4.67502 21.1862 5.15877C22 6.4663 22 8.31087 22 12C22 15.6891 22 17.5337 21.1862 18.8412C20.8851 19.325 20.5111 19.7457 20.0811 20.0845C18.9188 21 17.2792 21 14 21H10C6.72077 21 5.08116 21 3.91891 20.0845C3.48891 19.7457 3.1149 19.325 2.81382 18.8412C2 17.5337 2 15.6891 2 12Z", stroke: "currentColor", strokeWidth: "1.5", key: "0" }],
|
|
15
|
+
["path", { d: "M9.5 3L9.5 21", stroke: "currentColor", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }],
|
|
16
|
+
["path", { d: "M5 7H6M5 10H6", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "2" }]
|
|
17
|
+
];
|
|
18
|
+
|
|
12
19
|
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/AlignSelectionIcon.js
|
|
13
20
|
var AlignSelectionIcon = [
|
|
14
21
|
["path", { d: "M20 6V18M18 4H6M18 20H6M4 18V6", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
|
|
@@ -116,6 +123,14 @@
|
|
|
116
123
|
["path", { d: "M15.5 12H8.5M12 8.5V15.5", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "1" }]
|
|
117
124
|
];
|
|
118
125
|
|
|
126
|
+
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/Plug01Icon.js
|
|
127
|
+
var Plug01Icon = [
|
|
128
|
+
["path", { d: "M15.5 2V6M8.5 6V2", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
|
|
129
|
+
["path", { d: "M6.00446 7.61331C5.93719 6.74273 6.63957 6 7.53014 6H16.4699C17.3604 6 18.0628 6.74273 17.9955 7.61331L17.8117 9.99197C17.6796 11.7019 17.1011 13.3498 16.132 14.7773L15.5312 15.6622C14.9638 16.4979 14.0077 17 12.9838 17H11.0162C9.99228 17 9.03617 16.4979 8.46881 15.6622L7.86803 14.7773C6.89885 13.3498 6.32041 11.7019 6.18827 9.99197L6.00446 7.61331Z", stroke: "currentColor", strokeWidth: "1.5", key: "1" }],
|
|
130
|
+
["path", { d: "M12 17V22", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "2" }],
|
|
131
|
+
["path", { d: "M11 9H13", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "3" }]
|
|
132
|
+
];
|
|
133
|
+
|
|
119
134
|
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/BubbleChatIcon.js
|
|
120
135
|
var BubbleChatIcon = [
|
|
121
136
|
["path", { d: "M21.5 12C21.5 17.2467 17.2467 21.5 12 21.5C10.3719 21.5 8.8394 21.0904 7.5 20.3687C5.63177 19.362 4.37462 20.2979 3.26592 20.4658C3.09774 20.4913 2.93024 20.4302 2.80997 20.31C2.62741 20.1274 2.59266 19.8451 2.6935 19.6074C3.12865 18.5818 3.5282 16.6382 2.98341 15C2.6698 14.057 2.5 13.0483 2.5 12C2.5 6.75329 6.75329 2.5 12 2.5C17.2467 2.5 21.5 6.75329 21.5 12Z", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "0" }],
|
|
@@ -143,6 +158,12 @@
|
|
|
143
158
|
["path", { d: "M9.5 13.9995L12.8693 10.6301C13.2731 10.2263 13.8208 9.99945 14.3919 9.99945C15.0873 9.99945 15.7399 10.3353 16.1441 10.9011L20.5 16.9995", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", key: "3" }]
|
|
144
159
|
];
|
|
145
160
|
|
|
161
|
+
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/DollarSquareIcon.js
|
|
162
|
+
var DollarSquareIcon = [
|
|
163
|
+
["path", { d: "M2.5 12C2.5 7.77027 2.5 5.6554 3.69797 4.25276C3.86808 4.05358 4.05358 3.86808 4.25276 3.69797C5.6554 2.5 7.77027 2.5 12 2.5C16.2297 2.5 18.3446 2.5 19.7472 3.69797C19.9464 3.86808 20.1319 4.05358 20.302 4.25276C21.5 5.6554 21.5 7.77027 21.5 12C21.5 16.2297 21.5 18.3446 20.302 19.7472C20.1319 19.9464 19.9464 20.1319 19.7472 20.302C18.3446 21.5 16.2297 21.5 12 21.5C7.77027 21.5 5.6554 21.5 4.25276 20.302C4.05358 20.1319 3.86808 19.9464 3.69797 19.7472C2.5 18.3446 2.5 16.2297 2.5 12Z", stroke: "currentColor", strokeWidth: "1.5", key: "0" }],
|
|
164
|
+
["path", { d: "M14.7102 10.0611C14.6111 9.29844 13.7354 8.06622 12.1608 8.06619C10.3312 8.06616 9.56136 9.07946 9.40515 9.58611C9.16145 10.2638 9.21019 11.6571 11.3547 11.809C14.0354 11.999 15.1093 12.3154 14.9727 13.956C14.836 15.5965 13.3417 15.951 12.1608 15.9129C10.9798 15.875 9.04764 15.3325 8.97266 13.8733M11.9734 6.99805V8.06982M11.9734 15.9031V16.998", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.5", key: "1" }]
|
|
165
|
+
];
|
|
166
|
+
|
|
146
167
|
// src/acp-ask.ts
|
|
147
168
|
function answeredField(field, answered) {
|
|
148
169
|
return answered.has(field.key) || (field.kind === "select" || field.kind === "multiselect") && !!field.custom && answered.has(field.custom.key);
|
|
@@ -410,23 +431,53 @@
|
|
|
410
431
|
// src/client/slash.ts
|
|
411
432
|
var MAX_QUERY = 24;
|
|
412
433
|
var BREAK = /[\s ]/;
|
|
434
|
+
var PATH_CHAR = /[./\\:@#%&=?~+*_-]/;
|
|
435
|
+
function opensTrigger(prev) {
|
|
436
|
+
return BREAK.test(prev) || /[\p{P}\p{S}]/u.test(prev) && !PATH_CHAR.test(prev);
|
|
437
|
+
}
|
|
413
438
|
var menuCount = 0;
|
|
439
|
+
function menuPosition(at2, box, view, scale2) {
|
|
440
|
+
const margin = 8 * scale2;
|
|
441
|
+
const gap = 6 * scale2;
|
|
442
|
+
const left = Math.max(margin, Math.min(at2.left, view.width - box.width - margin));
|
|
443
|
+
const below = at2.bottom + gap;
|
|
444
|
+
const above = at2.top - box.height - gap;
|
|
445
|
+
const crowded = below + box.height > view.height - margin || at2.top > view.height * 0.6;
|
|
446
|
+
const top = crowded && above >= margin ? above : Math.min(below, view.height - box.height - margin);
|
|
447
|
+
return { left, top };
|
|
448
|
+
}
|
|
414
449
|
function detectSlash(before, trigger = "/") {
|
|
415
450
|
const start = before.lastIndexOf(trigger);
|
|
416
451
|
if (start === -1) return null;
|
|
417
452
|
const prev = start === 0 ? "" : before[start - 1];
|
|
418
|
-
if (prev && !
|
|
453
|
+
if (prev && !opensTrigger(prev)) return null;
|
|
419
454
|
const query = before.slice(start + 1);
|
|
420
455
|
if (query.length > MAX_QUERY || BREAK.test(query)) return null;
|
|
421
456
|
return { start, query };
|
|
422
457
|
}
|
|
458
|
+
var WORD_BREAK = /[^\p{L}\p{N}]/u;
|
|
459
|
+
function rank(command, q) {
|
|
460
|
+
const names = [command.id, command.label].map((term) => term.toLowerCase());
|
|
461
|
+
if (names.some((name) => name.startsWith(q))) return 0;
|
|
462
|
+
if (names.some((name) => startsWord(name, q))) return 1;
|
|
463
|
+
if ([...names, ...command.keywords.map((k) => k.toLowerCase())].some((term) => term.includes(q))) return 2;
|
|
464
|
+
return null;
|
|
465
|
+
}
|
|
466
|
+
function startsWord(text, q) {
|
|
467
|
+
let at2 = text.indexOf(q);
|
|
468
|
+
while (at2 !== -1) {
|
|
469
|
+
if (at2 === 0 || WORD_BREAK.test(text.charAt(at2 - 1))) return true;
|
|
470
|
+
at2 = text.indexOf(q, at2 + 1);
|
|
471
|
+
}
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
423
474
|
function filterCommands(commands, query) {
|
|
424
475
|
const available = commands.filter((c) => c.enabled?.() ?? true);
|
|
425
476
|
const q = query.trim().toLowerCase();
|
|
426
477
|
if (!q) return available;
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
);
|
|
478
|
+
const ranked = available.map((command) => ({ command, rank: rank(command, q) })).filter((r) => r.rank !== null).sort((a, b) => a.rank - b.rank).map((r) => r.command);
|
|
479
|
+
if (ranked.length > 0) return ranked;
|
|
480
|
+
return available.filter((c) => c.description && startsWord(c.description.toLowerCase(), q));
|
|
430
481
|
}
|
|
431
482
|
function attachSlashMenu(editable, {
|
|
432
483
|
mk,
|
|
@@ -466,11 +517,8 @@
|
|
|
466
517
|
const at2 = slashRect();
|
|
467
518
|
if (!at2) return;
|
|
468
519
|
const box = menu.getBoundingClientRect();
|
|
469
|
-
const
|
|
470
|
-
const
|
|
471
|
-
const above = at2.top - box.height - 6;
|
|
472
|
-
const crowded = below + box.height > view.innerHeight - 8 || at2.top > view.innerHeight * 0.6;
|
|
473
|
-
const top = crowded && above >= 8 ? above : Math.min(below, view.innerHeight - box.height - 8);
|
|
520
|
+
const scale2 = box.width / menu.offsetWidth || 1;
|
|
521
|
+
const { left, top } = menuPosition(at2, box, { width: view.innerWidth, height: view.innerHeight }, scale2);
|
|
474
522
|
menu.style.left = `${left}px`;
|
|
475
523
|
menu.style.top = `${top}px`;
|
|
476
524
|
}
|
|
@@ -626,8 +674,38 @@
|
|
|
626
674
|
return { close };
|
|
627
675
|
}
|
|
628
676
|
|
|
677
|
+
// src/library/policy.ts
|
|
678
|
+
var VIDEO_CAP_BYTES = 2e8;
|
|
679
|
+
var THUMBNAIL_LONG_SIDE = 400;
|
|
680
|
+
var TAG_MAX_LENGTH = 64;
|
|
681
|
+
function normalizeTag(raw) {
|
|
682
|
+
const name = raw.normalize("NFC").trim().replace(/\s+/g, " ");
|
|
683
|
+
if (name === "" || name.length > TAG_MAX_LENGTH || /[,,]/.test(name)) return null;
|
|
684
|
+
return lowercaseInitial(name);
|
|
685
|
+
}
|
|
686
|
+
function lowercaseInitial(name) {
|
|
687
|
+
const [first = "", second = ""] = name;
|
|
688
|
+
if (second !== second.toLowerCase()) return name;
|
|
689
|
+
return first.toLowerCase() + name.slice(first.length);
|
|
690
|
+
}
|
|
691
|
+
function tagKey(name) {
|
|
692
|
+
return name.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
693
|
+
}
|
|
694
|
+
function thumbnailSize(width, height) {
|
|
695
|
+
const scale2 = Math.min(1, THUMBNAIL_LONG_SIDE / Math.max(width, height));
|
|
696
|
+
return { width: Math.max(1, Math.round(width * scale2)), height: Math.max(1, Math.round(height * scale2)) };
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/attachment-policy.ts
|
|
700
|
+
var MAX_ATTACHMENT_BYTES = 8 * 1024 * 1024;
|
|
701
|
+
function isVideoMime(mime) {
|
|
702
|
+
return mime.startsWith("video/");
|
|
703
|
+
}
|
|
704
|
+
function attachmentByteLimit(mime) {
|
|
705
|
+
return isVideoMime(mime) ? VIDEO_CAP_BYTES : MAX_ATTACHMENT_BYTES;
|
|
706
|
+
}
|
|
707
|
+
|
|
629
708
|
// src/client/attach.ts
|
|
630
|
-
var MAX_BYTES = 8 * 1024 * 1024;
|
|
631
709
|
function directAttachments(api2) {
|
|
632
710
|
return {
|
|
633
711
|
async upload(file) {
|
|
@@ -799,8 +877,9 @@
|
|
|
799
877
|
placeCaretAfter(after);
|
|
800
878
|
}
|
|
801
879
|
function add(file) {
|
|
802
|
-
|
|
803
|
-
|
|
880
|
+
const limit = attachmentByteLimit(file.type);
|
|
881
|
+
if (file.size > limit) {
|
|
882
|
+
showError(`${file.name || "\u9019\u500B\u6A94\u6848"} \u8D85\u904E\u55AE\u6A94 ${Math.round(limit / 1e6)} MB \u4E0A\u9650`);
|
|
804
883
|
return;
|
|
805
884
|
}
|
|
806
885
|
const chip = fileChip(file.name || "\u8CBC\u4E0A\u7684\u5716\u7247");
|
|
@@ -986,6 +1065,16 @@
|
|
|
986
1065
|
refs: () => draftRefs(snapshot2()),
|
|
987
1066
|
pending: () => [...uploading].filter((c) => editable.contains(c)).length,
|
|
988
1067
|
pendingNames: () => draftPendingNames(snapshot2()),
|
|
1068
|
+
paintNotes(noteFor) {
|
|
1069
|
+
editable.querySelectorAll(`[${CHIP_ATTR}], [${PICK_ATTR}]`).forEach((chip) => {
|
|
1070
|
+
const ids = chip.hasAttribute(PICK_ATTR) ? parsePick(chip.getAttribute(PICK_ATTR)).map((f) => f.id) : [chip.getAttribute(CHIP_ATTR) ?? ""].filter(Boolean);
|
|
1071
|
+
const text = ids.length ? noteFor(ids) : null;
|
|
1072
|
+
let note2 = chip.querySelector(".ez-chip-note");
|
|
1073
|
+
if (!text) return note2?.remove();
|
|
1074
|
+
note2 ?? (note2 = chip.querySelector(".ez-chip-name").insertAdjacentElement("afterend", mk("span", "ez-chip-note")));
|
|
1075
|
+
note2.textContent = text;
|
|
1076
|
+
});
|
|
1077
|
+
},
|
|
989
1078
|
// Either menu, whichever is up - at most one can be, since a trigger only
|
|
990
1079
|
// counts at the start of the word being typed.
|
|
991
1080
|
closeSlash: () => slash.close() || skillMenu.close(),
|
|
@@ -1192,8 +1281,8 @@
|
|
|
1192
1281
|
guest: sender.kind
|
|
1193
1282
|
};
|
|
1194
1283
|
}),
|
|
1195
|
-
/** Mod+wheel, and from a canvas guest
|
|
1196
|
-
* stage or the board. `at` is in the guest's viewport. */
|
|
1284
|
+
/** Mod+wheel, and from a canvas guest any wheel while annotating or picking:
|
|
1285
|
+
* pan or zoom the stage or the board. `at` is in the guest's viewport. */
|
|
1197
1286
|
"ez:wheel": up(BOTH, (r) => {
|
|
1198
1287
|
const at2 = obj(r.at);
|
|
1199
1288
|
const x = at2 ? num(at2.x) : null;
|
|
@@ -1238,8 +1327,8 @@
|
|
|
1238
1327
|
case "upload": {
|
|
1239
1328
|
const name = str(op.name);
|
|
1240
1329
|
const mime = str(op.mime);
|
|
1241
|
-
if (name === null || mime === null || !(op.
|
|
1242
|
-
return { op: "upload", name, mime,
|
|
1330
|
+
if (name === null || mime === null || !(op.file instanceof Blob)) return null;
|
|
1331
|
+
return { op: "upload", name, mime, file: op.file };
|
|
1243
1332
|
}
|
|
1244
1333
|
case "discard-upload": {
|
|
1245
1334
|
const id = str(op.id);
|
|
@@ -1342,6 +1431,19 @@
|
|
|
1342
1431
|
var ZOOM_MAX = 4;
|
|
1343
1432
|
var MAX_FRAME_HTML = 512 * 1024;
|
|
1344
1433
|
var MAX_CANVAS_NAME = 60;
|
|
1434
|
+
var MAX_FRAME_TITLE = 80;
|
|
1435
|
+
var MIN_FRAME_SIZE = { width: 240, height: 240 };
|
|
1436
|
+
var MAX_FRAME_SIZE = { width: 3840, height: 12e3 };
|
|
1437
|
+
var MAX_IMAGE_BYTES = 20 * 1024 * 1024;
|
|
1438
|
+
var IMAGE_TYPES = {
|
|
1439
|
+
"image/png": "png",
|
|
1440
|
+
"image/jpeg": "jpg",
|
|
1441
|
+
"image/gif": "gif",
|
|
1442
|
+
"image/webp": "webp",
|
|
1443
|
+
"image/avif": "avif",
|
|
1444
|
+
"image/svg+xml": "svg"
|
|
1445
|
+
};
|
|
1446
|
+
var ASSET_SHAPE = new RegExp(`^[0-9a-f]{12}\\.(${Object.values(IMAGE_TYPES).join("|")})$`);
|
|
1345
1447
|
|
|
1346
1448
|
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/AiSketchIcon.js
|
|
1347
1449
|
var AiSketchIcon = [
|
|
@@ -1373,6 +1475,13 @@
|
|
|
1373
1475
|
const bottom = Math.max(...rects.map((r) => r.y + r.height));
|
|
1374
1476
|
return { x, y, width: right - x, height: bottom - y };
|
|
1375
1477
|
}
|
|
1478
|
+
function imageFrameSize(natural) {
|
|
1479
|
+
const scale2 = Math.min(1, MAX_FRAME_SIZE.width / natural.width, MAX_FRAME_SIZE.height / natural.height);
|
|
1480
|
+
return {
|
|
1481
|
+
width: Math.max(MIN_FRAME_SIZE.width, Math.round(natural.width * scale2)),
|
|
1482
|
+
height: Math.max(MIN_FRAME_SIZE.height, Math.round(natural.height * scale2))
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1376
1485
|
function freeAlongRow(from, size, existing, limit) {
|
|
1377
1486
|
let x = from.x;
|
|
1378
1487
|
for (; ; ) {
|
|
@@ -1425,12 +1534,26 @@
|
|
|
1425
1534
|
height: (stage2.height + 2 * margin) / camera.zoom
|
|
1426
1535
|
};
|
|
1427
1536
|
}
|
|
1537
|
+
function boxBetween(a, b) {
|
|
1538
|
+
return { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y), width: Math.abs(a.x - b.x), height: Math.abs(a.y - b.y) };
|
|
1539
|
+
}
|
|
1428
1540
|
function intersects(a, b) {
|
|
1429
1541
|
return !(a.x + a.width < b.x || b.x + b.width < a.x || a.y + a.height < b.y || b.y + b.height < a.y);
|
|
1430
1542
|
}
|
|
1431
1543
|
function worldTransform(camera) {
|
|
1432
1544
|
return `translate(${-camera.x * camera.zoom}px, ${-camera.y * camera.zoom}px) scale(${camera.zoom})`;
|
|
1433
1545
|
}
|
|
1546
|
+
var EDGE_ZONE = 24;
|
|
1547
|
+
var EDGE_SPEED = 1200;
|
|
1548
|
+
function edgePan(at2, from, stage2) {
|
|
1549
|
+
const axis = (p, start, length) => {
|
|
1550
|
+
const zone = Math.min(EDGE_ZONE, length / 4);
|
|
1551
|
+
if (p < zone && p < start) return -EDGE_SPEED * Math.min(1, (zone - p) / zone);
|
|
1552
|
+
if (p > length - zone && p > start) return EDGE_SPEED * Math.min(1, (p - (length - zone)) / zone);
|
|
1553
|
+
return 0;
|
|
1554
|
+
};
|
|
1555
|
+
return { x: axis(at2.x, from.x, stage2.width), y: axis(at2.y, from.y, stage2.height) };
|
|
1556
|
+
}
|
|
1434
1557
|
|
|
1435
1558
|
// src/client/canvas/guides.ts
|
|
1436
1559
|
var SNAP_PX = 6;
|
|
@@ -1497,6 +1620,23 @@
|
|
|
1497
1620
|
copies
|
|
1498
1621
|
};
|
|
1499
1622
|
}
|
|
1623
|
+
function planImages(images, center, mint) {
|
|
1624
|
+
const width = images.reduce((sum, image) => sum + image.size.width, 0) + GAP * (images.length - 1);
|
|
1625
|
+
let x = Math.round(center.x - width / 2);
|
|
1626
|
+
const inputs = images.map((image) => {
|
|
1627
|
+
const rect = { x, y: Math.round(center.y - image.size.height / 2), ...image.size };
|
|
1628
|
+
x += image.size.width + GAP;
|
|
1629
|
+
return { id: mint(), asset: image.asset, title: image.title, rect };
|
|
1630
|
+
});
|
|
1631
|
+
const added = inputs.map((input) => input.id);
|
|
1632
|
+
return {
|
|
1633
|
+
label: added.length > 1 ? `\u8CBC\u4E0A ${added.length} \u5F35\u5716\u7247` : "\u8CBC\u4E0A\u5716\u7247",
|
|
1634
|
+
apply: inputs.map((input) => ({ t: "image", input })),
|
|
1635
|
+
undo: [{ t: "remove", ids: added }],
|
|
1636
|
+
redo: [{ t: "restore", ids: added }],
|
|
1637
|
+
added
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1500
1640
|
function planRemove(ids) {
|
|
1501
1641
|
const list = [...ids];
|
|
1502
1642
|
return {
|
|
@@ -1515,6 +1655,7 @@
|
|
|
1515
1655
|
frames2.push({ ...source, id: edit.input.id, rect: { ...source.rect, ...edit.input.at } });
|
|
1516
1656
|
continue;
|
|
1517
1657
|
}
|
|
1658
|
+
if (edit.t === "image") continue;
|
|
1518
1659
|
for (const op of edit.ops) {
|
|
1519
1660
|
if (op.t === "move") {
|
|
1520
1661
|
const at2 = new Map(op.frames.map((f) => [f.id, f]));
|
|
@@ -1590,7 +1731,7 @@
|
|
|
1590
1731
|
var TEST_IDS = {
|
|
1591
1732
|
/** role=tablist */
|
|
1592
1733
|
tabs: "ez-tabs",
|
|
1593
|
-
/** role=tab,
|
|
1734
|
+
/** role=tab, while a dev server is attached or there is one to start */
|
|
1594
1735
|
appTab: "ez-tab-app",
|
|
1595
1736
|
/** role=tab, `data-canvas-id` */
|
|
1596
1737
|
canvasTab: "ez-tab-canvas",
|
|
@@ -1649,6 +1790,7 @@
|
|
|
1649
1790
|
var ZOOM_STEP = 1.25;
|
|
1650
1791
|
var WHEEL_ZOOM = 25e-4;
|
|
1651
1792
|
var DRAG_PX = 3;
|
|
1793
|
+
var MAX_PAN_STEP_S = 1 / 30;
|
|
1652
1794
|
function el(tag, className, text) {
|
|
1653
1795
|
const node = document.createElement(tag);
|
|
1654
1796
|
node.className = className;
|
|
@@ -1656,12 +1798,13 @@
|
|
|
1656
1798
|
return node;
|
|
1657
1799
|
}
|
|
1658
1800
|
var BoardView = class {
|
|
1659
|
-
constructor(canvas,
|
|
1801
|
+
constructor(canvas, host2) {
|
|
1660
1802
|
this.canvas = canvas;
|
|
1661
|
-
this.host =
|
|
1803
|
+
this.host = host2;
|
|
1662
1804
|
__publicField(this, "el");
|
|
1663
1805
|
__publicField(this, "world");
|
|
1664
1806
|
__publicField(this, "heads");
|
|
1807
|
+
__publicField(this, "marquee");
|
|
1665
1808
|
__publicField(this, "guides");
|
|
1666
1809
|
__publicField(this, "empty");
|
|
1667
1810
|
__publicField(this, "readout");
|
|
@@ -1685,6 +1828,8 @@
|
|
|
1685
1828
|
__publicField(this, "stage", { width: 0, height: 0 });
|
|
1686
1829
|
__publicField(this, "shown", false);
|
|
1687
1830
|
__publicField(this, "frameRequested", 0);
|
|
1831
|
+
__publicField(this, "edgePanRequested", 0);
|
|
1832
|
+
__publicField(this, "edgePanAt", 0);
|
|
1688
1833
|
__publicField(this, "settleTimer", 0);
|
|
1689
1834
|
__publicField(this, "saveTimer", 0);
|
|
1690
1835
|
/** The zoom the frames were last told, so a pan sends them nothing. */
|
|
@@ -1708,11 +1853,13 @@
|
|
|
1708
1853
|
this.guides = el("div", "ez-guides");
|
|
1709
1854
|
this.world.append(this.guides);
|
|
1710
1855
|
this.heads = el("div", "ez-board-heads");
|
|
1856
|
+
this.marquee = el("div", "ez-board-marquee");
|
|
1857
|
+
this.marquee.hidden = true;
|
|
1711
1858
|
this.empty = el("div", "ez-board-empty");
|
|
1712
1859
|
this.empty.append(icon(AiSketchIcon, 64));
|
|
1713
1860
|
const tools = el("div", "ez-board-tools");
|
|
1714
1861
|
tools.dataset.testid = TEST_IDS.tools;
|
|
1715
|
-
const
|
|
1862
|
+
const button2 = (label, glyph, run) => {
|
|
1716
1863
|
const b = el("button", "ez-board-tool");
|
|
1717
1864
|
b.append(icon(glyph, 14));
|
|
1718
1865
|
b.setAttribute("aria-label", label);
|
|
@@ -1725,11 +1872,11 @@
|
|
|
1725
1872
|
this.readout.setAttribute("role", "status");
|
|
1726
1873
|
this.readout.setAttribute("aria-label", LABELS.zoomLevel);
|
|
1727
1874
|
tools.append(
|
|
1728
|
-
|
|
1875
|
+
button2(LABELS.zoomOut, MinusIcon, () => this.zoomBy(1 / ZOOM_STEP)),
|
|
1729
1876
|
this.readout,
|
|
1730
|
-
|
|
1877
|
+
button2(LABELS.zoomIn, PlusIcon, () => this.zoomBy(ZOOM_STEP))
|
|
1731
1878
|
);
|
|
1732
|
-
this.el.append(this.world, this.heads, this.empty, tools);
|
|
1879
|
+
this.el.append(this.world, this.heads, this.marquee, this.empty, tools);
|
|
1733
1880
|
this.el.addEventListener("wheel", (e) => this.onBoardWheel(e), { passive: false });
|
|
1734
1881
|
this.el.addEventListener("pointerdown", (e) => this.onPointerDown(e));
|
|
1735
1882
|
this.el.addEventListener("pointermove", (e) => this.onPointerMove(e));
|
|
@@ -1818,6 +1965,7 @@
|
|
|
1818
1965
|
window.clearTimeout(this.settleTimer);
|
|
1819
1966
|
window.clearTimeout(this.saveTimer);
|
|
1820
1967
|
cancelAnimationFrame(this.frameRequested);
|
|
1968
|
+
cancelAnimationFrame(this.edgePanRequested);
|
|
1821
1969
|
this.el.remove();
|
|
1822
1970
|
}
|
|
1823
1971
|
/** E/R on: frames take the pointer so the overlay annotates; off: the board
|
|
@@ -1969,6 +2117,23 @@
|
|
|
1969
2117
|
this.commit(step2);
|
|
1970
2118
|
this.select(new Set(step2.copies));
|
|
1971
2119
|
}
|
|
2120
|
+
/** Pasted images, each at its natural size, in a row centred on the view and
|
|
2121
|
+
* selected, as a paste lands in Figma. */
|
|
2122
|
+
async pasteImages(files) {
|
|
2123
|
+
const stored = await Promise.all(
|
|
2124
|
+
files.map(async (file) => {
|
|
2125
|
+
const natural = await naturalSize(file);
|
|
2126
|
+
const asset = natural && await this.host.storeImage(file);
|
|
2127
|
+
return natural && asset ? { asset, title: imageTitle(file), size: imageFrameSize(natural) } : null;
|
|
2128
|
+
})
|
|
2129
|
+
);
|
|
2130
|
+
const images = stored.filter((image) => image !== null);
|
|
2131
|
+
if (!images.length || !this.camera) return;
|
|
2132
|
+
const center = screenToWorld(this.camera, { x: this.stage.width / 2, y: this.stage.height / 2 });
|
|
2133
|
+
const step2 = planImages(images, center, () => mintFrameId((b) => crypto.getRandomValues(b)));
|
|
2134
|
+
this.commit(step2);
|
|
2135
|
+
this.select(new Set(step2.added));
|
|
2136
|
+
}
|
|
1972
2137
|
select(ids) {
|
|
1973
2138
|
this.selection = ids;
|
|
1974
2139
|
this.paintSelection();
|
|
@@ -2156,11 +2321,13 @@
|
|
|
2156
2321
|
} else {
|
|
2157
2322
|
this.setCamera(panned(this.camera, -e.deltaX * unit, -e.deltaY * unit));
|
|
2158
2323
|
}
|
|
2324
|
+
if (this.gesture?.t === "move" && this.gesture.started) this.dragTo(this.gesture);
|
|
2325
|
+
if (this.gesture?.t === "marquee" && this.gesture.started) this.paintMarquee(this.gesture);
|
|
2159
2326
|
}
|
|
2160
|
-
/**
|
|
2161
|
-
* selects and drags it. */
|
|
2327
|
+
/** Space held or the middle button pans; the background draws a selection
|
|
2328
|
+
* box; a frame's head or body selects and drags it. */
|
|
2162
2329
|
onPointerDown(e) {
|
|
2163
|
-
if (e.button !== 0 || !this.camera || this.gesture) return;
|
|
2330
|
+
if (e.button !== 0 && e.button !== 1 || !this.camera || this.gesture) return;
|
|
2164
2331
|
const target2 = e.target;
|
|
2165
2332
|
if (target2.closest(".ez-board-tools")) return;
|
|
2166
2333
|
this.following = false;
|
|
@@ -2170,7 +2337,7 @@
|
|
|
2170
2337
|
this.el.setPointerCapture(e.pointerId);
|
|
2171
2338
|
this.gesture = gesture;
|
|
2172
2339
|
};
|
|
2173
|
-
if (this.spaceHeld) {
|
|
2340
|
+
if (this.spaceHeld || e.button === 1) {
|
|
2174
2341
|
start({ t: "pan", pointer: e.pointerId, x: e.clientX, y: e.clientY, camera: this.camera });
|
|
2175
2342
|
this.el.classList.add("ez-panning");
|
|
2176
2343
|
return;
|
|
@@ -2192,36 +2359,76 @@
|
|
|
2192
2359
|
} else if (!this.selection.has(id)) {
|
|
2193
2360
|
this.select(/* @__PURE__ */ new Set([id]));
|
|
2194
2361
|
}
|
|
2195
|
-
|
|
2362
|
+
const from = this.boardPoint(e);
|
|
2363
|
+
start({
|
|
2364
|
+
t: "move",
|
|
2365
|
+
pointer: e.pointerId,
|
|
2366
|
+
x: e.clientX,
|
|
2367
|
+
y: e.clientY,
|
|
2368
|
+
from,
|
|
2369
|
+
at: from,
|
|
2370
|
+
camera: this.camera,
|
|
2371
|
+
ids: new Set(this.selection),
|
|
2372
|
+
started: false,
|
|
2373
|
+
dx: 0,
|
|
2374
|
+
dy: 0,
|
|
2375
|
+
toggleOnClick
|
|
2376
|
+
});
|
|
2196
2377
|
return;
|
|
2197
2378
|
}
|
|
2198
2379
|
if (!id) {
|
|
2199
2380
|
this.setLive(null);
|
|
2200
|
-
this.select(/* @__PURE__ */ new Set());
|
|
2381
|
+
if (!e.shiftKey) this.select(/* @__PURE__ */ new Set());
|
|
2201
2382
|
this.host.escape();
|
|
2202
|
-
|
|
2203
|
-
|
|
2383
|
+
const from = this.boardPoint(e);
|
|
2384
|
+
start({
|
|
2385
|
+
t: "marquee",
|
|
2386
|
+
pointer: e.pointerId,
|
|
2387
|
+
origin: screenToWorld(this.camera, from),
|
|
2388
|
+
from,
|
|
2389
|
+
at: from,
|
|
2390
|
+
base: new Set(this.selection),
|
|
2391
|
+
started: false
|
|
2392
|
+
});
|
|
2204
2393
|
}
|
|
2205
2394
|
}
|
|
2206
2395
|
onPointerMove(e) {
|
|
2207
2396
|
const g = this.gesture;
|
|
2208
2397
|
if (!g || e.pointerId !== g.pointer || !this.camera) return;
|
|
2209
|
-
const zoom = this.camera.zoom;
|
|
2210
2398
|
if (g.t === "pan") {
|
|
2211
2399
|
this.setCamera(panned(g.camera, e.clientX - g.x, e.clientY - g.y));
|
|
2212
2400
|
return;
|
|
2213
2401
|
}
|
|
2402
|
+
if (g.t === "marquee") {
|
|
2403
|
+
g.at = this.boardPoint(e);
|
|
2404
|
+
if (!g.started && Math.hypot(g.at.x - g.from.x, g.at.y - g.from.y) < DRAG_PX) return;
|
|
2405
|
+
g.started = true;
|
|
2406
|
+
this.paintMarquee(g);
|
|
2407
|
+
this.startEdgePan();
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2214
2410
|
if (!g.started) {
|
|
2215
2411
|
if (Math.hypot(e.clientX - g.x, e.clientY - g.y) < DRAG_PX) return;
|
|
2216
2412
|
g.started = true;
|
|
2217
2413
|
this.el.classList.add("ez-arranging");
|
|
2218
2414
|
}
|
|
2415
|
+
g.at = { x: g.from.x + e.clientX - g.x, y: g.from.y + e.clientY - g.y };
|
|
2416
|
+
this.dragTo(g);
|
|
2417
|
+
this.startEdgePan();
|
|
2418
|
+
}
|
|
2419
|
+
/** The dragged frames under the pointer, wherever the camera has gone since
|
|
2420
|
+
* the press. */
|
|
2421
|
+
dragTo(g) {
|
|
2422
|
+
const camera = this.camera;
|
|
2423
|
+
if (!camera) return;
|
|
2219
2424
|
const moving = this.frames.filter((f) => g.ids.has(f.id));
|
|
2220
2425
|
const box = boundsOf(moving.map((f) => f.rect));
|
|
2221
2426
|
if (!box) return;
|
|
2222
|
-
const
|
|
2427
|
+
const grabbed = screenToWorld(g.camera, g.from);
|
|
2428
|
+
const pointer = screenToWorld(camera, g.at);
|
|
2429
|
+
const raw = { ...box, x: box.x + pointer.x - grabbed.x, y: box.y + pointer.y - grabbed.y };
|
|
2223
2430
|
const others = this.frames.filter((f) => !g.ids.has(f.id)).map((f) => f.rect);
|
|
2224
|
-
const snapped = snapMove(raw, others, zoom);
|
|
2431
|
+
const snapped = snapMove(raw, others, camera.zoom);
|
|
2225
2432
|
g.dx = Math.round(snapped.rect.x - box.x);
|
|
2226
2433
|
g.dy = Math.round(snapped.rect.y - box.y);
|
|
2227
2434
|
for (const f of moving) {
|
|
@@ -2230,12 +2437,48 @@
|
|
|
2230
2437
|
this.paintHeads();
|
|
2231
2438
|
this.paintGuides(snapped.guides);
|
|
2232
2439
|
}
|
|
2440
|
+
/** Selects every frame the box touches, on top of what a shift-press kept. */
|
|
2441
|
+
paintMarquee(g) {
|
|
2442
|
+
const camera = this.camera;
|
|
2443
|
+
if (!camera) return;
|
|
2444
|
+
const box = boxBetween(g.origin, screenToWorld(camera, g.at));
|
|
2445
|
+
const hits = this.frames.filter((f) => intersects(box, f.rect)).map((f) => f.id);
|
|
2446
|
+
this.select(/* @__PURE__ */ new Set([...g.base, ...hits]));
|
|
2447
|
+
const screen = boxBetween(worldToScreen(camera, g.origin), g.at);
|
|
2448
|
+
this.marquee.style.transform = `translate(${screen.x}px, ${screen.y}px)`;
|
|
2449
|
+
this.marquee.style.width = `${screen.width}px`;
|
|
2450
|
+
this.marquee.style.height = `${screen.height}px`;
|
|
2451
|
+
this.marquee.hidden = false;
|
|
2452
|
+
}
|
|
2453
|
+
startEdgePan() {
|
|
2454
|
+
if (this.edgePanRequested) return;
|
|
2455
|
+
this.edgePanAt = performance.now();
|
|
2456
|
+
this.edgePanRequested = requestAnimationFrame((now) => this.edgePanStep(now));
|
|
2457
|
+
}
|
|
2458
|
+
/** One frame of a drag held at the edge: pan, then carry the frames along.
|
|
2459
|
+
* Stops by itself once the pointer leaves the edge or the drag ends. */
|
|
2460
|
+
edgePanStep(now) {
|
|
2461
|
+
this.edgePanRequested = 0;
|
|
2462
|
+
const g = this.gesture;
|
|
2463
|
+
if (!g || g.t === "pan" || !g.started || !this.camera) return;
|
|
2464
|
+
const speed = edgePan(g.at, g.from, this.stage);
|
|
2465
|
+
if (!speed.x && !speed.y) return;
|
|
2466
|
+
const dt = Math.min(MAX_PAN_STEP_S, Math.max(0, now - this.edgePanAt) / 1e3);
|
|
2467
|
+
this.edgePanAt = now;
|
|
2468
|
+
this.setCamera(panned(this.camera, -speed.x * dt, -speed.y * dt));
|
|
2469
|
+
if (g.t === "move") this.dragTo(g);
|
|
2470
|
+
else this.paintMarquee(g);
|
|
2471
|
+
this.edgePanRequested = requestAnimationFrame((next) => this.edgePanStep(next));
|
|
2472
|
+
}
|
|
2233
2473
|
onPointerUp(e, cancelled = false) {
|
|
2234
2474
|
const g = this.gesture;
|
|
2235
2475
|
if (!g || e.pointerId !== g.pointer) return;
|
|
2236
2476
|
this.gesture = null;
|
|
2477
|
+
cancelAnimationFrame(this.edgePanRequested);
|
|
2478
|
+
this.edgePanRequested = 0;
|
|
2237
2479
|
this.el.classList.remove("ez-panning", "ez-arranging");
|
|
2238
2480
|
this.paintGuides([]);
|
|
2481
|
+
this.marquee.hidden = true;
|
|
2239
2482
|
if (g.t !== "move") return;
|
|
2240
2483
|
if (!g.started) {
|
|
2241
2484
|
if (g.toggleOnClick) this.select(new Set([...this.selection].filter((id) => id !== g.toggleOnClick)));
|
|
@@ -2255,6 +2498,29 @@
|
|
|
2255
2498
|
if (id && this.cards.get(id)?.iframe) this.setLive(id);
|
|
2256
2499
|
}
|
|
2257
2500
|
};
|
|
2501
|
+
async function naturalSize(image) {
|
|
2502
|
+
const bitmap = await createImageBitmap(image).catch(() => null);
|
|
2503
|
+
if (bitmap) {
|
|
2504
|
+
const size = { width: bitmap.width, height: bitmap.height };
|
|
2505
|
+
bitmap.close();
|
|
2506
|
+
return size;
|
|
2507
|
+
}
|
|
2508
|
+
const url = URL.createObjectURL(image);
|
|
2509
|
+
try {
|
|
2510
|
+
const img = new Image();
|
|
2511
|
+
img.src = url;
|
|
2512
|
+
await img.decode();
|
|
2513
|
+
return img.naturalWidth && img.naturalHeight ? { width: img.naturalWidth, height: img.naturalHeight } : null;
|
|
2514
|
+
} catch {
|
|
2515
|
+
return null;
|
|
2516
|
+
} finally {
|
|
2517
|
+
URL.revokeObjectURL(url);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
function imageTitle(file) {
|
|
2521
|
+
const stem = file.name.replace(/\.[^.]*$/, "").trim();
|
|
2522
|
+
return [...stem || "\u5716\u7247"].slice(0, MAX_FRAME_TITLE).join("");
|
|
2523
|
+
}
|
|
2258
2524
|
|
|
2259
2525
|
// src/client/confirm-dialog.ts
|
|
2260
2526
|
function confirmDialog(offer) {
|
|
@@ -2324,10 +2590,10 @@
|
|
|
2324
2590
|
];
|
|
2325
2591
|
|
|
2326
2592
|
// src/client/canvas/tabs.ts
|
|
2327
|
-
function tabsModel(
|
|
2593
|
+
function tabsModel(appTab, canvas) {
|
|
2328
2594
|
const open = canvas.canvases.filter((c) => !c.archived).sort((a, b) => a.createdAt - b.createdAt);
|
|
2329
2595
|
const tabs = [
|
|
2330
|
-
...
|
|
2596
|
+
...appTab ? [{ id: "app", label: LABELS.appTab, closable: false }] : [],
|
|
2331
2597
|
...open.map((c) => ({ id: c.id, label: LABELS.canvasTab(c.name), closable: true }))
|
|
2332
2598
|
];
|
|
2333
2599
|
const active = tabs.some((t) => t.id === canvas.activeTab) ? canvas.activeTab : tabs[0]?.id ?? null;
|
|
@@ -2549,6 +2815,9 @@
|
|
|
2549
2815
|
};
|
|
2550
2816
|
|
|
2551
2817
|
// src/client/canvas/index.ts
|
|
2818
|
+
function returnKeysToShell(board, frame) {
|
|
2819
|
+
if (document.activeElement === frame) board.el.focus({ preventScroll: true });
|
|
2820
|
+
}
|
|
2552
2821
|
async function canvasRequest(api2, request) {
|
|
2553
2822
|
const [method, path, body] = (() => {
|
|
2554
2823
|
switch (request.do) {
|
|
@@ -2568,11 +2837,18 @@
|
|
|
2568
2837
|
return ["POST", `/canvases/${request.canvasId}/ops`, request.step];
|
|
2569
2838
|
case "duplicate":
|
|
2570
2839
|
return ["POST", `/canvases/${request.canvasId}/frames`, request.input];
|
|
2840
|
+
case "asset":
|
|
2841
|
+
return ["POST", `/canvases/${request.canvasId}/assets`, request.image];
|
|
2842
|
+
case "image-frame":
|
|
2843
|
+
return ["POST", `/canvases/${request.canvasId}/image-frames`, request.input];
|
|
2571
2844
|
case "view":
|
|
2572
2845
|
return ["PUT", "/view", request.view];
|
|
2573
2846
|
}
|
|
2574
2847
|
})();
|
|
2575
|
-
const res = await api2(
|
|
2848
|
+
const res = await api2(
|
|
2849
|
+
path,
|
|
2850
|
+
body instanceof Blob ? { method, headers: { "content-type": body.type }, body } : { method, ...body !== void 0 ? { body: JSON.stringify(body) } : {} }
|
|
2851
|
+
);
|
|
2576
2852
|
const answer2 = await res.json().catch(() => null);
|
|
2577
2853
|
if (!res.ok) throw new Error(answer2?.error ?? `HTTP ${res.status}`);
|
|
2578
2854
|
return answer2;
|
|
@@ -2585,7 +2861,7 @@
|
|
|
2585
2861
|
return api2("/attachments", {
|
|
2586
2862
|
method: "POST",
|
|
2587
2863
|
headers: { "content-type": op.mime, "x-ez-name": encodeURIComponent(op.name) },
|
|
2588
|
-
body: op.
|
|
2864
|
+
body: op.file
|
|
2589
2865
|
});
|
|
2590
2866
|
case "discard-upload":
|
|
2591
2867
|
return api2(`/attachments/${encodeURIComponent(op.id)}`, { method: "DELETE" });
|
|
@@ -2616,6 +2892,7 @@
|
|
|
2616
2892
|
if (sure) await request({ do: "delete", canvasId: id });
|
|
2617
2893
|
}
|
|
2618
2894
|
});
|
|
2895
|
+
if (ports.tabsLead) strip2.el.prepend(ports.tabsLead);
|
|
2619
2896
|
ports.stageWrap.prepend(strip2.el);
|
|
2620
2897
|
async function request(r) {
|
|
2621
2898
|
try {
|
|
@@ -2633,8 +2910,9 @@
|
|
|
2633
2910
|
const made = new BoardView(doc, {
|
|
2634
2911
|
guests: ports.guests,
|
|
2635
2912
|
send: async (edit) => await request(
|
|
2636
|
-
edit.t === "ops" ? { do: "ops", canvasId: id, step: { opId: newOpId(), ops: edit.ops } } : { do: "duplicate", canvasId: id, input: edit.input }
|
|
2913
|
+
edit.t === "ops" ? { do: "ops", canvasId: id, step: { opId: newOpId(), ops: edit.ops } } : edit.t === "duplicate" ? { do: "duplicate", canvasId: id, input: edit.input } : { do: "image-frame", canvasId: id, input: edit.input }
|
|
2637
2914
|
),
|
|
2915
|
+
storeImage: async (image) => (await request({ do: "asset", canvasId: id, image }))?.asset ?? null,
|
|
2638
2916
|
saveCamera: (camera) => void request({ do: "view", view: { camera: { canvasId: id, camera } } }),
|
|
2639
2917
|
escape: ports.escape,
|
|
2640
2918
|
chooseFrame: (frame) => ports.chooseFrame({
|
|
@@ -2663,6 +2941,7 @@
|
|
|
2663
2941
|
shown = tab;
|
|
2664
2942
|
for (const [id, b] of boards) if (id !== tab) b.hide();
|
|
2665
2943
|
ports.stage.hidden = tab !== "app";
|
|
2944
|
+
document.documentElement.classList.toggle("ez-on-board", next !== null);
|
|
2666
2945
|
ports.onTabShown(tab);
|
|
2667
2946
|
if (next) {
|
|
2668
2947
|
next.show();
|
|
@@ -2677,11 +2956,24 @@
|
|
|
2677
2956
|
}
|
|
2678
2957
|
function paintStrip2() {
|
|
2679
2958
|
if (!snapshot2?.canvas) return;
|
|
2680
|
-
strip2.paint(tabsModel(snapshot2.
|
|
2959
|
+
strip2.paint(tabsModel(snapshot2.appTab, snapshot2.canvas));
|
|
2681
2960
|
}
|
|
2682
2961
|
function activeBoard() {
|
|
2683
2962
|
return shown && shown !== "app" ? boards.get(shown) ?? null : null;
|
|
2684
2963
|
}
|
|
2964
|
+
function focusedBoard() {
|
|
2965
|
+
const board2 = activeBoard();
|
|
2966
|
+
const focus = document.activeElement;
|
|
2967
|
+
return board2 && (!focus || focus === document.body || board2.el.contains(focus)) ? board2 : null;
|
|
2968
|
+
}
|
|
2969
|
+
document.addEventListener("paste", (e) => {
|
|
2970
|
+
const board2 = focusedBoard();
|
|
2971
|
+
if (!board2 || e.defaultPrevented || document.querySelector("dialog[open]")) return;
|
|
2972
|
+
const images = [...e.clipboardData?.files ?? []].filter((f) => f.type in IMAGE_TYPES);
|
|
2973
|
+
if (!images.length) return;
|
|
2974
|
+
e.preventDefault();
|
|
2975
|
+
void board2.pasteImages(images);
|
|
2976
|
+
});
|
|
2685
2977
|
function pushAnnotations(s) {
|
|
2686
2978
|
const byGuest = /* @__PURE__ */ new Map();
|
|
2687
2979
|
s.annotations.forEach((a, i) => {
|
|
@@ -2704,7 +2996,7 @@
|
|
|
2704
2996
|
render(s) {
|
|
2705
2997
|
snapshot2 = s;
|
|
2706
2998
|
if (!s.canvas) return;
|
|
2707
|
-
const model = tabsModel(s.
|
|
2999
|
+
const model = tabsModel(s.appTab, s.canvas);
|
|
2708
3000
|
strip2.paint(model);
|
|
2709
3001
|
for (const [id, b] of boards) {
|
|
2710
3002
|
const summary = s.canvas.canvases.find((c) => c.id === id);
|
|
@@ -2749,15 +3041,15 @@
|
|
|
2749
3041
|
if (b) ports.guests.post(guest.id, { type: "ez:viewport", ...b.viewportFor(), scoped: false });
|
|
2750
3042
|
if (snapshot2) pushAnnotations(snapshot2);
|
|
2751
3043
|
return false;
|
|
3044
|
+
case "ez:popup":
|
|
3045
|
+
if (!message.open && b) returnKeysToShell(b, guest.iframe);
|
|
3046
|
+
return false;
|
|
2752
3047
|
default:
|
|
2753
3048
|
return false;
|
|
2754
3049
|
}
|
|
2755
3050
|
},
|
|
2756
3051
|
onKeyDown(e) {
|
|
2757
|
-
|
|
2758
|
-
const focus = document.activeElement;
|
|
2759
|
-
if (!board2 || focus && focus !== document.body && !board2.el.contains(focus)) return false;
|
|
2760
|
-
return board2.onKeyDown(e);
|
|
3052
|
+
return focusedBoard()?.onKeyDown(e) ?? false;
|
|
2761
3053
|
},
|
|
2762
3054
|
onKeyUp(e) {
|
|
2763
3055
|
activeBoard()?.onKeyUp(e);
|
|
@@ -2791,27 +3083,6 @@
|
|
|
2791
3083
|
};
|
|
2792
3084
|
}
|
|
2793
3085
|
|
|
2794
|
-
// src/library/policy.ts
|
|
2795
|
-
var THUMBNAIL_LONG_SIDE = 400;
|
|
2796
|
-
var TAG_MAX_LENGTH = 64;
|
|
2797
|
-
function normalizeTag(raw) {
|
|
2798
|
-
const name = raw.normalize("NFC").trim().replace(/\s+/g, " ");
|
|
2799
|
-
if (name === "" || name.length > TAG_MAX_LENGTH || /[,,]/.test(name)) return null;
|
|
2800
|
-
return lowercaseInitial(name);
|
|
2801
|
-
}
|
|
2802
|
-
function lowercaseInitial(name) {
|
|
2803
|
-
const [first = "", second = ""] = name;
|
|
2804
|
-
if (second !== second.toLowerCase()) return name;
|
|
2805
|
-
return first.toLowerCase() + name.slice(first.length);
|
|
2806
|
-
}
|
|
2807
|
-
function tagKey(name) {
|
|
2808
|
-
return name.normalize("NFKC").trim().replace(/\s+/g, " ").toLowerCase();
|
|
2809
|
-
}
|
|
2810
|
-
function thumbnailSize(width, height) {
|
|
2811
|
-
const scale2 = Math.min(1, THUMBNAIL_LONG_SIDE / Math.max(width, height));
|
|
2812
|
-
return { width: Math.max(1, Math.round(width * scale2)), height: Math.max(1, Math.round(height * scale2)) };
|
|
2813
|
-
}
|
|
2814
|
-
|
|
2815
3086
|
// src/client/thumbnail.ts
|
|
2816
3087
|
var THUMBNAIL_TYPE = "image/webp";
|
|
2817
3088
|
var THUMBNAIL_QUALITY = 0.8;
|
|
@@ -2973,11 +3244,11 @@
|
|
|
2973
3244
|
}
|
|
2974
3245
|
function card(item, index) {
|
|
2975
3246
|
const li = h2("li");
|
|
2976
|
-
const
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
3247
|
+
const button2 = h2("button", "ez-library-card");
|
|
3248
|
+
button2.type = "button";
|
|
3249
|
+
button2.dataset.testid = LIBRARY_TEST_IDS.card;
|
|
3250
|
+
button2.dataset.itemId = item.id;
|
|
3251
|
+
button2.setAttribute("aria-label", cardLabel(item));
|
|
2981
3252
|
const media = h2("span", "ez-library-card-media");
|
|
2982
3253
|
if (item.thumbnail) {
|
|
2983
3254
|
const img = h2("img");
|
|
@@ -2995,10 +3266,10 @@
|
|
|
2995
3266
|
badge.append(h2("span", void 0, item.link ? "\u9023\u7D50" : "\u5F71\u7247"));
|
|
2996
3267
|
media.append(badge);
|
|
2997
3268
|
}
|
|
2998
|
-
|
|
2999
|
-
if (captions)
|
|
3000
|
-
decorate(
|
|
3001
|
-
li.append(
|
|
3269
|
+
button2.append(media);
|
|
3270
|
+
if (captions) button2.append(h2("span", "ez-library-card-caption", sourceName(item.source)));
|
|
3271
|
+
decorate(button2, item, index);
|
|
3272
|
+
li.append(button2);
|
|
3002
3273
|
return li;
|
|
3003
3274
|
}
|
|
3004
3275
|
function paintGrid() {
|
|
@@ -3181,12 +3452,12 @@
|
|
|
3181
3452
|
return el2;
|
|
3182
3453
|
}
|
|
3183
3454
|
function iconButton(className, label, glyph, size = 16) {
|
|
3184
|
-
const
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
return
|
|
3455
|
+
const button2 = h3("button", className);
|
|
3456
|
+
button2.type = "button";
|
|
3457
|
+
button2.setAttribute("aria-label", label);
|
|
3458
|
+
button2.title = label;
|
|
3459
|
+
button2.append(icon(glyph, size));
|
|
3460
|
+
return button2;
|
|
3190
3461
|
}
|
|
3191
3462
|
var dateFormat = new Intl.DateTimeFormat("zh-TW", { year: "numeric", month: "long", day: "numeric" });
|
|
3192
3463
|
function openDetail(options) {
|
|
@@ -3302,6 +3573,11 @@
|
|
|
3302
3573
|
video.playsInline = true;
|
|
3303
3574
|
video.preload = "metadata";
|
|
3304
3575
|
if (item.thumbnail) video.poster = item.thumbnail.url;
|
|
3576
|
+
if (item.dimensions) {
|
|
3577
|
+
const { width, height } = item.dimensions;
|
|
3578
|
+
video.style.aspectRatio = `${width} / ${height}`;
|
|
3579
|
+
video.style.width = `min(100cqw, ${width}px, calc(100cqh * ${width / height}))`;
|
|
3580
|
+
}
|
|
3305
3581
|
media = video;
|
|
3306
3582
|
} else if (original || item.thumbnail) {
|
|
3307
3583
|
const img = h3("img", "ez-library-detail-media");
|
|
@@ -3545,20 +3821,20 @@
|
|
|
3545
3821
|
function copyField(value, label) {
|
|
3546
3822
|
const row = h4("div", "ez-install-copy");
|
|
3547
3823
|
const code = h4("code", void 0, value);
|
|
3548
|
-
const
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3824
|
+
const button2 = h4("button", "ez-install-copy-button");
|
|
3825
|
+
button2.type = "button";
|
|
3826
|
+
button2.setAttribute("aria-label", label);
|
|
3827
|
+
button2.title = label;
|
|
3828
|
+
button2.append(icon(Copy01Icon, 14));
|
|
3553
3829
|
let timer;
|
|
3554
|
-
|
|
3830
|
+
button2.onclick = () => {
|
|
3555
3831
|
void navigator.clipboard.writeText(value).then(() => {
|
|
3556
3832
|
clearTimeout(timer);
|
|
3557
|
-
|
|
3558
|
-
timer = setTimeout(() =>
|
|
3833
|
+
button2.replaceChildren(icon(Tick02Icon, 14));
|
|
3834
|
+
timer = setTimeout(() => button2.replaceChildren(icon(Copy01Icon, 14)), COPIED_MS);
|
|
3559
3835
|
});
|
|
3560
3836
|
};
|
|
3561
|
-
row.append(code,
|
|
3837
|
+
row.append(code, button2);
|
|
3562
3838
|
return row;
|
|
3563
3839
|
}
|
|
3564
3840
|
var PROBLEMS = {
|
|
@@ -3728,8 +4004,8 @@
|
|
|
3728
4004
|
const title = h5("h1", "ez-library-title", "\u7D20\u6750\u5EAB");
|
|
3729
4005
|
const browser = libraryBrowser(api2, {
|
|
3730
4006
|
scroll,
|
|
3731
|
-
decorate: (
|
|
3732
|
-
|
|
4007
|
+
decorate: (button2, _item, index) => {
|
|
4008
|
+
button2.onclick = () => showDetail(index);
|
|
3733
4009
|
},
|
|
3734
4010
|
blank: () => {
|
|
3735
4011
|
const install = h5("button", "ez-library-empty-link", "\u5B89\u88DD ezdesign \u63D2\u4EF6");
|
|
@@ -3852,8 +4128,8 @@
|
|
|
3852
4128
|
let painted = false;
|
|
3853
4129
|
let open = false;
|
|
3854
4130
|
const el2 = h6("div", "ez-account");
|
|
3855
|
-
const
|
|
3856
|
-
|
|
4131
|
+
const button2 = h6("button", "ez-activity-btn ez-account-btn");
|
|
4132
|
+
button2.type = "button";
|
|
3857
4133
|
const menu = h6("div", "ez-menu ez-account-menu");
|
|
3858
4134
|
menu.setAttribute("role", "menu");
|
|
3859
4135
|
const who = h6("div", "ez-account-who");
|
|
@@ -3862,13 +4138,13 @@
|
|
|
3862
4138
|
signOut.setAttribute("role", "menuitem");
|
|
3863
4139
|
signOut.append(icon(Logout01Icon, 14), h6("span", "ez-menu-name", "\u767B\u51FA"));
|
|
3864
4140
|
menu.append(who, signOut);
|
|
3865
|
-
el2.append(
|
|
4141
|
+
el2.append(button2, menu);
|
|
3866
4142
|
const signIn = () => window.open(`${apiBase}/account/login`, "_blank");
|
|
3867
4143
|
function setOpen(next) {
|
|
3868
4144
|
open = next && !!email;
|
|
3869
4145
|
el2.toggleAttribute("data-open", open);
|
|
3870
|
-
if (email)
|
|
3871
|
-
else
|
|
4146
|
+
if (email) button2.setAttribute("aria-expanded", String(open));
|
|
4147
|
+
else button2.removeAttribute("aria-expanded");
|
|
3872
4148
|
}
|
|
3873
4149
|
function render2(account2) {
|
|
3874
4150
|
const nextEmail = account2?.email ?? null;
|
|
@@ -3877,22 +4153,22 @@
|
|
|
3877
4153
|
offered = !!account2;
|
|
3878
4154
|
email = nextEmail;
|
|
3879
4155
|
el2.hidden = !offered;
|
|
3880
|
-
|
|
4156
|
+
button2.textContent = "";
|
|
3881
4157
|
if (email) {
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
4158
|
+
button2.setAttribute("aria-label", `\u5E33\u865F\uFF1A${email}`);
|
|
4159
|
+
button2.title = email;
|
|
4160
|
+
button2.setAttribute("aria-haspopup", "menu");
|
|
4161
|
+
button2.append(h6("span", "ez-avatar", email.charAt(0).toUpperCase()));
|
|
3886
4162
|
who.replaceChildren(h6("span", "ez-account-label", "\u5DF2\u767B\u5165"), h6("span", "ez-account-email", email));
|
|
3887
4163
|
} else {
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
4164
|
+
button2.setAttribute("aria-label", "\u767B\u5165 ezdesign");
|
|
4165
|
+
button2.title = "\u767B\u5165 ezdesign";
|
|
4166
|
+
button2.removeAttribute("aria-haspopup");
|
|
4167
|
+
button2.append(icon(UserCircleIcon, 18));
|
|
3892
4168
|
}
|
|
3893
4169
|
setOpen(false);
|
|
3894
4170
|
}
|
|
3895
|
-
|
|
4171
|
+
button2.onclick = () => {
|
|
3896
4172
|
if (email) setOpen(!open);
|
|
3897
4173
|
else signIn();
|
|
3898
4174
|
};
|
|
@@ -3906,7 +4182,7 @@
|
|
|
3906
4182
|
el2.addEventListener("keydown", (e) => {
|
|
3907
4183
|
if (e.key === "Escape" && open) {
|
|
3908
4184
|
setOpen(false);
|
|
3909
|
-
|
|
4185
|
+
button2.focus();
|
|
3910
4186
|
}
|
|
3911
4187
|
});
|
|
3912
4188
|
render2(void 0);
|
|
@@ -4045,16 +4321,16 @@
|
|
|
4045
4321
|
const browser = libraryBrowser(api2, {
|
|
4046
4322
|
scroll,
|
|
4047
4323
|
captions: false,
|
|
4048
|
-
decorate: (
|
|
4324
|
+
decorate: (button2, item) => {
|
|
4049
4325
|
const check = h8("span", "ez-library-card-check");
|
|
4050
4326
|
check.append(icon(Tick02Icon, 12));
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4327
|
+
button2.querySelector(".ez-library-card-media").append(check);
|
|
4328
|
+
button2.setAttribute("aria-pressed", String(chosen.includes(item.id)));
|
|
4329
|
+
button2.onclick = () => {
|
|
4054
4330
|
const at2 = chosen.indexOf(item.id);
|
|
4055
4331
|
if (at2 < 0) chosen.push(item.id);
|
|
4056
4332
|
else chosen.splice(at2, 1);
|
|
4057
|
-
|
|
4333
|
+
button2.setAttribute("aria-pressed", String(at2 < 0));
|
|
4058
4334
|
paintCount();
|
|
4059
4335
|
};
|
|
4060
4336
|
},
|
|
@@ -4113,6 +4389,485 @@
|
|
|
4113
4389
|
});
|
|
4114
4390
|
}
|
|
4115
4391
|
|
|
4392
|
+
// src/client/video-digest/runner.ts
|
|
4393
|
+
var IDLE_MS = 3e4;
|
|
4394
|
+
var STALL_MS = 2e4;
|
|
4395
|
+
var RETRY_MS = 1e4;
|
|
4396
|
+
function videoDigests(api2, workerUrl, onChange) {
|
|
4397
|
+
const fractions = /* @__PURE__ */ new Map();
|
|
4398
|
+
const queue = [];
|
|
4399
|
+
const resting = /* @__PURE__ */ new Set();
|
|
4400
|
+
let current = null;
|
|
4401
|
+
let worker = null;
|
|
4402
|
+
let stallTimer = 0;
|
|
4403
|
+
let idleTimer = 0;
|
|
4404
|
+
const spawn = () => {
|
|
4405
|
+
const w = new Worker(workerUrl);
|
|
4406
|
+
w.onmessage = (e) => handle(e.data);
|
|
4407
|
+
w.onerror = (e) => {
|
|
4408
|
+
e.preventDefault();
|
|
4409
|
+
crashed("the digest worker crashed");
|
|
4410
|
+
};
|
|
4411
|
+
return w;
|
|
4412
|
+
};
|
|
4413
|
+
const next = () => {
|
|
4414
|
+
if (current) return;
|
|
4415
|
+
const id = queue.shift();
|
|
4416
|
+
if (!id) {
|
|
4417
|
+
idleTimer = window.setTimeout(() => {
|
|
4418
|
+
worker?.terminate();
|
|
4419
|
+
worker = null;
|
|
4420
|
+
}, IDLE_MS);
|
|
4421
|
+
return;
|
|
4422
|
+
}
|
|
4423
|
+
clearTimeout(idleTimer);
|
|
4424
|
+
current = id;
|
|
4425
|
+
worker ?? (worker = spawn());
|
|
4426
|
+
worker.postMessage({ id, api: api2 });
|
|
4427
|
+
armStall();
|
|
4428
|
+
};
|
|
4429
|
+
const armStall = () => {
|
|
4430
|
+
clearTimeout(stallTimer);
|
|
4431
|
+
stallTimer = window.setTimeout(() => crashed("the digest stopped answering"), STALL_MS);
|
|
4432
|
+
};
|
|
4433
|
+
const finish = (id) => {
|
|
4434
|
+
clearTimeout(stallTimer);
|
|
4435
|
+
fractions.delete(id);
|
|
4436
|
+
current = null;
|
|
4437
|
+
next();
|
|
4438
|
+
onChange();
|
|
4439
|
+
};
|
|
4440
|
+
const handle = (event) => {
|
|
4441
|
+
if (event.id !== current) return;
|
|
4442
|
+
if (event.type === "progress") {
|
|
4443
|
+
fractions.set(event.id, event.fraction);
|
|
4444
|
+
armStall();
|
|
4445
|
+
onChange();
|
|
4446
|
+
return;
|
|
4447
|
+
}
|
|
4448
|
+
if (event.type === "error") {
|
|
4449
|
+
resting.add(event.id);
|
|
4450
|
+
window.setTimeout(() => resting.delete(event.id), RETRY_MS);
|
|
4451
|
+
}
|
|
4452
|
+
finish(event.id);
|
|
4453
|
+
};
|
|
4454
|
+
const crashed = (detail) => {
|
|
4455
|
+
worker?.terminate();
|
|
4456
|
+
worker = null;
|
|
4457
|
+
const id = current;
|
|
4458
|
+
if (!id) return;
|
|
4459
|
+
const body = { state: "failed", reason: "crashed", detail };
|
|
4460
|
+
void fetch(`${api2}/attachments/${id}/video`, {
|
|
4461
|
+
method: "PUT",
|
|
4462
|
+
headers: { "content-type": "application/json" },
|
|
4463
|
+
body: JSON.stringify(body)
|
|
4464
|
+
}).catch(() => {
|
|
4465
|
+
});
|
|
4466
|
+
finish(id);
|
|
4467
|
+
};
|
|
4468
|
+
return {
|
|
4469
|
+
observe(pending) {
|
|
4470
|
+
const listed = new Set(pending);
|
|
4471
|
+
for (const id of pending) {
|
|
4472
|
+
if (fractions.has(id) || resting.has(id)) continue;
|
|
4473
|
+
fractions.set(id, 0);
|
|
4474
|
+
queue.push(id);
|
|
4475
|
+
}
|
|
4476
|
+
for (const id of [...fractions.keys()]) {
|
|
4477
|
+
if (listed.has(id) || id === current) continue;
|
|
4478
|
+
fractions.delete(id);
|
|
4479
|
+
const at2 = queue.indexOf(id);
|
|
4480
|
+
if (at2 >= 0) queue.splice(at2, 1);
|
|
4481
|
+
}
|
|
4482
|
+
next();
|
|
4483
|
+
},
|
|
4484
|
+
progress: (id) => fractions.get(id) ?? 0
|
|
4485
|
+
};
|
|
4486
|
+
}
|
|
4487
|
+
|
|
4488
|
+
// node_modules/.pnpm/@hugeicons+core-free-icons@4.3.5/node_modules/@hugeicons/core-free-icons/dist/esm/StopIcon.js
|
|
4489
|
+
var StopIcon = [
|
|
4490
|
+
["path", { d: "M4 12C4 8.72077 4 7.08116 4.81382 5.91891C5.1149 5.48891 5.48891 5.1149 5.91891 4.81382C7.08116 4 8.72077 4 12 4C15.2792 4 16.9188 4 18.0811 4.81382C18.5111 5.1149 18.8851 5.48891 19.1862 5.91891C20 7.08116 20 8.72077 20 12C20 15.2792 20 16.9188 19.1862 18.0811C18.8851 18.5111 18.5111 18.8851 18.0811 19.1862C16.9188 20 15.2792 20 12 20C8.72077 20 7.08116 20 5.91891 19.1862C5.48891 18.8851 5.1149 18.5111 4.81382 18.0811C4 16.9188 4 15.2792 4 12Z", stroke: "currentColor", strokeWidth: "1.5", key: "0" }]
|
|
4491
|
+
];
|
|
4492
|
+
|
|
4493
|
+
// src/desktop-wire.ts
|
|
4494
|
+
var DESKTOP_BRIDGE = "ezdesignDesktop";
|
|
4495
|
+
|
|
4496
|
+
// src/client/host.ts
|
|
4497
|
+
var bridge = window[DESKTOP_BRIDGE];
|
|
4498
|
+
var host = bridge ? {
|
|
4499
|
+
kind: "desktop",
|
|
4500
|
+
showProject: (opened) => bridge.showProject(opened),
|
|
4501
|
+
pickFolder: () => bridge.pickFolder(),
|
|
4502
|
+
pathForFile: (file) => bridge.pathForFile(file),
|
|
4503
|
+
toggleSidebar: () => bridge.toggleSidebar(),
|
|
4504
|
+
onLayout: (listener) => bridge.onLayout(listener),
|
|
4505
|
+
onUpdate: (listener) => bridge.onUpdate?.(listener),
|
|
4506
|
+
takeUpdate: () => bridge.takeUpdate?.()
|
|
4507
|
+
} : { kind: "browser", showProject: (opened) => location.assign(opened.shellUrl) };
|
|
4508
|
+
if (bridge) {
|
|
4509
|
+
const root2 = document.documentElement;
|
|
4510
|
+
root2.dataset.host = "desktop";
|
|
4511
|
+
root2.style.setProperty("--sidebar-width", `${bridge.sidebarWidth}px`);
|
|
4512
|
+
root2.style.setProperty("--pane-inset", `${bridge.paneInset}px`);
|
|
4513
|
+
root2.style.setProperty("--pane-radius", `${bridge.paneRadius}px`);
|
|
4514
|
+
bridge.onLayout(({ sidebar: sidebar2 }) => {
|
|
4515
|
+
root2.dataset.sidebar = sidebar2 ? "open" : "closed";
|
|
4516
|
+
root2.style.setProperty("--traffic-light-room", sidebar2 ? "0px" : `${bridge.trafficLightRoom}px`);
|
|
4517
|
+
});
|
|
4518
|
+
}
|
|
4519
|
+
|
|
4520
|
+
// src/client/dev-server-panel.ts
|
|
4521
|
+
var DEV_SERVER_TEST_IDS = {
|
|
4522
|
+
card: "ez-devserver-card",
|
|
4523
|
+
log: "ez-devserver-log"
|
|
4524
|
+
};
|
|
4525
|
+
var LOG_POLL_MS = 700;
|
|
4526
|
+
var CARD_LOG_LINES = 200;
|
|
4527
|
+
var SOURCE = {
|
|
4528
|
+
detected: "\u5F9E package.json \u5075\u6E2C",
|
|
4529
|
+
agent: "agent \u5EFA\u8B70\u3001\u4F60\u78BA\u8A8D\u904E\u7684\u6307\u4EE4",
|
|
4530
|
+
user: "\u4F60\u8A2D\u5B9A\u7684\u6307\u4EE4"
|
|
4531
|
+
};
|
|
4532
|
+
function h9(tag, className, text) {
|
|
4533
|
+
const node = document.createElement(tag);
|
|
4534
|
+
if (className) node.className = className;
|
|
4535
|
+
if (text !== void 0) node.textContent = text;
|
|
4536
|
+
return node;
|
|
4537
|
+
}
|
|
4538
|
+
function button(className, label, glyph) {
|
|
4539
|
+
const b = h9("button", className);
|
|
4540
|
+
b.type = "button";
|
|
4541
|
+
if (glyph) b.append(icon(glyph, 14));
|
|
4542
|
+
b.append(h9("span", void 0, label));
|
|
4543
|
+
return b;
|
|
4544
|
+
}
|
|
4545
|
+
function installLine(parts) {
|
|
4546
|
+
const span = h9("span");
|
|
4547
|
+
for (const part of parts) span.append("command" in part ? h9("code", "ez-devserver-inline", part.command) : part.text);
|
|
4548
|
+
return span;
|
|
4549
|
+
}
|
|
4550
|
+
var agentName = (command) => agentProfileFor(command)?.name ?? "agent";
|
|
4551
|
+
function crashLine(state) {
|
|
4552
|
+
if (state.cause === "no-url") return "60 \u79D2\u5167\u6C92\u6709\u5370\u51FA\u7DB2\u5740\uFF0C\u4E5F\u6C92\u6709\u958B\u555F\u4EFB\u4F55 port\uFF0C\u5DF2\u505C\u6B62\u5B83\u3002";
|
|
4553
|
+
if (state.cause === "spawn") return "\u6307\u4EE4\u6C92\u8FA6\u6CD5\u57F7\u884C\u3002";
|
|
4554
|
+
if (state.signal) return `Dev server \u88AB ${state.signal} \u7D50\u675F\u4E86\u3002`;
|
|
4555
|
+
return state.exitCode !== void 0 ? `Dev server \u7D50\u675F\u4E86\uFF08exit code ${state.exitCode}\uFF09\u3002` : "Dev server \u7D50\u675F\u4E86\u3002";
|
|
4556
|
+
}
|
|
4557
|
+
function installDevServerPanel(api2) {
|
|
4558
|
+
const card = h9("section", "ez-devserver-card");
|
|
4559
|
+
card.dataset.testid = DEV_SERVER_TEST_IDS.card;
|
|
4560
|
+
card.setAttribute("aria-live", "polite");
|
|
4561
|
+
card.hidden = true;
|
|
4562
|
+
let state = null;
|
|
4563
|
+
let drawnFor = "";
|
|
4564
|
+
let editing2 = false;
|
|
4565
|
+
let error = null;
|
|
4566
|
+
let busy = false;
|
|
4567
|
+
const log = new LogFeed(api2);
|
|
4568
|
+
async function post(path, body = {}, method = "POST") {
|
|
4569
|
+
busy = true;
|
|
4570
|
+
error = null;
|
|
4571
|
+
repaint();
|
|
4572
|
+
try {
|
|
4573
|
+
const res = await fetch(`${api2}/dev-server/${path}`, {
|
|
4574
|
+
method,
|
|
4575
|
+
headers: { "content-type": "application/json" },
|
|
4576
|
+
body: JSON.stringify({ ...body, host: host.kind })
|
|
4577
|
+
});
|
|
4578
|
+
if (!res.ok) error = (await res.json().catch(() => null))?.error ?? `${res.status}`;
|
|
4579
|
+
return res.ok;
|
|
4580
|
+
} catch {
|
|
4581
|
+
error = "\u9023\u4E0D\u4E0A ezdesign daemon";
|
|
4582
|
+
return false;
|
|
4583
|
+
} finally {
|
|
4584
|
+
busy = false;
|
|
4585
|
+
repaint();
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4588
|
+
function repaint() {
|
|
4589
|
+
drawnFor = "";
|
|
4590
|
+
if (state) paint(state, lastPage);
|
|
4591
|
+
}
|
|
4592
|
+
function commandBlock(command) {
|
|
4593
|
+
const block = h9("div", "ez-devserver-command");
|
|
4594
|
+
const line = h9("code", "ez-devserver-line", command.line);
|
|
4595
|
+
block.append(line);
|
|
4596
|
+
const where = command.cwd ? `${SOURCE[command.source]} \xB7 \u5728 ${command.cwd}/ \u57F7\u884C` : SOURCE[command.source];
|
|
4597
|
+
block.append(h9("span", "ez-devserver-source", where));
|
|
4598
|
+
return block;
|
|
4599
|
+
}
|
|
4600
|
+
function commandForm(initial, cancellable, proposalId) {
|
|
4601
|
+
const form = h9("form", "ez-devserver-form");
|
|
4602
|
+
const lineLabel = h9("label", "ez-devserver-label", "\u555F\u52D5\u6307\u4EE4");
|
|
4603
|
+
const lineInput = h9("input", "ez-devserver-input");
|
|
4604
|
+
lineInput.name = "line";
|
|
4605
|
+
lineInput.placeholder = "pnpm --filter web dev";
|
|
4606
|
+
lineInput.value = initial?.line ?? "";
|
|
4607
|
+
lineInput.spellcheck = false;
|
|
4608
|
+
lineInput.autocomplete = "off";
|
|
4609
|
+
lineLabel.append(lineInput);
|
|
4610
|
+
const cwdLabel = h9("label", "ez-devserver-label", "\u5728\u54EA\u500B\u8CC7\u6599\u593E\u57F7\u884C\uFF08\u76F8\u5C0D\u65BC\u5C08\u6848\uFF0C\u9078\u586B\uFF09");
|
|
4611
|
+
const cwdInput = h9("input", "ez-devserver-input");
|
|
4612
|
+
cwdInput.name = "cwd";
|
|
4613
|
+
cwdInput.placeholder = ".";
|
|
4614
|
+
cwdInput.value = initial?.cwd ?? "";
|
|
4615
|
+
cwdInput.spellcheck = false;
|
|
4616
|
+
cwdInput.autocomplete = "off";
|
|
4617
|
+
cwdLabel.append(cwdInput);
|
|
4618
|
+
const actions = h9("div", "ez-devserver-actions");
|
|
4619
|
+
const go = button("ez-devserver-go", "\u5132\u5B58\u4E26\u555F\u52D5", PlayIcon);
|
|
4620
|
+
go.type = "submit";
|
|
4621
|
+
go.disabled = busy;
|
|
4622
|
+
actions.append(go);
|
|
4623
|
+
if (cancellable) {
|
|
4624
|
+
const cancel = button("ez-devserver-secondary", "\u53D6\u6D88");
|
|
4625
|
+
cancel.onclick = () => {
|
|
4626
|
+
editing2 = false;
|
|
4627
|
+
error = null;
|
|
4628
|
+
repaint();
|
|
4629
|
+
};
|
|
4630
|
+
actions.append(cancel);
|
|
4631
|
+
}
|
|
4632
|
+
if (!proposalId && (initial?.source === "user" || initial?.source === "agent")) {
|
|
4633
|
+
const reset = button("ez-devserver-secondary", "\u6539\u56DE\u81EA\u52D5\u5075\u6E2C");
|
|
4634
|
+
reset.onclick = () => {
|
|
4635
|
+
editing2 = false;
|
|
4636
|
+
void post("command", {}, "DELETE");
|
|
4637
|
+
};
|
|
4638
|
+
actions.append(reset);
|
|
4639
|
+
}
|
|
4640
|
+
form.append(lineLabel, cwdLabel, actions);
|
|
4641
|
+
form.onsubmit = (e) => {
|
|
4642
|
+
e.preventDefault();
|
|
4643
|
+
void post("command", { line: lineInput.value, cwd: cwdInput.value, ...proposalId ? { proposalId } : {} }).then((ok) => {
|
|
4644
|
+
if (ok) editing2 = false;
|
|
4645
|
+
repaint();
|
|
4646
|
+
});
|
|
4647
|
+
};
|
|
4648
|
+
queueMicrotask(() => lineInput.focus({ preventScroll: true }));
|
|
4649
|
+
return form;
|
|
4650
|
+
}
|
|
4651
|
+
function proposalBlock(offer) {
|
|
4652
|
+
const block = commandBlock({ line: offer.line, cwd: offer.cwd, source: "agent" });
|
|
4653
|
+
block.querySelector(".ez-devserver-source").textContent = `${agentName(offer.agent)} \u7684\u5EFA\u8B70${offer.cwd ? ` \xB7 \u5728 ${offer.cwd}/ \u57F7\u884C` : ""}`;
|
|
4654
|
+
if (offer.reason) block.append(h9("span", "ez-devserver-reason", offer.reason));
|
|
4655
|
+
return block;
|
|
4656
|
+
}
|
|
4657
|
+
function proposalNote(offer) {
|
|
4658
|
+
const name = agentName(offer.agent);
|
|
4659
|
+
switch (offer.state) {
|
|
4660
|
+
case "asking":
|
|
4661
|
+
return h9("p", "ez-devserver-asking", "agent \u5075\u6E2C\u4E2D\u2026");
|
|
4662
|
+
case "none-found":
|
|
4663
|
+
return h9("p", "ez-devserver-hint", `${name} \u770B\u904E\u4E86\uFF0C\u6C92\u627E\u5230\u53EF\u4EE5\u555F\u52D5\u7684\u7DB2\u9801${offer.reason ? `\uFF1A${offer.reason}` : "\u3002"}`);
|
|
4664
|
+
case "failed":
|
|
4665
|
+
return h9("p", "ez-devserver-error", `\u6C92\u8FA6\u6CD5\u53D6\u5F97 ${name} \u7684\u5EFA\u8B70\uFF1A${offer.error}`);
|
|
4666
|
+
case "proposed":
|
|
4667
|
+
return h9("p", "ez-devserver-hint", `${name} \u5EFA\u8B70\u7684\u6307\u4EE4\uFF0C\u53EF\u4EE5\u5148\u4FEE\u6539\u518D\u57F7\u884C\u3002`);
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
function logBlock(lines) {
|
|
4671
|
+
const pre = h9("pre", "ez-devserver-log");
|
|
4672
|
+
pre.dataset.testid = DEV_SERVER_TEST_IDS.log;
|
|
4673
|
+
pre.tabIndex = 0;
|
|
4674
|
+
log.into(pre, lines);
|
|
4675
|
+
return pre;
|
|
4676
|
+
}
|
|
4677
|
+
function paintCard(s) {
|
|
4678
|
+
const title = h9("h2", "ez-devserver-title");
|
|
4679
|
+
const body = [];
|
|
4680
|
+
const actions = h9("div", "ez-devserver-actions");
|
|
4681
|
+
const start = (label) => {
|
|
4682
|
+
const b = button("ez-devserver-go", label, PlayIcon);
|
|
4683
|
+
b.disabled = busy;
|
|
4684
|
+
b.onclick = () => void post(s.phase === "crashed" ? "restart" : "start");
|
|
4685
|
+
actions.append(b);
|
|
4686
|
+
};
|
|
4687
|
+
const edit = (label = "\u6539\u7528\u5176\u4ED6\u6307\u4EE4") => {
|
|
4688
|
+
const b = button("ez-devserver-secondary", label);
|
|
4689
|
+
b.onclick = () => {
|
|
4690
|
+
editing2 = true;
|
|
4691
|
+
repaint();
|
|
4692
|
+
};
|
|
4693
|
+
actions.append(b);
|
|
4694
|
+
};
|
|
4695
|
+
const command = "command" in s ? s.command : void 0;
|
|
4696
|
+
if (editing2 && s.phase !== "starting" && s.phase !== "needs-command") {
|
|
4697
|
+
title.textContent = "dev server \u7684\u555F\u52D5\u6307\u4EE4";
|
|
4698
|
+
body.push(commandForm(command, true));
|
|
4699
|
+
} else {
|
|
4700
|
+
switch (s.phase) {
|
|
4701
|
+
case "idle":
|
|
4702
|
+
case "stopped":
|
|
4703
|
+
title.textContent = s.phase === "idle" ? "\u555F\u52D5 dev server" : "Dev server \u5DF2\u505C\u6B62";
|
|
4704
|
+
if (command) {
|
|
4705
|
+
body.push(commandBlock(command));
|
|
4706
|
+
start("\u555F\u52D5");
|
|
4707
|
+
edit();
|
|
4708
|
+
} else {
|
|
4709
|
+
title.textContent = "\u6B63\u5728\u5075\u6E2C\u555F\u52D5\u6307\u4EE4";
|
|
4710
|
+
body.push(h9("p", "ez-devserver-asking", "agent \u5075\u6E2C\u4E2D\u2026"));
|
|
4711
|
+
}
|
|
4712
|
+
break;
|
|
4713
|
+
case "starting": {
|
|
4714
|
+
title.textContent = "\u6B63\u5728\u555F\u52D5 dev server";
|
|
4715
|
+
if (command) body.push(commandBlock(command));
|
|
4716
|
+
body.push(logBlock(CARD_LOG_LINES));
|
|
4717
|
+
const stop = button("ez-devserver-secondary", "\u505C\u6B62", StopIcon);
|
|
4718
|
+
stop.disabled = busy;
|
|
4719
|
+
stop.onclick = () => void post("stop");
|
|
4720
|
+
actions.append(stop);
|
|
4721
|
+
break;
|
|
4722
|
+
}
|
|
4723
|
+
case "needs-command": {
|
|
4724
|
+
const offer = s.proposal;
|
|
4725
|
+
if (offer?.state === "asking" && !editing2) {
|
|
4726
|
+
title.textContent = "\u6B63\u5728\u5075\u6E2C\u555F\u52D5\u6307\u4EE4";
|
|
4727
|
+
body.push(proposalNote(offer));
|
|
4728
|
+
break;
|
|
4729
|
+
}
|
|
4730
|
+
title.textContent = "\u9700\u8981\u4E00\u500B\u555F\u52D5\u6307\u4EE4";
|
|
4731
|
+
if (offer?.state === "proposed" && !editing2) {
|
|
4732
|
+
title.textContent = "\u555F\u52D5 dev server";
|
|
4733
|
+
body.push(proposalBlock(offer));
|
|
4734
|
+
const run = button("ez-devserver-go", "\u57F7\u884C", PlayIcon);
|
|
4735
|
+
run.disabled = busy;
|
|
4736
|
+
run.onclick = () => void post("command", { line: offer.line, cwd: offer.cwd, proposalId: offer.id });
|
|
4737
|
+
const change = button("ez-devserver-secondary", "\u4FEE\u6539");
|
|
4738
|
+
change.onclick = () => {
|
|
4739
|
+
editing2 = true;
|
|
4740
|
+
repaint();
|
|
4741
|
+
};
|
|
4742
|
+
actions.append(run, change);
|
|
4743
|
+
break;
|
|
4744
|
+
}
|
|
4745
|
+
if (offer) body.push(proposalNote(offer));
|
|
4746
|
+
if (s.serverScripts.length) body.push(h9("p", "ez-devserver-hint", `\u770B\u8D77\u4F86\u50CF dev server \u7684 script\uFF1A${s.serverScripts.join("\u3001")}`));
|
|
4747
|
+
body.push(
|
|
4748
|
+
offer?.state === "proposed" ? commandForm({ line: offer.line, cwd: offer.cwd, source: "agent" }, true, offer.id) : commandForm(void 0, false)
|
|
4749
|
+
);
|
|
4750
|
+
if (offer?.state === "failed" || offer?.state === "none-found") {
|
|
4751
|
+
const again = button("ez-devserver-secondary", "\u518D\u554F\u4E00\u6B21");
|
|
4752
|
+
again.onclick = () => void post("propose");
|
|
4753
|
+
actions.append(again);
|
|
4754
|
+
}
|
|
4755
|
+
break;
|
|
4756
|
+
}
|
|
4757
|
+
case "blocked": {
|
|
4758
|
+
title.textContent = "\u7F3A\u5C11\u555F\u52D5\u9700\u8981\u7684\u5DE5\u5177";
|
|
4759
|
+
body.push(commandBlock(s.command));
|
|
4760
|
+
const list = h9("ul", "ez-devserver-missing");
|
|
4761
|
+
for (const m of s.missing) {
|
|
4762
|
+
const item = h9("li");
|
|
4763
|
+
item.append(h9("code", "ez-devserver-tool", m.tool), installLine(m.install));
|
|
4764
|
+
list.append(item);
|
|
4765
|
+
}
|
|
4766
|
+
body.push(list, h9("p", "ez-devserver-hint", "\u88DD\u597D\u4E4B\u5F8C\u6309\u300C\u518D\u8A66\u4E00\u6B21\u300D\u3002"));
|
|
4767
|
+
start("\u518D\u8A66\u4E00\u6B21");
|
|
4768
|
+
edit();
|
|
4769
|
+
break;
|
|
4770
|
+
}
|
|
4771
|
+
case "crashed":
|
|
4772
|
+
title.textContent = "Dev server \u505C\u6B62\u904B\u4F5C\u4E86";
|
|
4773
|
+
body.push(h9("p", "ez-devserver-text", crashLine(s)), commandBlock(s.command));
|
|
4774
|
+
if (s.tail.length) {
|
|
4775
|
+
const pre = h9("pre", "ez-devserver-log", s.tail.join("\n"));
|
|
4776
|
+
pre.dataset.testid = DEV_SERVER_TEST_IDS.log;
|
|
4777
|
+
pre.tabIndex = 0;
|
|
4778
|
+
body.push(pre);
|
|
4779
|
+
queueMicrotask(() => pre.scrollTop = pre.scrollHeight);
|
|
4780
|
+
}
|
|
4781
|
+
start("\u91CD\u65B0\u555F\u52D5");
|
|
4782
|
+
edit();
|
|
4783
|
+
break;
|
|
4784
|
+
case "running":
|
|
4785
|
+
case "external":
|
|
4786
|
+
title.textContent = "\u6B63\u5728\u9023\u4E0A dev server";
|
|
4787
|
+
break;
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
card.replaceChildren(title, ...body);
|
|
4791
|
+
if (actions.childElementCount) card.append(actions);
|
|
4792
|
+
if (error) card.append(h9("p", "ez-devserver-error", error));
|
|
4793
|
+
}
|
|
4794
|
+
let lastPage = { shown: false, onAppTab: false };
|
|
4795
|
+
let detecting = false;
|
|
4796
|
+
function paint(s, page) {
|
|
4797
|
+
const showCard = page.onAppTab && !page.shown;
|
|
4798
|
+
if (showCard && s.phase === "idle" && !s.command && !detecting) {
|
|
4799
|
+
detecting = true;
|
|
4800
|
+
void post("start");
|
|
4801
|
+
}
|
|
4802
|
+
card.hidden = !showCard;
|
|
4803
|
+
log.feedCard(showCard && s.phase === "starting");
|
|
4804
|
+
const key = JSON.stringify([s, showCard, editing2, busy, error]);
|
|
4805
|
+
if (key === drawnFor) return;
|
|
4806
|
+
drawnFor = key;
|
|
4807
|
+
if (showCard) paintCard(s);
|
|
4808
|
+
}
|
|
4809
|
+
return {
|
|
4810
|
+
card,
|
|
4811
|
+
update(next, page) {
|
|
4812
|
+
if (next.phase === "starting" && state?.phase !== "starting") log.reset();
|
|
4813
|
+
state = next;
|
|
4814
|
+
lastPage = page;
|
|
4815
|
+
paint(next, page);
|
|
4816
|
+
}
|
|
4817
|
+
};
|
|
4818
|
+
}
|
|
4819
|
+
var LogFeed = class {
|
|
4820
|
+
constructor(api2) {
|
|
4821
|
+
this.api = api2;
|
|
4822
|
+
__publicField(this, "timer", null);
|
|
4823
|
+
__publicField(this, "views", /* @__PURE__ */ new Set());
|
|
4824
|
+
__publicField(this, "last", { lines: [], dropped: 0 });
|
|
4825
|
+
__publicField(this, "wanted", false);
|
|
4826
|
+
}
|
|
4827
|
+
into(pre, lines) {
|
|
4828
|
+
const view = { pre, lines };
|
|
4829
|
+
this.views.add(view);
|
|
4830
|
+
this.draw(view);
|
|
4831
|
+
this.schedule();
|
|
4832
|
+
void this.fetch();
|
|
4833
|
+
}
|
|
4834
|
+
reset() {
|
|
4835
|
+
this.last = { lines: [], dropped: 0 };
|
|
4836
|
+
}
|
|
4837
|
+
feedCard(on) {
|
|
4838
|
+
this.wanted = on;
|
|
4839
|
+
for (const view of [...this.views]) if (!view.pre.isConnected) this.views.delete(view);
|
|
4840
|
+
this.schedule();
|
|
4841
|
+
}
|
|
4842
|
+
schedule() {
|
|
4843
|
+
const needed = this.wanted;
|
|
4844
|
+
if (needed && this.timer === null) {
|
|
4845
|
+
this.timer = window.setInterval(() => void this.fetch(), LOG_POLL_MS);
|
|
4846
|
+
} else if (!needed && this.timer !== null) {
|
|
4847
|
+
window.clearInterval(this.timer);
|
|
4848
|
+
this.timer = null;
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
async fetch() {
|
|
4852
|
+
try {
|
|
4853
|
+
const res = await fetch(`${this.api}/dev-server/log`);
|
|
4854
|
+
if (!res.ok) return;
|
|
4855
|
+
this.last = await res.json();
|
|
4856
|
+
} catch {
|
|
4857
|
+
return;
|
|
4858
|
+
}
|
|
4859
|
+
for (const view of this.views) this.draw(view);
|
|
4860
|
+
}
|
|
4861
|
+
draw(view) {
|
|
4862
|
+
const { pre } = view;
|
|
4863
|
+
const pinned = pre.scrollHeight - pre.scrollTop - pre.clientHeight < 24;
|
|
4864
|
+
const text = this.last.lines.slice(-view.lines).join("\n");
|
|
4865
|
+
if (pre.textContent === text) return;
|
|
4866
|
+
pre.textContent = text;
|
|
4867
|
+
if (pinned) pre.scrollTop = pre.scrollHeight;
|
|
4868
|
+
}
|
|
4869
|
+
};
|
|
4870
|
+
|
|
4116
4871
|
// src/canvas/wire.ts
|
|
4117
4872
|
var SSE_CANVAS = "canvas";
|
|
4118
4873
|
var SSE_CANVAS_REMOVED = "canvas-removed";
|
|
@@ -4139,7 +4894,7 @@
|
|
|
4139
4894
|
// src/client/page-storage.ts
|
|
4140
4895
|
var SHELL_OWNED_PREFIXES = ["ezdesign:", "ez-update-dismissed", "ez-confirm-skip:"];
|
|
4141
4896
|
var MAX_RECORDS_PER_STORE = 1e3;
|
|
4142
|
-
var
|
|
4897
|
+
var MAX_BYTES = 15e5;
|
|
4143
4898
|
var COLLECT_TIMEOUT_MS = 1500;
|
|
4144
4899
|
function storageEntries(store) {
|
|
4145
4900
|
const out = [];
|
|
@@ -4233,7 +4988,7 @@
|
|
|
4233
4988
|
const timedOut = new Promise((ok) => setTimeout(() => ok([]), COLLECT_TIMEOUT_MS));
|
|
4234
4989
|
const indexedDB = await Promise.race([readIndexedDb(factory).catch(() => []), timedOut]);
|
|
4235
4990
|
const storage = { localStorage: local, sessionStorage: session, indexedDB };
|
|
4236
|
-
return JSON.stringify(storage).length >
|
|
4991
|
+
return JSON.stringify(storage).length > MAX_BYTES ? { ...storage, indexedDB: [] } : storage;
|
|
4237
4992
|
}
|
|
4238
4993
|
|
|
4239
4994
|
// src/client/usage-note.ts
|
|
@@ -4381,9 +5136,9 @@
|
|
|
4381
5136
|
const heights = rows.map((row) => m.head + Math.max(...row.map((d) => d.height)));
|
|
4382
5137
|
const tops = [];
|
|
4383
5138
|
let y = 0;
|
|
4384
|
-
for (const
|
|
5139
|
+
for (const h11 of heights) {
|
|
4385
5140
|
tops.push(y);
|
|
4386
|
-
y +=
|
|
5141
|
+
y += h11 + m.rowGap;
|
|
4387
5142
|
}
|
|
4388
5143
|
return {
|
|
4389
5144
|
tops,
|
|
@@ -5093,6 +5848,7 @@
|
|
|
5093
5848
|
var API = `${PREFIX}/api`;
|
|
5094
5849
|
var BUILD = document.currentScript?.dataset.version ?? "";
|
|
5095
5850
|
var shellAttachments = directAttachments(API);
|
|
5851
|
+
var digests = videoDigests(API, `${PREFIX}/video-digest.js?v=${BUILD}`, () => paintVideos());
|
|
5096
5852
|
var MOD_LABEL = modLabel(navigator.userAgent);
|
|
5097
5853
|
var PAGE_PATH = new URLSearchParams(location.search).get("path") || "/";
|
|
5098
5854
|
var ANNOTATE_MODES = [
|
|
@@ -5117,7 +5873,7 @@
|
|
|
5117
5873
|
var TICK_ICON = 14;
|
|
5118
5874
|
var snapshot = null;
|
|
5119
5875
|
var canvasUi = null;
|
|
5120
|
-
var stagedApp =
|
|
5876
|
+
var stagedApp = document.currentScript?.dataset.app || null;
|
|
5121
5877
|
var annotateMode = "off";
|
|
5122
5878
|
var daemonGone = false;
|
|
5123
5879
|
var goneTimer;
|
|
@@ -5158,26 +5914,26 @@
|
|
|
5158
5914
|
}
|
|
5159
5915
|
loadView();
|
|
5160
5916
|
var root = document.getElementById("ez-shell");
|
|
5161
|
-
function
|
|
5917
|
+
function h10(tag, className, text) {
|
|
5162
5918
|
const node = document.createElement(tag);
|
|
5163
5919
|
if (className) node.className = className;
|
|
5164
5920
|
if (text !== void 0) node.textContent = text;
|
|
5165
5921
|
return node;
|
|
5166
5922
|
}
|
|
5167
|
-
var brand =
|
|
5923
|
+
var brand = h10("div", "ez-logo");
|
|
5168
5924
|
brand.setAttribute("role", "img");
|
|
5169
5925
|
brand.setAttribute("aria-label", "ezdesign");
|
|
5170
5926
|
brand.innerHTML = brandLockupSvg();
|
|
5171
|
-
var version =
|
|
5172
|
-
var updatePill =
|
|
5927
|
+
var version = h10("span", "ez-version");
|
|
5928
|
+
var updatePill = h10("button", "ez-update-flag");
|
|
5173
5929
|
updatePill.setAttribute("aria-haspopup", "menu");
|
|
5174
5930
|
updatePill.setAttribute("aria-expanded", "false");
|
|
5175
|
-
var updateMenu =
|
|
5931
|
+
var updateMenu = h10("div", "ez-menu");
|
|
5176
5932
|
updateMenu.setAttribute("role", "menu");
|
|
5177
|
-
var updateNow =
|
|
5933
|
+
var updateNow = h10("button", "ez-menu-item");
|
|
5178
5934
|
updateNow.setAttribute("role", "menuitem");
|
|
5179
5935
|
updateMenu.append(updateNow);
|
|
5180
|
-
var updateHint =
|
|
5936
|
+
var updateHint = h10("div", "ez-update-hint");
|
|
5181
5937
|
updateHint.hidden = true;
|
|
5182
5938
|
updateHint.append(updatePill, updateMenu);
|
|
5183
5939
|
var updateMenuOpen = false;
|
|
@@ -5200,15 +5956,15 @@
|
|
|
5200
5956
|
paintUpdateMenu();
|
|
5201
5957
|
}
|
|
5202
5958
|
});
|
|
5203
|
-
var target =
|
|
5204
|
-
var agentStatus =
|
|
5205
|
-
var agentPill =
|
|
5959
|
+
var target = h10("span", "ez-target");
|
|
5960
|
+
var agentStatus = h10("div", "ez-badge");
|
|
5961
|
+
var agentPill = h10("button", "ez-agent-pill");
|
|
5206
5962
|
agentPill.setAttribute("aria-haspopup", "menu");
|
|
5207
5963
|
agentPill.setAttribute("aria-expanded", "false");
|
|
5208
|
-
var agentMenu =
|
|
5964
|
+
var agentMenu = h10("div", "ez-menu ez-menu-up");
|
|
5209
5965
|
agentMenu.setAttribute("role", "menu");
|
|
5210
5966
|
agentMenu.setAttribute("aria-label", "Agent");
|
|
5211
|
-
var agentWrap =
|
|
5967
|
+
var agentWrap = h10("div", "ez-agent");
|
|
5212
5968
|
agentWrap.hidden = true;
|
|
5213
5969
|
agentWrap.append(agentPill, agentMenu);
|
|
5214
5970
|
var plain = (key) => (e) => !e.metaKey && !e.ctrlKey && e.key.toLowerCase() === key.toLowerCase();
|
|
@@ -5307,7 +6063,7 @@
|
|
|
5307
6063
|
}
|
|
5308
6064
|
return false;
|
|
5309
6065
|
}
|
|
5310
|
-
var keysBtn =
|
|
6066
|
+
var keysBtn = h10("button", "ez-keys");
|
|
5311
6067
|
keysBtn.append(icon(KeyboardIcon, 14));
|
|
5312
6068
|
keysBtn.title = "\u5FEB\u6377\u9375";
|
|
5313
6069
|
keysBtn.setAttribute("aria-label", "\u5FEB\u6377\u9375");
|
|
@@ -5326,13 +6082,13 @@
|
|
|
5326
6082
|
paintKeys();
|
|
5327
6083
|
}
|
|
5328
6084
|
keysBtn.onclick = () => pinKeys(!keysPinned);
|
|
5329
|
-
var keysPanel =
|
|
6085
|
+
var keysPanel = h10("div", "ez-keys-panel");
|
|
5330
6086
|
for (const s of SHORTCUTS) {
|
|
5331
|
-
const row =
|
|
5332
|
-
row.append(
|
|
6087
|
+
const row = h10("div", "ez-keys-row");
|
|
6088
|
+
row.append(h10("kbd", "ez-kbd", s.keys), h10("span", "ez-keys-label", s.label));
|
|
5333
6089
|
keysPanel.appendChild(row);
|
|
5334
6090
|
}
|
|
5335
|
-
var keysWrap =
|
|
6091
|
+
var keysWrap = h10("div", "ez-keys-wrap");
|
|
5336
6092
|
keysWrap.append(keysBtn, keysPanel);
|
|
5337
6093
|
keysWrap.addEventListener("pointerenter", () => {
|
|
5338
6094
|
window.clearTimeout(keysCloseTimer);
|
|
@@ -5349,23 +6105,23 @@
|
|
|
5349
6105
|
document.addEventListener("click", (e) => {
|
|
5350
6106
|
if (keysPinned && e.target instanceof Node && !keysWrap.contains(e.target)) pinKeys(false);
|
|
5351
6107
|
});
|
|
5352
|
-
var headRow =
|
|
5353
|
-
headRow.append(brand, version, updateHint,
|
|
5354
|
-
var deviceName =
|
|
6108
|
+
var headRow = h10("div", "ez-head-row");
|
|
6109
|
+
headRow.append(brand, version, updateHint, h10("div", "ez-spacer"), keysWrap, agentStatus);
|
|
6110
|
+
var deviceName = h10("button", "ez-seg-label");
|
|
5355
6111
|
deviceName.onclick = () => setDevice(deviceId);
|
|
5356
|
-
var deviceCaret =
|
|
6112
|
+
var deviceCaret = h10("button", "ez-seg-caret");
|
|
5357
6113
|
deviceCaret.append(icon(ChevronDownIcon, 12));
|
|
5358
6114
|
deviceCaret.setAttribute("aria-haspopup", "menu");
|
|
5359
6115
|
deviceCaret.setAttribute("aria-expanded", "false");
|
|
5360
|
-
var deviceMenu =
|
|
6116
|
+
var deviceMenu = h10("div", "ez-menu");
|
|
5361
6117
|
deviceMenu.setAttribute("role", "menu");
|
|
5362
6118
|
deviceMenu.setAttribute("aria-label", "\u9810\u89BD\u5C3A\u5BF8");
|
|
5363
6119
|
var deviceItems = DEVICES.map((d) => {
|
|
5364
|
-
const item =
|
|
6120
|
+
const item = h10("button", "ez-menu-item");
|
|
5365
6121
|
item.setAttribute("role", "menuitemradio");
|
|
5366
6122
|
item.dataset.device = d.id;
|
|
5367
6123
|
item.title = deviceLabel(d);
|
|
5368
|
-
item.append(
|
|
6124
|
+
item.append(h10("span", "ez-menu-name", d.name), menuCheck());
|
|
5369
6125
|
item.onclick = () => {
|
|
5370
6126
|
closeDeviceMenu();
|
|
5371
6127
|
setDevice(d.id);
|
|
@@ -5373,7 +6129,7 @@
|
|
|
5373
6129
|
deviceMenu.appendChild(item);
|
|
5374
6130
|
return item;
|
|
5375
6131
|
});
|
|
5376
|
-
var deviceGroup =
|
|
6132
|
+
var deviceGroup = h10("div", "ez-seg-item ez-seg-device");
|
|
5377
6133
|
deviceGroup.append(deviceName, deviceCaret, deviceMenu);
|
|
5378
6134
|
var deviceMenuOpen = false;
|
|
5379
6135
|
function paintDeviceMenu() {
|
|
@@ -5417,11 +6173,12 @@
|
|
|
5417
6173
|
if (to instanceof Node && deviceGroup.contains(to)) return;
|
|
5418
6174
|
closeDeviceMenu();
|
|
5419
6175
|
});
|
|
5420
|
-
var multiBtn =
|
|
6176
|
+
var multiBtn = h10("button", "ez-seg-item ez-seg-multi", "\u5168\u90E8\u5C3A\u5BF8");
|
|
5421
6177
|
multiBtn.title = "\u6240\u6709\u5C3A\u5BF8\u6392\u6210\u4E00\u5F35\u756B\u5E03\uFF0C\u62D6\u66F3\u80CC\u666F\u79FB\u52D5\uFF084\uFF09";
|
|
5422
6178
|
multiBtn.onclick = () => setMulti(!multi);
|
|
5423
|
-
var deviceRow =
|
|
6179
|
+
var deviceRow = h10("div", "ez-seg");
|
|
5424
6180
|
deviceRow.append(deviceGroup, multiBtn);
|
|
6181
|
+
deviceRow.hidden = stagedApp === null;
|
|
5425
6182
|
function paintControls() {
|
|
5426
6183
|
const device = deviceById(deviceId);
|
|
5427
6184
|
deviceName.textContent = device.name;
|
|
@@ -5437,10 +6194,10 @@
|
|
|
5437
6194
|
multiBtn.setAttribute("aria-pressed", String(multi));
|
|
5438
6195
|
paintShown();
|
|
5439
6196
|
}
|
|
5440
|
-
var annotateGroup =
|
|
6197
|
+
var annotateGroup = h10("div", "ez-annotate-group");
|
|
5441
6198
|
var annotateBtns = ANNOTATE_MODES.map((m) => {
|
|
5442
|
-
const btn =
|
|
5443
|
-
btn.append(icon(m.svg, 15),
|
|
6199
|
+
const btn = h10("button", `ez-tool-btn ez-mode-${m.id}`);
|
|
6200
|
+
btn.append(icon(m.svg, 15), h10("span", void 0, m.label));
|
|
5444
6201
|
btn.title = `${m.hint}\uFF08${m.key}\uFF09\u30FBEsc \u96E2\u958B`;
|
|
5445
6202
|
btn.onclick = () => sendMode(annotateMode === m.id ? "off" : m.id);
|
|
5446
6203
|
annotateGroup.appendChild(btn);
|
|
@@ -5454,12 +6211,13 @@
|
|
|
5454
6211
|
}
|
|
5455
6212
|
canvasUi?.setAnnotating(annotateMode);
|
|
5456
6213
|
}
|
|
5457
|
-
var
|
|
6214
|
+
var devServerPanel = installDevServerPanel(API);
|
|
6215
|
+
var sideHead = h10("div", "ez-side-head");
|
|
5458
6216
|
sideHead.append(headRow, target, deviceRow, annotateGroup);
|
|
5459
|
-
var statusPill =
|
|
6217
|
+
var statusPill = h10("div", "ez-status");
|
|
5460
6218
|
statusPill.setAttribute("role", "status");
|
|
5461
6219
|
statusPill.hidden = true;
|
|
5462
|
-
var updateCard =
|
|
6220
|
+
var updateCard = h10("section", "ez-update");
|
|
5463
6221
|
updateCard.hidden = true;
|
|
5464
6222
|
var UPDATE_DISMISSED_KEY = "ez-update-dismissed";
|
|
5465
6223
|
function updateOfferKey(u) {
|
|
@@ -5525,10 +6283,10 @@
|
|
|
5525
6283
|
updateCard.hidden = !u || !!dismissed;
|
|
5526
6284
|
updateCard.textContent = "";
|
|
5527
6285
|
if (!u || dismissed) return;
|
|
5528
|
-
updateCard.append(
|
|
6286
|
+
updateCard.append(h10("div", "ez-update-title", updateTitle(u)));
|
|
5529
6287
|
const busy = u.phase !== "available" && u.phase !== "failed";
|
|
5530
|
-
const lines =
|
|
5531
|
-
const line = (text, cls = "") => lines.append(
|
|
6288
|
+
const lines = h10("ul", "ez-update-lines");
|
|
6289
|
+
const line = (text, cls = "") => lines.append(h10("li", cls || void 0, text));
|
|
5532
6290
|
const working = s.acp?.state === "working";
|
|
5533
6291
|
if (busy) {
|
|
5534
6292
|
if (u.phase === "installing") line("\u4E0B\u8F09\u4E26\u5B89\u88DD\u65B0\u7248\u672C\u2026");
|
|
@@ -5539,10 +6297,10 @@
|
|
|
5539
6297
|
}
|
|
5540
6298
|
if (lines.childElementCount) updateCard.append(lines);
|
|
5541
6299
|
if (!busy) {
|
|
5542
|
-
const actions =
|
|
5543
|
-
const go =
|
|
6300
|
+
const actions = h10("div", "ez-update-actions");
|
|
6301
|
+
const go = h10("button", "ez-update-go");
|
|
5544
6302
|
go.append(
|
|
5545
|
-
|
|
6303
|
+
h10(
|
|
5546
6304
|
"span",
|
|
5547
6305
|
"ez-update-label",
|
|
5548
6306
|
u.phase === "failed" ? "\u91CD\u8A66" : working ? "\u4ECD\u8981\u66F4\u65B0" : "\u7ACB\u5373\u66F4\u65B0"
|
|
@@ -5552,7 +6310,7 @@
|
|
|
5552
6310
|
go.onclick = () => void startUpdate();
|
|
5553
6311
|
actions.append(go);
|
|
5554
6312
|
updateCard.append(actions);
|
|
5555
|
-
const dismiss =
|
|
6313
|
+
const dismiss = h10("button", "ez-update-x");
|
|
5556
6314
|
dismiss.append(icon(Cancel01Icon, 13));
|
|
5557
6315
|
dismiss.title = "\u7A0D\u5F8C\u518D\u8AAA\uFF08\u7248\u865F\u65C1\u7684\u63D0\u793A\u6703\u7559\u8457\uFF09";
|
|
5558
6316
|
dismiss.setAttribute("aria-label", dismiss.title);
|
|
@@ -5560,16 +6318,16 @@
|
|
|
5560
6318
|
updateCard.append(dismiss);
|
|
5561
6319
|
}
|
|
5562
6320
|
}
|
|
5563
|
-
var stageWrap =
|
|
5564
|
-
var stage =
|
|
5565
|
-
var grid =
|
|
5566
|
-
stage.append(grid);
|
|
5567
|
-
var strip =
|
|
6321
|
+
var stageWrap = h10("div", "ez-stage-wrap");
|
|
6322
|
+
var stage = h10("div", "ez-stage");
|
|
6323
|
+
var grid = h10("div", "ez-grid");
|
|
6324
|
+
stage.append(devServerPanel.card, grid);
|
|
6325
|
+
var strip = h10("div", "ez-strip");
|
|
5568
6326
|
strip.hidden = true;
|
|
5569
6327
|
function stripNotice(text) {
|
|
5570
6328
|
strip.hidden = false;
|
|
5571
|
-
const pill =
|
|
5572
|
-
pill.append(icon(MagicWand01Icon, 14),
|
|
6329
|
+
const pill = h10("div", "ez-strip-pill");
|
|
6330
|
+
pill.append(icon(MagicWand01Icon, 14), h10("div", "ez-strip-pending", text));
|
|
5573
6331
|
strip.replaceChildren(pill);
|
|
5574
6332
|
setTimeout(() => {
|
|
5575
6333
|
if (!liveExplores().length) strip.hidden = true;
|
|
@@ -5701,18 +6459,18 @@
|
|
|
5701
6459
|
return;
|
|
5702
6460
|
}
|
|
5703
6461
|
closeStripAsk();
|
|
5704
|
-
const card =
|
|
6462
|
+
const card = h10("div", "ez-strip-ask");
|
|
5705
6463
|
card.setAttribute("role", "dialog");
|
|
5706
6464
|
card.setAttribute("aria-label", offer.go);
|
|
5707
|
-
const skip =
|
|
6465
|
+
const skip = h10("input");
|
|
5708
6466
|
skip.type = "checkbox";
|
|
5709
|
-
const skipLabel =
|
|
5710
|
-
skipLabel.append(skip,
|
|
5711
|
-
const go =
|
|
5712
|
-
const no =
|
|
5713
|
-
const row =
|
|
6467
|
+
const skipLabel = h10("label", "ez-strip-ask-skip");
|
|
6468
|
+
skipLabel.append(skip, h10("span", void 0, "\u4E0D\u8981\u518D\u63D0\u793A"));
|
|
6469
|
+
const go = h10("button", "ez-strip-ask-go", offer.go);
|
|
6470
|
+
const no = h10("button", "ez-strip-ask-no", "\u53D6\u6D88");
|
|
6471
|
+
const row = h10("div", "ez-strip-ask-actions");
|
|
5714
6472
|
row.append(go, no);
|
|
5715
|
-
card.append(
|
|
6473
|
+
card.append(h10("div", void 0, offer.body), row, skipLabel);
|
|
5716
6474
|
const outside = (e) => {
|
|
5717
6475
|
if (e.target instanceof Node && !card.contains(e.target)) done3(false);
|
|
5718
6476
|
};
|
|
@@ -5760,17 +6518,17 @@
|
|
|
5760
6518
|
});
|
|
5761
6519
|
}
|
|
5762
6520
|
function roundPill(round2) {
|
|
5763
|
-
const pill =
|
|
6521
|
+
const pill = h10("div", "ez-strip-pill");
|
|
5764
6522
|
pill.dataset.round = round2.id;
|
|
5765
6523
|
pill.title = round2.direction ? `${round2.label}\uFF1A${round2.direction}` : round2.label;
|
|
5766
6524
|
pill.setAttribute("role", "group");
|
|
5767
6525
|
pill.setAttribute("aria-label", `\u63A2\u7D22 ${round2.label}`);
|
|
5768
6526
|
pill.append(icon(MagicWand01Icon, 14));
|
|
5769
|
-
const chips =
|
|
6527
|
+
const chips = h10("div", "ez-strip-chips");
|
|
5770
6528
|
chips.setAttribute("role", "radiogroup");
|
|
5771
6529
|
chips.setAttribute("aria-label", "\u8B8A\u9AD4");
|
|
5772
6530
|
const chip = (choice, name, title) => {
|
|
5773
|
-
const btn =
|
|
6531
|
+
const btn = h10("button", "ez-strip-chip", name);
|
|
5774
6532
|
btn.setAttribute("role", "radio");
|
|
5775
6533
|
btn.dataset.choice = choice ?? "";
|
|
5776
6534
|
btn.title = title;
|
|
@@ -5788,12 +6546,12 @@
|
|
|
5788
6546
|
radioKeys(chips, radios, (btn) => select(round2, btn.dataset.choice || null));
|
|
5789
6547
|
chips.append(...radios);
|
|
5790
6548
|
if (round2.status === "generating") {
|
|
5791
|
-
chips.append(
|
|
6549
|
+
chips.append(h10("div", "ez-strip-pending", round2.variants.length ? "\u9084\u5728\u60F3\u2026" : "\u6B63\u5728\u7522\u751F\u2026"));
|
|
5792
6550
|
}
|
|
5793
6551
|
pill.append(chips);
|
|
5794
|
-
const actions =
|
|
6552
|
+
const actions = h10("div", "ez-strip-actions");
|
|
5795
6553
|
const chosen = round2.variants.find((v) => v.id === round2.selected);
|
|
5796
|
-
const adopt =
|
|
6554
|
+
const adopt = h10("button", "ez-strip-action", "\u9078\u64C7");
|
|
5797
6555
|
adopt.disabled = !chosen;
|
|
5798
6556
|
adopt.title = chosen ? `\u5E36\u300C${chosen.name}\u300D\u56DE\u4E3B\u5C0D\u8A71\uFF0C\u4EA4\u7D66 agent \u5BE6\u4F5C\u9032\u5C08\u6848` : "\u5148\u6311\u4E00\u500B\u8B8A\u9AD4\uFF0C\u624D\u6709\u6771\u897F\u53EF\u4EE5\u5E36\u56DE\u53BB";
|
|
5799
6557
|
adopt.onclick = () => askOnStrip(
|
|
@@ -5806,7 +6564,7 @@
|
|
|
5806
6564
|
() => void adoptVariant(round2, chosen)
|
|
5807
6565
|
);
|
|
5808
6566
|
actions.append(adopt);
|
|
5809
|
-
const quit =
|
|
6567
|
+
const quit = h10("button", "ez-strip-action", "\u9000\u51FA\u63A2\u7D22");
|
|
5810
6568
|
quit.title = "\u7D50\u675F\u9019\u4E00\u8F2A\u63A2\u7D22\uFF0C\u56DE\u5230\u4E3B\u5C0D\u8A71";
|
|
5811
6569
|
quit.onclick = () => askOnStrip(
|
|
5812
6570
|
actions,
|
|
@@ -5821,36 +6579,36 @@
|
|
|
5821
6579
|
pill.append(actions);
|
|
5822
6580
|
return pill;
|
|
5823
6581
|
}
|
|
5824
|
-
var shownBtn =
|
|
6582
|
+
var shownBtn = h10("button", "ez-shown-btn");
|
|
5825
6583
|
shownBtn.append(icon(Grid02Icon, 14));
|
|
5826
6584
|
shownBtn.title = "\u9078\u64C7\u756B\u5E03\u4E0A\u8981\u986F\u793A\u7684\u5C3A\u5BF8";
|
|
5827
6585
|
shownBtn.setAttribute("aria-label", "\u9078\u64C7\u756B\u5E03\u4E0A\u8981\u986F\u793A\u7684\u5C3A\u5BF8");
|
|
5828
6586
|
shownBtn.setAttribute("aria-haspopup", "menu");
|
|
5829
6587
|
shownBtn.setAttribute("aria-expanded", "false");
|
|
5830
|
-
var shownMenu =
|
|
6588
|
+
var shownMenu = h10("div", "ez-menu ez-menu-right");
|
|
5831
6589
|
shownMenu.setAttribute("role", "menu");
|
|
5832
6590
|
shownMenu.setAttribute("aria-label", "\u756B\u5E03\u4E0A\u7684\u5C3A\u5BF8");
|
|
5833
6591
|
var shownItems = GRID_DEVICES.map((d) => {
|
|
5834
|
-
const item =
|
|
6592
|
+
const item = h10("button", "ez-menu-item");
|
|
5835
6593
|
item.setAttribute("role", "menuitemcheckbox");
|
|
5836
6594
|
item.dataset.device = d.id;
|
|
5837
6595
|
item.title = deviceLabel(d);
|
|
5838
|
-
const tick =
|
|
6596
|
+
const tick = h10("span", "ez-menu-tick");
|
|
5839
6597
|
tick.append(icon(CheckIcon, 14));
|
|
5840
|
-
item.append(tick,
|
|
6598
|
+
item.append(tick, h10("span", "ez-menu-name", d.name));
|
|
5841
6599
|
item.onclick = () => toggleShown(d.id);
|
|
5842
6600
|
shownMenu.appendChild(item);
|
|
5843
6601
|
return item;
|
|
5844
6602
|
});
|
|
5845
|
-
var shownWrap =
|
|
6603
|
+
var shownWrap = h10("div", "ez-shown");
|
|
5846
6604
|
shownWrap.append(shownBtn, shownMenu);
|
|
5847
|
-
var pickPill =
|
|
6605
|
+
var pickPill = h10("div", "ez-pick-pill");
|
|
5848
6606
|
pickPill.hidden = true;
|
|
5849
|
-
var pickPillText =
|
|
5850
|
-
var pickPillCancel =
|
|
6607
|
+
var pickPillText = h10("span", "ez-pick-pill-text");
|
|
6608
|
+
var pickPillCancel = h10("button", "ez-pick-pill-cancel", "\u53D6\u6D88");
|
|
5851
6609
|
pickPillCancel.onclick = () => abortPick("escape");
|
|
5852
6610
|
pickPill.append(icon(AlignSelectionIcon, 14), pickPillText, pickPillCancel);
|
|
5853
|
-
var stageDock =
|
|
6611
|
+
var stageDock = h10("div", "ez-stage-dock");
|
|
5854
6612
|
stageDock.append(strip, pickPill);
|
|
5855
6613
|
stageWrap.append(stage, shownWrap, stageDock, installAnnouncement(API, ANNOUNCEMENTS));
|
|
5856
6614
|
var shownMenuOpen = false;
|
|
@@ -5965,7 +6723,7 @@
|
|
|
5965
6723
|
return;
|
|
5966
6724
|
}
|
|
5967
6725
|
if (stagedApp === null) {
|
|
5968
|
-
target.textContent = "
|
|
6726
|
+
target.textContent = "";
|
|
5969
6727
|
document.title = "ezdesign";
|
|
5970
6728
|
return;
|
|
5971
6729
|
}
|
|
@@ -5974,12 +6732,12 @@
|
|
|
5974
6732
|
document.title = `ezdesign \xB7 ${nav.url}`;
|
|
5975
6733
|
}
|
|
5976
6734
|
function mountFrame(id, device, into) {
|
|
5977
|
-
const card =
|
|
5978
|
-
const head =
|
|
6735
|
+
const card = h10("div", "ez-card");
|
|
6736
|
+
const head = h10("div", "ez-card-head");
|
|
5979
6737
|
head.title = "\u62D6\u66F3\u8ABF\u6574\u6392\u5217";
|
|
5980
|
-
const box =
|
|
5981
|
-
const wrap =
|
|
5982
|
-
const iframe =
|
|
6738
|
+
const box = h10("div", "ez-screen");
|
|
6739
|
+
const wrap = h10("div", "ez-frame-wrap");
|
|
6740
|
+
const iframe = h10("iframe", "ez-frame");
|
|
5983
6741
|
iframe.src = nav.url;
|
|
5984
6742
|
wrap.appendChild(iframe);
|
|
5985
6743
|
box.appendChild(wrap);
|
|
@@ -6095,10 +6853,8 @@
|
|
|
6095
6853
|
}
|
|
6096
6854
|
function stageApp(app) {
|
|
6097
6855
|
if (app === stagedApp) return;
|
|
6098
|
-
const presumed = stagedApp === void 0;
|
|
6099
6856
|
stagedApp = app;
|
|
6100
6857
|
deviceRow.hidden = app === null || !!canvasUi && canvasUi.activeTab !== "app";
|
|
6101
|
-
if (presumed && app !== null) return;
|
|
6102
6858
|
rebuildStage();
|
|
6103
6859
|
}
|
|
6104
6860
|
function rebuildStage() {
|
|
@@ -6127,33 +6883,24 @@
|
|
|
6127
6883
|
paintAnnotateMode();
|
|
6128
6884
|
paintStageClasses();
|
|
6129
6885
|
rebuildStage();
|
|
6130
|
-
var sidebar =
|
|
6131
|
-
var queueSection =
|
|
6132
|
-
var queueList =
|
|
6133
|
-
var queueScroll =
|
|
6886
|
+
var sidebar = h10("aside", "ez-sidebar");
|
|
6887
|
+
var queueSection = h10("section", "ez-section ez-queue-section");
|
|
6888
|
+
var queueList = h10("ul", "ez-queue");
|
|
6889
|
+
var queueScroll = h10("div", "ez-fade ez-queue-scroll");
|
|
6134
6890
|
queueScroll.appendChild(queueList);
|
|
6135
|
-
var sendBtn =
|
|
6136
|
-
var sendLabel =
|
|
6891
|
+
var sendBtn = h10("button", "ez-send");
|
|
6892
|
+
var sendLabel = h10("span", void 0, "\u9001\u51FA\u7D66 agent");
|
|
6137
6893
|
sendBtn.title = "\u9001\u51FA\u7D66 agent\uFF08\u2318/Ctrl + Enter\uFF09";
|
|
6138
6894
|
sendBtn.append(icon(Navigation03Icon, 15), sendLabel);
|
|
6139
6895
|
sendBtn.onclick = () => void sendBatch();
|
|
6140
6896
|
var noteAttach = attachify({
|
|
6141
6897
|
attachments: shellAttachments,
|
|
6142
|
-
mk:
|
|
6898
|
+
mk: h10,
|
|
6143
6899
|
className: "ez-note",
|
|
6144
6900
|
placeholder: "\u6574\u9AD4\u60F3\u6CD5\u6216\u88DC\u5145\u8AAA\u660E\uFF0C\u8F38\u5165 / \u7528\u6307\u4EE4\uFF08\u9078\u586B\uFF09",
|
|
6145
6901
|
onChange: () => paintSendState(),
|
|
6146
6902
|
commands: [
|
|
6147
|
-
|
|
6148
|
-
id: "element",
|
|
6149
|
-
label: "Element",
|
|
6150
|
-
hint: "\u9078\u53D6\u9801\u9762\u5143\u7D20\u6216\u7BC4\u570D",
|
|
6151
|
-
keywords: ["element", "pick", "ref", "reference", "\u5143\u7D20", "\u6307\u5B9A", "\u53C3\u8003", "\u6846\u9078"],
|
|
6152
|
-
icon: AlignSelectionIcon,
|
|
6153
|
-
// The pointer is in the other document, so this can only ask. The answer
|
|
6154
|
-
// comes back as a message and lands here via the pick reducer.
|
|
6155
|
-
run: () => startPick("note")
|
|
6156
|
-
},
|
|
6903
|
+
elementCommand(() => noteAttach),
|
|
6157
6904
|
{
|
|
6158
6905
|
id: "new",
|
|
6159
6906
|
label: "New chat",
|
|
@@ -6177,6 +6924,17 @@
|
|
|
6177
6924
|
// while this review has only ever had the one conversation.
|
|
6178
6925
|
enabled: () => !!snapshot?.acp && (snapshot.chats?.length ?? 0) > 1,
|
|
6179
6926
|
run: () => void openResume()
|
|
6927
|
+
},
|
|
6928
|
+
{
|
|
6929
|
+
id: "skills",
|
|
6930
|
+
label: "Skills",
|
|
6931
|
+
hint: "\u8F38\u5165 $ \u4F7F\u7528 skill",
|
|
6932
|
+
keywords: ["skill", "skills", "$", "\u6280\u80FD"],
|
|
6933
|
+
icon: DollarSquareIcon,
|
|
6934
|
+
// Skills have their own menu, behind `$`: this one row is how a user who
|
|
6935
|
+
// only knows `/` finds it. Typed rather than inserted, so it opens there.
|
|
6936
|
+
enabled: () => !!snapshot?.acp,
|
|
6937
|
+
run: () => document.execCommand("insertText", false, "$")
|
|
6180
6938
|
}
|
|
6181
6939
|
],
|
|
6182
6940
|
skills: () => fetchSkills(),
|
|
@@ -6184,50 +6942,61 @@
|
|
|
6184
6942
|
});
|
|
6185
6943
|
var note = noteAttach.editable;
|
|
6186
6944
|
note.title = "\u5BEB\u88DC\u5145\u8AAA\u660E\uFF08N\uFF09";
|
|
6187
|
-
var
|
|
6945
|
+
var pickComposer = noteAttach;
|
|
6946
|
+
function elementCommand(into) {
|
|
6947
|
+
return {
|
|
6948
|
+
id: "element",
|
|
6949
|
+
label: "Element",
|
|
6950
|
+
hint: "\u9078\u53D6\u9801\u9762\u5143\u7D20\u6216\u7BC4\u570D",
|
|
6951
|
+
keywords: ["element", "pick", "ref", "reference", "\u5143\u7D20", "\u6307\u5B9A", "\u53C3\u8003", "\u6846\u9078"],
|
|
6952
|
+
icon: AlignSelectionIcon,
|
|
6953
|
+
run: () => startPick(into())
|
|
6954
|
+
};
|
|
6955
|
+
}
|
|
6956
|
+
var configPill = h10("button", "ez-config-pill");
|
|
6188
6957
|
configPill.setAttribute("aria-haspopup", "menu");
|
|
6189
6958
|
configPill.setAttribute("aria-expanded", "false");
|
|
6190
|
-
var configMenu =
|
|
6959
|
+
var configMenu = h10("div", "ez-menu ez-menu-up");
|
|
6191
6960
|
configMenu.setAttribute("role", "menu");
|
|
6192
|
-
var configWrap =
|
|
6961
|
+
var configWrap = h10("div", "ez-config");
|
|
6193
6962
|
configWrap.hidden = true;
|
|
6194
6963
|
configWrap.append(configPill, configMenu);
|
|
6195
|
-
var limitPill =
|
|
6964
|
+
var limitPill = h10("button", "ez-limit");
|
|
6196
6965
|
limitPill.type = "button";
|
|
6197
6966
|
limitPill.setAttribute("aria-describedby", "ez-usage-card");
|
|
6198
|
-
var limitCard =
|
|
6967
|
+
var limitCard = h10("div", "ez-usage-card");
|
|
6199
6968
|
limitCard.id = "ez-usage-card";
|
|
6200
6969
|
limitCard.setAttribute("role", "tooltip");
|
|
6201
|
-
var limitWrap =
|
|
6970
|
+
var limitWrap = h10("div", "ez-usage");
|
|
6202
6971
|
limitWrap.hidden = true;
|
|
6203
6972
|
limitWrap.append(limitPill, limitCard);
|
|
6204
|
-
var confirmTitle =
|
|
6205
|
-
var confirmBody =
|
|
6206
|
-
var confirmSkip =
|
|
6973
|
+
var confirmTitle = h10("div", "ez-notice-title");
|
|
6974
|
+
var confirmBody = h10("div", "ez-notice-body");
|
|
6975
|
+
var confirmSkip = h10("input");
|
|
6207
6976
|
confirmSkip.type = "checkbox";
|
|
6208
6977
|
confirmSkip.id = "ez-confirm-skip";
|
|
6209
|
-
var confirmSkipLabel =
|
|
6978
|
+
var confirmSkipLabel = h10("label", "ez-notice-skip");
|
|
6210
6979
|
confirmSkipLabel.htmlFor = confirmSkip.id;
|
|
6211
|
-
confirmSkipLabel.append(confirmSkip,
|
|
6212
|
-
var confirmGo =
|
|
6213
|
-
var confirmNo =
|
|
6214
|
-
var confirmActions =
|
|
6980
|
+
confirmSkipLabel.append(confirmSkip, h10("span", "", "\u4EE5\u5F8C\u4E0D\u518D\u63D0\u9192"));
|
|
6981
|
+
var confirmGo = h10("button", "ez-notice-go");
|
|
6982
|
+
var confirmNo = h10("button", "ez-notice-no", "\u53D6\u6D88");
|
|
6983
|
+
var confirmActions = h10("div", "ez-notice-actions");
|
|
6215
6984
|
confirmActions.append(confirmGo, confirmNo);
|
|
6216
|
-
var confirmCard =
|
|
6985
|
+
var confirmCard = h10("section", "ez-notice ez-confirm");
|
|
6217
6986
|
confirmCard.hidden = true;
|
|
6218
6987
|
confirmCard.dataset.testid = "ez-confirm";
|
|
6219
6988
|
confirmCard.setAttribute("role", "dialog");
|
|
6220
6989
|
confirmTitle.id = "ez-confirm-title";
|
|
6221
6990
|
confirmCard.setAttribute("aria-labelledby", confirmTitle.id);
|
|
6222
6991
|
confirmCard.append(confirmTitle, confirmBody, confirmActions, confirmSkipLabel);
|
|
6223
|
-
var resumeTitle =
|
|
6224
|
-
var resumeList =
|
|
6992
|
+
var resumeTitle = h10("div", "ez-notice-title", "\u56DE\u5230\u4E4B\u524D\u7684\u5C0D\u8A71");
|
|
6993
|
+
var resumeList = h10("div", "ez-notice-list");
|
|
6225
6994
|
resumeList.setAttribute("role", "menu");
|
|
6226
|
-
var resumeClose =
|
|
6995
|
+
var resumeClose = h10("button", "ez-notice-x");
|
|
6227
6996
|
resumeClose.title = "\u95DC\u9589";
|
|
6228
6997
|
resumeClose.setAttribute("aria-label", "\u95DC\u9589");
|
|
6229
6998
|
resumeClose.append(icon(Cancel01Icon, 13));
|
|
6230
|
-
var resumeCard =
|
|
6999
|
+
var resumeCard = h10("section", "ez-notice ez-resume");
|
|
6231
7000
|
resumeCard.hidden = true;
|
|
6232
7001
|
resumeCard.append(resumeClose, resumeTitle, resumeList);
|
|
6233
7002
|
var resumeRows = [];
|
|
@@ -6248,14 +7017,14 @@
|
|
|
6248
7017
|
const { chats } = await res.json();
|
|
6249
7018
|
resumeList.textContent = "";
|
|
6250
7019
|
resumeRows = chats.map((chat) => {
|
|
6251
|
-
const row =
|
|
7020
|
+
const row = h10("button", "ez-notice-row");
|
|
6252
7021
|
row.setAttribute("role", "menuitemradio");
|
|
6253
7022
|
row.setAttribute("aria-checked", String(chat.current));
|
|
6254
7023
|
if (chat.current) row.dataset.current = "";
|
|
6255
7024
|
row.append(
|
|
6256
7025
|
icon(ArrowRight02Icon, 12),
|
|
6257
|
-
|
|
6258
|
-
|
|
7026
|
+
h10("span", "ez-notice-row-name", chat.title || chatTime(chat.startedAt)),
|
|
7027
|
+
h10("span", "ez-notice-row-when", chat.title ? chatTime(chat.startedAt) : "")
|
|
6259
7028
|
);
|
|
6260
7029
|
row.addEventListener("pointerenter", () => pointAtResumeRow(row));
|
|
6261
7030
|
row.addEventListener("focus", () => pointAtResumeRow(row));
|
|
@@ -6278,7 +7047,7 @@
|
|
|
6278
7047
|
}
|
|
6279
7048
|
};
|
|
6280
7049
|
resumeClose.onclick = () => closeResume();
|
|
6281
|
-
var notices =
|
|
7050
|
+
var notices = h10("div", "ez-notices");
|
|
6282
7051
|
notices.append(updateCard, resumeCard, confirmCard);
|
|
6283
7052
|
var answerConfirm = null;
|
|
6284
7053
|
function closeConfirm(ok, offer) {
|
|
@@ -6314,20 +7083,20 @@
|
|
|
6314
7083
|
answerConfirm = resolve;
|
|
6315
7084
|
});
|
|
6316
7085
|
}
|
|
6317
|
-
var harnessBtn =
|
|
7086
|
+
var harnessBtn = h10("button", "ez-harness");
|
|
6318
7087
|
harnessBtn.type = "button";
|
|
6319
7088
|
harnessBtn.setAttribute("role", "switch");
|
|
6320
7089
|
harnessBtn.setAttribute("aria-checked", "false");
|
|
6321
7090
|
var HARNESS_HINT = "\u5BE6\u9A57\u6027\u529F\u80FD\uFF1A\u958B\u555F\u5F8C\uFF0Cagent \u6703\u5148\u4E86\u89E3\u4F60\u7684\u7522\u54C1\u3001\u6574\u7406\u51FA\u8A2D\u8A08\u898F\u7BC4\uFF0C\u4E4B\u5F8C\u90FD\u7167\u898F\u7BC4\u8A2D\u8A08";
|
|
6322
7091
|
var RUNNING_HINT = "agent \u6B63\u5728\u57F7\u884C\uFF0C\u9019\u4E00\u8F2A\u7D50\u675F\u5F8C\u624D\u80FD\u8ABF\u6574";
|
|
6323
7092
|
harnessBtn.title = HARNESS_HINT;
|
|
6324
|
-
var harnessMark =
|
|
7093
|
+
var harnessMark = h10("span", "ez-harness-mark");
|
|
6325
7094
|
harnessMark.append(icon(SparklesIcon, 12));
|
|
6326
7095
|
harnessBtn.append(
|
|
6327
7096
|
harnessMark,
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
7097
|
+
h10("span", "ez-harness-label", "\u589E\u5F37\u8A2D\u8A08"),
|
|
7098
|
+
h10("span", "ez-switch"),
|
|
7099
|
+
h10("span", "ez-harness-tag", "\u5BE6\u9A57")
|
|
6331
7100
|
);
|
|
6332
7101
|
harnessBtn.onclick = () => void toggleHarness();
|
|
6333
7102
|
var EFFORTS = [
|
|
@@ -6335,21 +7104,21 @@
|
|
|
6335
7104
|
{ level: "medium", label: "\u4E2D", hint: "\u4E2D\uFF1A\u5B8C\u6574\u8A2D\u8A08\u6D41\u7A0B\uFF0C\u4F46\u4E0D\u53E6\u5916\u8ACB\u4EBA\u6AA2\u67E5" },
|
|
6336
7105
|
{ level: "high", label: "\u9AD8", hint: "\u9AD8\uFF1A\u5B8C\u6574\u8A2D\u8A08\u6D41\u7A0B\uFF0C\u6700\u5F8C\u518D\u7368\u7ACB\u6AA2\u67E5\u4E00\u6B21" }
|
|
6337
7106
|
];
|
|
6338
|
-
var effortGroup =
|
|
7107
|
+
var effortGroup = h10("label", "ez-effort");
|
|
6339
7108
|
effortGroup.hidden = true;
|
|
6340
|
-
var effortTrack =
|
|
7109
|
+
var effortTrack = h10("span", "ez-effort-track");
|
|
6341
7110
|
effortTrack.setAttribute("aria-hidden", "true");
|
|
6342
|
-
effortTrack.append(
|
|
6343
|
-
var effortSlider =
|
|
7111
|
+
effortTrack.append(h10("span", "ez-effort-fill"), h10("span", "ez-effort-thumb"));
|
|
7112
|
+
var effortSlider = h10("input", "ez-effort-input");
|
|
6344
7113
|
effortSlider.type = "range";
|
|
6345
7114
|
effortSlider.min = "0";
|
|
6346
7115
|
effortSlider.max = String(EFFORTS.length - 1);
|
|
6347
7116
|
effortSlider.step = "1";
|
|
6348
7117
|
effortSlider.setAttribute("aria-label", "\u8A2D\u8A08\u529B\u5EA6");
|
|
6349
|
-
var effortValue =
|
|
6350
|
-
var effortControl =
|
|
7118
|
+
var effortValue = h10("span", "ez-effort-value");
|
|
7119
|
+
var effortControl = h10("span", "ez-effort-slider");
|
|
6351
7120
|
effortControl.append(effortTrack, effortSlider);
|
|
6352
|
-
effortGroup.append(
|
|
7121
|
+
effortGroup.append(h10("span", "ez-effort-label", "\u529B\u5EA6"), effortControl, effortValue);
|
|
6353
7122
|
function showEffort(at2) {
|
|
6354
7123
|
const effort = EFFORTS[at2];
|
|
6355
7124
|
effortSlider.value = String(at2);
|
|
@@ -6418,16 +7187,16 @@
|
|
|
6418
7187
|
var effortHeld = false;
|
|
6419
7188
|
effortSlider.onpointerdown = () => effortHeld = true;
|
|
6420
7189
|
window.addEventListener("pointerup", () => effortHeld = false);
|
|
6421
|
-
var controlRow =
|
|
7190
|
+
var controlRow = h10("div", "ez-control-row");
|
|
6422
7191
|
controlRow.hidden = true;
|
|
6423
7192
|
controlRow.append(agentWrap, configWrap, limitWrap);
|
|
6424
|
-
var harnessRow =
|
|
7193
|
+
var harnessRow = h10("div", "ez-harness-row");
|
|
6425
7194
|
harnessRow.hidden = true;
|
|
6426
7195
|
harnessRow.append(harnessBtn, effortGroup);
|
|
6427
7196
|
queueSection.append(queueScroll, harnessRow, controlRow, noteAttach.wrap, sendBtn);
|
|
6428
7197
|
var editAttach = attachify({
|
|
6429
7198
|
attachments: shellAttachments,
|
|
6430
|
-
mk:
|
|
7199
|
+
mk: h10,
|
|
6431
7200
|
className: "ez-qi-input",
|
|
6432
7201
|
// Worded as the page popup's, which asks the same question of the same kind of
|
|
6433
7202
|
// text, and puts the keys in the field rather than on a line of their own.
|
|
@@ -6437,7 +7206,9 @@
|
|
|
6437
7206
|
onChange: () => {
|
|
6438
7207
|
paintEditState();
|
|
6439
7208
|
capQueue();
|
|
6440
|
-
}
|
|
7209
|
+
},
|
|
7210
|
+
commands: [elementCommand(() => editAttach)],
|
|
7211
|
+
chooseLibrary: () => chooseLibraryAttachments(API)
|
|
6441
7212
|
});
|
|
6442
7213
|
editAttach.wrap.addEventListener(
|
|
6443
7214
|
"keydown",
|
|
@@ -6456,12 +7227,12 @@
|
|
|
6456
7227
|
},
|
|
6457
7228
|
true
|
|
6458
7229
|
);
|
|
6459
|
-
var forkBar =
|
|
7230
|
+
var forkBar = h10("nav", "ez-fork-bar");
|
|
6460
7231
|
forkBar.hidden = true;
|
|
6461
7232
|
forkBar.setAttribute("aria-label", "\u76EE\u524D\u7684\u5C0D\u8A71\u4F4D\u7F6E");
|
|
6462
|
-
var forkRoot =
|
|
6463
|
-
var forkChip =
|
|
6464
|
-
var forkName =
|
|
7233
|
+
var forkRoot = h10("button", "ez-fork-root");
|
|
7234
|
+
var forkChip = h10("button", "ez-fork-here");
|
|
7235
|
+
var forkName = h10("span", "ez-fork-name");
|
|
6465
7236
|
forkChip.append(icon(MagicWand01Icon, 13), forkName);
|
|
6466
7237
|
function rootOf(chat, chats) {
|
|
6467
7238
|
let at2 = chat;
|
|
@@ -6486,7 +7257,7 @@
|
|
|
6486
7257
|
return all.filter((c) => c.parentChatId && (here ? c.parentChatId === here.id : false));
|
|
6487
7258
|
}
|
|
6488
7259
|
function branchPicker(trigger, menuClass) {
|
|
6489
|
-
const menu =
|
|
7260
|
+
const menu = h10("div", `ez-menu ${menuClass}`);
|
|
6490
7261
|
menu.setAttribute("role", "menu");
|
|
6491
7262
|
menu.setAttribute("aria-label", "\u5207\u63DB\u5230\u67D0\u500B\u5C0D\u8A71");
|
|
6492
7263
|
menu.hidden = true;
|
|
@@ -6504,14 +7275,14 @@
|
|
|
6504
7275
|
function show() {
|
|
6505
7276
|
menu.textContent = "";
|
|
6506
7277
|
rows = branchesOf(snapshot).map((chat) => {
|
|
6507
|
-
const row =
|
|
7278
|
+
const row = h10("button", "ez-notice-row ez-fork-row");
|
|
6508
7279
|
row.setAttribute("role", "menuitemradio");
|
|
6509
7280
|
row.setAttribute("aria-checked", String(chat.current));
|
|
6510
7281
|
if (chat.current) row.dataset.current = "";
|
|
6511
7282
|
row.append(
|
|
6512
7283
|
icon(ArrowRight02Icon, 12),
|
|
6513
|
-
|
|
6514
|
-
|
|
7284
|
+
h10("span", "ez-notice-row-name", chatName(chat, false)),
|
|
7285
|
+
h10("span", "ez-notice-row-when", chatDetail(chat))
|
|
6515
7286
|
);
|
|
6516
7287
|
row.addEventListener("pointerenter", () => pointAt(row));
|
|
6517
7288
|
row.addEventListener("focus", () => pointAt(row));
|
|
@@ -6555,8 +7326,8 @@
|
|
|
6555
7326
|
forkChip.disabled = true;
|
|
6556
7327
|
forkChip.setAttribute("aria-current", "page");
|
|
6557
7328
|
}
|
|
6558
|
-
var forkMore =
|
|
6559
|
-
forkMore.append(
|
|
7329
|
+
var forkMore = h10("button", "ez-fork-more");
|
|
7330
|
+
forkMore.append(h10("span", void 0, "\u5206\u652F\u5C0D\u8A71"), icon(ChevronDownIcon, 12));
|
|
6560
7331
|
forkMore.title = "\u9019\u689D\u4E3B\u7DDA\u5E95\u4E0B\u7684\u5206\u652F\u5C0D\u8A71";
|
|
6561
7332
|
var morePicker = BRANCHES_REACHABLE ? branchPicker(forkMore, "ez-fork-more-menu") : null;
|
|
6562
7333
|
async function leaveBranch(toChatId) {
|
|
@@ -6626,17 +7397,17 @@
|
|
|
6626
7397
|
void convScroll.offsetWidth;
|
|
6627
7398
|
convScroll.dataset.enter = deeper ? "deeper" : back ? "back" : "swap";
|
|
6628
7399
|
}
|
|
6629
|
-
var convSection =
|
|
6630
|
-
var convList =
|
|
6631
|
-
var convScroll =
|
|
7400
|
+
var convSection = h10("section", "ez-section ez-conv-section");
|
|
7401
|
+
var convList = h10("div", "ez-conv");
|
|
7402
|
+
var convScroll = h10("div", "ez-fade ez-conv-scroll");
|
|
6632
7403
|
convScroll.appendChild(convList);
|
|
6633
|
-
var forkSep =
|
|
7404
|
+
var forkSep = h10("span", "ez-fork-sep");
|
|
6634
7405
|
forkSep.append(icon(ChevronRightIcon, 10));
|
|
6635
7406
|
forkBar.append(forkRoot, forkSep, forkChip);
|
|
6636
7407
|
if (forkPicker) forkBar.append(forkPicker.menu);
|
|
6637
7408
|
if (morePicker) forkBar.append(forkMore, morePicker.menu);
|
|
6638
7409
|
convSection.append(forkBar, convScroll, notices);
|
|
6639
|
-
var resizer =
|
|
7410
|
+
var resizer = h10("div", "ez-resizer");
|
|
6640
7411
|
resizer.tabIndex = 0;
|
|
6641
7412
|
resizer.setAttribute("role", "separator");
|
|
6642
7413
|
resizer.setAttribute("aria-orientation", "vertical");
|
|
@@ -6644,17 +7415,17 @@
|
|
|
6644
7415
|
resizer.setAttribute("aria-label", "\u8ABF\u6574\u5074\u908A\u6B04\u5BEC\u5EA6");
|
|
6645
7416
|
resizer.title = "\u62D6\u66F3\u8ABF\u6574\u5BEC\u5EA6\uFF0C\u62D6\u5230\u5E95\u6536\u8D77\uFF0C\u96D9\u64CA\u9084\u539F";
|
|
6646
7417
|
sidebar.append(sideHead, convSection, queueSection);
|
|
6647
|
-
var sidebarSlot =
|
|
7418
|
+
var sidebarSlot = h10("div", "ez-sidebar-slot");
|
|
6648
7419
|
sidebarSlot.append(sidebar);
|
|
6649
|
-
var activityBar =
|
|
7420
|
+
var activityBar = h10("nav", "ez-activity");
|
|
6650
7421
|
activityBar.setAttribute("aria-label", "\u5074\u908A\u6B04");
|
|
6651
|
-
var reviewPanelBtn =
|
|
7422
|
+
var reviewPanelBtn = h10("button", "ez-activity-btn");
|
|
6652
7423
|
reviewPanelBtn.append(icon(BubbleChatIcon, 18));
|
|
6653
7424
|
reviewPanelBtn.onclick = () => toggleSidebar();
|
|
6654
7425
|
var VIEW_PARAM = "view";
|
|
6655
7426
|
var LIBRARY_VIEW = "library";
|
|
6656
7427
|
var libraryInUrl = () => new URLSearchParams(location.search).get(VIEW_PARAM) === LIBRARY_VIEW;
|
|
6657
|
-
var libraryBtn =
|
|
7428
|
+
var libraryBtn = h10("button", "ez-activity-btn");
|
|
6658
7429
|
libraryBtn.setAttribute("aria-pressed", String(libraryInUrl()));
|
|
6659
7430
|
libraryBtn.dataset.testid = LIBRARY_TEST_IDS.open;
|
|
6660
7431
|
libraryBtn.setAttribute("aria-label", "\u7D20\u6750\u5EAB");
|
|
@@ -6722,7 +7493,7 @@
|
|
|
6722
7493
|
function gridMetrics() {
|
|
6723
7494
|
return { gap: GRID_GAP, rowGap: GRID_ROW_GAP, head: cardHead() };
|
|
6724
7495
|
}
|
|
6725
|
-
var dropHint =
|
|
7496
|
+
var dropHint = h10("div", "ez-drop-hint");
|
|
6726
7497
|
var DRAG_SLOP = 4;
|
|
6727
7498
|
var ROW_SNAP = 30;
|
|
6728
7499
|
var PAN_EDGE = 44;
|
|
@@ -6985,7 +7756,7 @@
|
|
|
6985
7756
|
paintVeil();
|
|
6986
7757
|
paintPickPill();
|
|
6987
7758
|
if (was && !pickState && !out.effects.some((x) => x.do === "insert-note")) {
|
|
6988
|
-
|
|
7759
|
+
pickComposer.cancelRef();
|
|
6989
7760
|
paintSendState();
|
|
6990
7761
|
}
|
|
6991
7762
|
}
|
|
@@ -6998,7 +7769,7 @@
|
|
|
6998
7769
|
switch (effect.do) {
|
|
6999
7770
|
case "arm-overlay":
|
|
7000
7771
|
if (effect.host === "note") {
|
|
7001
|
-
|
|
7772
|
+
pickComposer.beginRef(PICKING_LABEL);
|
|
7002
7773
|
paintSendState();
|
|
7003
7774
|
}
|
|
7004
7775
|
for (const f of pickFrames(effect.frame)) {
|
|
@@ -7031,8 +7802,9 @@
|
|
|
7031
7802
|
for (const f of pickFrames(effect.frame)) if (f.kind === "app") navigateFrame(f, effect.page);
|
|
7032
7803
|
return;
|
|
7033
7804
|
case "insert-note":
|
|
7034
|
-
|
|
7035
|
-
focusNote();
|
|
7805
|
+
pickComposer.resolveRef(effect.ref);
|
|
7806
|
+
if (pickComposer === noteAttach) focusNote();
|
|
7807
|
+
else pickComposer.editable.focus();
|
|
7036
7808
|
paintSendState();
|
|
7037
7809
|
return;
|
|
7038
7810
|
case "banner":
|
|
@@ -7041,11 +7813,12 @@
|
|
|
7041
7813
|
return;
|
|
7042
7814
|
}
|
|
7043
7815
|
}
|
|
7044
|
-
function startPick(
|
|
7816
|
+
function startPick(into) {
|
|
7817
|
+
pickComposer = into;
|
|
7045
7818
|
dispatchPick({
|
|
7046
7819
|
t: "arm",
|
|
7047
7820
|
id: `s${++pickSeq}-${Date.now().toString(36)}`,
|
|
7048
|
-
host,
|
|
7821
|
+
host: "note",
|
|
7049
7822
|
now: Date.now()
|
|
7050
7823
|
});
|
|
7051
7824
|
}
|
|
@@ -7094,14 +7867,25 @@
|
|
|
7094
7867
|
...init
|
|
7095
7868
|
});
|
|
7096
7869
|
}
|
|
7870
|
+
function sidebarToggle(toggle) {
|
|
7871
|
+
const button2 = h10("button", "ez-sidebar-toggle");
|
|
7872
|
+
button2.type = "button";
|
|
7873
|
+
button2.title = "\u5C55\u958B\u5074\u908A\u6B04\uFF08\u2303\u2318S\uFF09";
|
|
7874
|
+
button2.setAttribute("aria-label", button2.title);
|
|
7875
|
+
button2.append(icon(SidebarLeftIcon, 16));
|
|
7876
|
+
button2.onclick = () => toggle();
|
|
7877
|
+
return button2;
|
|
7878
|
+
}
|
|
7097
7879
|
function canvasPorts() {
|
|
7098
7880
|
return {
|
|
7099
7881
|
guests: frames,
|
|
7100
7882
|
stageWrap,
|
|
7883
|
+
...host.kind === "desktop" ? { tabsLead: sidebarToggle(host.toggleSidebar) } : {},
|
|
7101
7884
|
stage,
|
|
7102
7885
|
api,
|
|
7103
7886
|
onTabShown: (tab) => {
|
|
7104
7887
|
deviceRow.hidden = stagedApp === null || tab !== "app";
|
|
7888
|
+
paintDevServer();
|
|
7105
7889
|
if (tab === "app") paintFrames();
|
|
7106
7890
|
paintPage();
|
|
7107
7891
|
paintPickPill();
|
|
@@ -7120,6 +7904,46 @@
|
|
|
7120
7904
|
function paintSendState() {
|
|
7121
7905
|
sendBtn.disabled = !canSend();
|
|
7122
7906
|
}
|
|
7907
|
+
var sendWhenReady = false;
|
|
7908
|
+
function setSendWhenReady(on) {
|
|
7909
|
+
sendWhenReady = on;
|
|
7910
|
+
sendBtn.classList.toggle("ez-send-waiting", on);
|
|
7911
|
+
sendBtn.setAttribute("aria-busy", String(on));
|
|
7912
|
+
sendBtn.title = on ? "\u5F71\u7247\u8655\u7406\u5B8C\u5C31\u6703\u9001\u51FA\uFF08\u518D\u6309\u4E00\u6B21\u53D6\u6D88\uFF09" : "\u9001\u51FA\u7D66 agent\uFF08\u2318/Ctrl + Enter\uFF09";
|
|
7913
|
+
}
|
|
7914
|
+
function videosHoldSend() {
|
|
7915
|
+
const pending = new Set(snapshot?.pendingVideos ?? []);
|
|
7916
|
+
if (!pending.size) return false;
|
|
7917
|
+
const queued = snapshot?.annotations.flatMap((a) => a.attachments?.map((f) => f.id) ?? []) ?? [];
|
|
7918
|
+
return [...noteAttach.ids(), ...editAttach.ids(), ...queued].some((id) => pending.has(id));
|
|
7919
|
+
}
|
|
7920
|
+
var VIDEO_UNREADABLE = {
|
|
7921
|
+
"unsupported-browser": "\u9019\u500B\u700F\u89BD\u5668\u7121\u6CD5\u89E3\u78BC\u5F71\u7247",
|
|
7922
|
+
"unsupported-codec": "\u700F\u89BD\u5668\u4E0D\u652F\u63F4\u9019\u6BB5\u5F71\u7247\u7684\u7DE8\u78BC",
|
|
7923
|
+
unreadable: "\u8B80\u4E0D\u51FA\u5F71\u7247\u5167\u5BB9",
|
|
7924
|
+
crashed: "\u64F7\u53D6\u756B\u9762\u6642\u4E2D\u65B7"
|
|
7925
|
+
};
|
|
7926
|
+
var videoLines = /* @__PURE__ */ new Map();
|
|
7927
|
+
var progressOf = (ids) => `${Math.round(ids.reduce((sum, id) => sum + digests.progress(id), 0) / ids.length * 100)}%`;
|
|
7928
|
+
function paintVideos() {
|
|
7929
|
+
const pending = new Set(snapshot?.pendingVideos ?? []);
|
|
7930
|
+
const noteFor = (ids) => {
|
|
7931
|
+
const waiting = ids.filter((id) => pending.has(id));
|
|
7932
|
+
return waiting.length ? `\u8655\u7406\u4E2D ${progressOf(waiting)}` : null;
|
|
7933
|
+
};
|
|
7934
|
+
noteAttach.paintNotes(noteFor);
|
|
7935
|
+
editAttach.paintNotes(noteFor);
|
|
7936
|
+
for (const [line, videos] of videoLines) {
|
|
7937
|
+
const failed = videos.find((f) => f.video?.state === "failed");
|
|
7938
|
+
const waiting = videos.filter((f) => pending.has(f.id)).map((f) => f.id);
|
|
7939
|
+
line.classList.toggle("ez-qi-video-failed", !waiting.length && !!failed);
|
|
7940
|
+
if (waiting.length) line.textContent = `\u5F71\u7247\u8655\u7406\u4E2D ${progressOf(waiting)}`;
|
|
7941
|
+
else if (failed?.video?.state === "failed") {
|
|
7942
|
+
line.textContent = `${failed.name}\uFF1A${VIDEO_UNREADABLE[failed.video.reason]}\uFF0Cagent \u770B\u4E0D\u5230\u756B\u9762`;
|
|
7943
|
+
} else line.textContent = "";
|
|
7944
|
+
}
|
|
7945
|
+
if (sendWhenReady && !videosHoldSend()) void sendBatch();
|
|
7946
|
+
}
|
|
7123
7947
|
var LIMIT_BEAT_MS = 12e4;
|
|
7124
7948
|
function refreshLimit() {
|
|
7125
7949
|
if (document.visibilityState !== "visible" || !snapshot?.acp) return;
|
|
@@ -7131,6 +7955,11 @@
|
|
|
7131
7955
|
setInterval(refreshLimit, LIMIT_BEAT_MS);
|
|
7132
7956
|
async function sendBatch() {
|
|
7133
7957
|
if (!canSend()) return;
|
|
7958
|
+
if (videosHoldSend()) {
|
|
7959
|
+
setSendWhenReady(!sendWhenReady);
|
|
7960
|
+
return;
|
|
7961
|
+
}
|
|
7962
|
+
setSendWhenReady(false);
|
|
7134
7963
|
const count = snapshot?.annotations.length ?? 0;
|
|
7135
7964
|
const attachments = noteAttach.ids();
|
|
7136
7965
|
const references = noteAttach.refs();
|
|
@@ -7183,6 +8012,7 @@
|
|
|
7183
8012
|
function closeEdit(reason) {
|
|
7184
8013
|
const at2 = editing;
|
|
7185
8014
|
if (!at2) return;
|
|
8015
|
+
if (pickState?.host === "note" && pickComposer === editAttach) abortPick("escape");
|
|
7186
8016
|
editing = null;
|
|
7187
8017
|
editSaving = false;
|
|
7188
8018
|
if (reason === "cancelled" || reason === "switched") {
|
|
@@ -7226,12 +8056,12 @@
|
|
|
7226
8056
|
}
|
|
7227
8057
|
function brandMark(brand2, size) {
|
|
7228
8058
|
if (!brand2) return [];
|
|
7229
|
-
const mark =
|
|
8059
|
+
const mark = h10("span", "ez-brand-mark");
|
|
7230
8060
|
mark.append(icon(brand2 === "claude" ? ClaudeIcon : ChatGptIcon, size));
|
|
7231
8061
|
return [mark];
|
|
7232
8062
|
}
|
|
7233
8063
|
function menuCheck() {
|
|
7234
|
-
const check =
|
|
8064
|
+
const check = h10("span", "ez-menu-check");
|
|
7235
8065
|
check.append(icon(CheckIcon, 14));
|
|
7236
8066
|
return check;
|
|
7237
8067
|
}
|
|
@@ -7292,6 +8122,7 @@
|
|
|
7292
8122
|
}
|
|
7293
8123
|
async function switchAgent(agent) {
|
|
7294
8124
|
closeAgentMenu();
|
|
8125
|
+
if (!snapshot?.acp) return void connectAgent(agent);
|
|
7295
8126
|
if (agent.id === runningAgentId()) return;
|
|
7296
8127
|
const ok = await askConfirm({
|
|
7297
8128
|
// Keyed on the act, not on which agent: the reason is the same whichever
|
|
@@ -7302,37 +8133,63 @@
|
|
|
7302
8133
|
go: `\u6539\u7528 ${agent.name}`
|
|
7303
8134
|
});
|
|
7304
8135
|
if (!ok) return;
|
|
8136
|
+
await connectAgent(agent);
|
|
8137
|
+
}
|
|
8138
|
+
async function connectAgent(agent) {
|
|
7305
8139
|
await api("/acp/agent", {
|
|
7306
8140
|
method: "POST",
|
|
7307
|
-
body: JSON.stringify({ id: agent.id })
|
|
8141
|
+
body: JSON.stringify({ id: agent.id, host: host.kind })
|
|
7308
8142
|
});
|
|
7309
8143
|
}
|
|
8144
|
+
async function disconnectAgent() {
|
|
8145
|
+
closeAgentMenu();
|
|
8146
|
+
await api("/acp/disconnect", { method: "POST" });
|
|
8147
|
+
}
|
|
7310
8148
|
function paintAgents() {
|
|
7311
8149
|
const command = snapshot?.acp?.agent ?? "";
|
|
7312
8150
|
const runningId = runningAgentId();
|
|
7313
8151
|
const shown = agents.filter((a) => a.installed || a.id === runningId);
|
|
7314
|
-
const
|
|
8152
|
+
const connected = !!snapshot?.acp;
|
|
8153
|
+
const signature = JSON.stringify([shown, command, connected]);
|
|
7315
8154
|
if (signature === agentsDrawn) return;
|
|
7316
8155
|
agentsDrawn = signature;
|
|
7317
8156
|
agentPill.textContent = "";
|
|
8157
|
+
agentPill.toggleAttribute("data-offline", !connected);
|
|
7318
8158
|
agentPill.append(
|
|
7319
|
-
...brandMark(agentBrandFor(command), 14),
|
|
7320
|
-
|
|
8159
|
+
...connected ? brandMark(agentBrandFor(command), 14) : [icon(Plug01Icon, 14)],
|
|
8160
|
+
h10("span", "ez-agent-name", connected ? agentProfileFor(command)?.name ?? "Agent" : "\u9023\u7DDA Agent"),
|
|
7321
8161
|
icon(ChevronDownIcon, 12)
|
|
7322
8162
|
);
|
|
7323
8163
|
agentMenu.textContent = "";
|
|
8164
|
+
const choices = h10("div", "ez-menu-group");
|
|
8165
|
+
agentMenu.append(choices);
|
|
8166
|
+
if (!shown.length) {
|
|
8167
|
+
const none = h10("button", "ez-menu-item");
|
|
8168
|
+
none.disabled = true;
|
|
8169
|
+
none.append(h10("span", "ez-menu-name", "\u9019\u53F0\u96FB\u8166\u4E0A\u6C92\u6709\u53EF\u7528\u7684 agent"));
|
|
8170
|
+
choices.append(none);
|
|
8171
|
+
}
|
|
7324
8172
|
agentRows = shown.map((agent) => {
|
|
7325
8173
|
const on = agent.id === runningId;
|
|
7326
|
-
const row =
|
|
8174
|
+
const row = h10("button", "ez-menu-item");
|
|
7327
8175
|
row.setAttribute("role", "menuitemradio");
|
|
7328
8176
|
row.setAttribute("aria-checked", String(on));
|
|
7329
8177
|
if (on) row.dataset.current = "";
|
|
7330
8178
|
const brand2 = AGENT_PROFILES.find((p) => p.id === agent.id)?.brand;
|
|
7331
|
-
row.append(...brandMark(brand2, 15),
|
|
8179
|
+
row.append(...brandMark(brand2, 15), h10("span", "ez-menu-name", agent.name), menuCheck());
|
|
7332
8180
|
row.onclick = () => void switchAgent(agent);
|
|
7333
|
-
|
|
8181
|
+
choices.append(row);
|
|
7334
8182
|
return row;
|
|
7335
8183
|
});
|
|
8184
|
+
if (!connected) return;
|
|
8185
|
+
const off = h10("button", "ez-menu-item");
|
|
8186
|
+
off.setAttribute("role", "menuitem");
|
|
8187
|
+
off.append(icon(Plug01Icon, 15), h10("span", "ez-menu-name", "\u4E2D\u65B7\u9023\u7DDA"));
|
|
8188
|
+
off.onclick = () => void disconnectAgent();
|
|
8189
|
+
const offGroup = h10("div", "ez-menu-group");
|
|
8190
|
+
offGroup.append(off);
|
|
8191
|
+
agentMenu.append(offGroup);
|
|
8192
|
+
agentRows.push(off);
|
|
7336
8193
|
}
|
|
7337
8194
|
async function fetchSkills() {
|
|
7338
8195
|
if (!snapshot?.acp) return [];
|
|
@@ -7342,7 +8199,8 @@
|
|
|
7342
8199
|
return skills.map((skill) => ({
|
|
7343
8200
|
id: skill.name,
|
|
7344
8201
|
label: skill.name,
|
|
7345
|
-
keywords: [
|
|
8202
|
+
keywords: [],
|
|
8203
|
+
description: skill.description,
|
|
7346
8204
|
run: () => noteAttach.insertSkill(skill.name)
|
|
7347
8205
|
}));
|
|
7348
8206
|
}
|
|
@@ -7404,24 +8262,24 @@
|
|
|
7404
8262
|
if (!line) return;
|
|
7405
8263
|
limitPill.textContent = line;
|
|
7406
8264
|
const plan = planName(limit?.plan);
|
|
7407
|
-
const head =
|
|
7408
|
-
head.append(
|
|
7409
|
-
if (plan) head.append(
|
|
8265
|
+
const head = h10("div", "ez-usage-head");
|
|
8266
|
+
head.append(h10("span", "ez-usage-title", "\u7528\u91CF"));
|
|
8267
|
+
if (plan) head.append(h10("span", "ez-usage-plan", plan));
|
|
7410
8268
|
limitCard.replaceChildren(head);
|
|
7411
8269
|
for (const row of usageRows(limit)) {
|
|
7412
|
-
const top =
|
|
8270
|
+
const top = h10("div", "ez-usage-line");
|
|
7413
8271
|
top.append(
|
|
7414
|
-
|
|
7415
|
-
|
|
8272
|
+
h10("span", "ez-usage-label", row.label),
|
|
8273
|
+
h10("span", "ez-usage-left", `\u5269 ${row.percent}%`)
|
|
7416
8274
|
);
|
|
7417
|
-
const fill =
|
|
8275
|
+
const fill = h10("i");
|
|
7418
8276
|
fill.style.width = `${row.used}%`;
|
|
7419
|
-
const bar =
|
|
8277
|
+
const bar = h10("div", "ez-usage-bar");
|
|
7420
8278
|
bar.append(fill);
|
|
7421
|
-
const item =
|
|
8279
|
+
const item = h10("div", "ez-usage-row");
|
|
7422
8280
|
if (row.low) item.dataset.low = "";
|
|
7423
8281
|
item.append(top, bar);
|
|
7424
|
-
if (row.when) item.append(
|
|
8282
|
+
if (row.when) item.append(h10("div", "ez-usage-when", row.when));
|
|
7425
8283
|
limitCard.append(item);
|
|
7426
8284
|
}
|
|
7427
8285
|
}
|
|
@@ -7442,13 +8300,13 @@
|
|
|
7442
8300
|
const named = pillOption(options);
|
|
7443
8301
|
const label = named && named.type === "select" ? shortConfigValueName(configValueName(named, named.currentValue)) : named && configLabel(named) || "";
|
|
7444
8302
|
configPill.textContent = "";
|
|
7445
|
-
configPill.append(
|
|
8303
|
+
configPill.append(h10("span", "ez-config-name", label), icon(ChevronDownIcon, 12));
|
|
7446
8304
|
const full = named && named.type === "select" ? configValueName(named, named.currentValue) : "";
|
|
7447
8305
|
const detail = named && named.type === "select" ? configValues(named).find((o) => o.value === named.currentValue)?.description : void 0;
|
|
7448
8306
|
configPill.title = [named ? configLabel(named) : "", full, detail].filter(Boolean).join(" \xB7 ");
|
|
7449
8307
|
configMenu.textContent = "";
|
|
7450
8308
|
for (const option of [...options].sort(byCategory)) {
|
|
7451
|
-
const group =
|
|
8309
|
+
const group = h10("div", "ez-menu-group");
|
|
7452
8310
|
group.setAttribute("role", "group");
|
|
7453
8311
|
group.setAttribute("aria-label", configLabel(option));
|
|
7454
8312
|
if (option.type === "boolean") {
|
|
@@ -7456,7 +8314,7 @@
|
|
|
7456
8314
|
configRow(option, !option.currentValue, configLabel(option), option, option.currentValue)
|
|
7457
8315
|
);
|
|
7458
8316
|
} else {
|
|
7459
|
-
group.append(
|
|
8317
|
+
group.append(h10("div", "ez-menu-label", configLabel(option)));
|
|
7460
8318
|
for (const value of configValues(option)) {
|
|
7461
8319
|
group.append(
|
|
7462
8320
|
configRow(option, value.value, value.name, value, value.value === option.currentValue)
|
|
@@ -7470,11 +8328,11 @@
|
|
|
7470
8328
|
var HIDDEN_CATEGORIES = /* @__PURE__ */ new Set(["mode", "model_config"]);
|
|
7471
8329
|
var CATEGORY_ORDER = ["model", "thought_level"];
|
|
7472
8330
|
function byCategory(a, b) {
|
|
7473
|
-
const
|
|
8331
|
+
const rank2 = (o) => {
|
|
7474
8332
|
const at2 = CATEGORY_ORDER.indexOf(o.category ?? "");
|
|
7475
8333
|
return at2 === -1 ? CATEGORY_ORDER.length : at2;
|
|
7476
8334
|
};
|
|
7477
|
-
return
|
|
8335
|
+
return rank2(a) - rank2(b);
|
|
7478
8336
|
}
|
|
7479
8337
|
function resolvedName(option, value, name, describes) {
|
|
7480
8338
|
const resolved = describes.description;
|
|
@@ -7484,11 +8342,11 @@
|
|
|
7484
8342
|
return `${name.replace(/\s*\([^)]*\)\s*$/, "")} (${resolved.replace(/\s*\(([^)]*)\)/g, " \xB7 $1")})`;
|
|
7485
8343
|
}
|
|
7486
8344
|
function configRow(option, value, name, describes, on) {
|
|
7487
|
-
const row =
|
|
8345
|
+
const row = h10("button", "ez-menu-item");
|
|
7488
8346
|
row.setAttribute("role", option.type === "boolean" ? "menuitemcheckbox" : "menuitemradio");
|
|
7489
8347
|
row.setAttribute("aria-checked", String(on));
|
|
7490
8348
|
if (on) row.dataset.current = "";
|
|
7491
|
-
row.append(
|
|
8349
|
+
row.append(h10("span", "ez-menu-name", resolvedName(option, value, name, describes)), menuCheck());
|
|
7492
8350
|
if (describes.description) row.title = describes.description;
|
|
7493
8351
|
row.onclick = () => void setConfig(option.id, value);
|
|
7494
8352
|
return row;
|
|
@@ -7500,23 +8358,24 @@
|
|
|
7500
8358
|
if (signature === queueDrawn) return;
|
|
7501
8359
|
queueDrawn = signature;
|
|
7502
8360
|
queueList.textContent = "";
|
|
8361
|
+
videoLines.clear();
|
|
7503
8362
|
annotations.forEach((a, i) => {
|
|
7504
|
-
const li =
|
|
7505
|
-
const head =
|
|
7506
|
-
head.append(
|
|
8363
|
+
const li = h10("li", "ez-queue-item");
|
|
8364
|
+
const head = h10("div", "ez-qi-head");
|
|
8365
|
+
head.append(h10("span", "ez-qi-num", String(i + 1)), h10("span", "ez-qi-label", annotationLabel(a)));
|
|
7507
8366
|
const vp = a.anchor.viewport;
|
|
7508
8367
|
if (vp?.width && vp.preset !== "desktop") {
|
|
7509
|
-
head.append(
|
|
8368
|
+
head.append(h10("span", "ez-qi-vp", `${vp.width}px`));
|
|
7510
8369
|
}
|
|
7511
|
-
const acts =
|
|
8370
|
+
const acts = h10("div", "ez-qi-acts");
|
|
7512
8371
|
const open = editing?.id === a.id;
|
|
7513
|
-
const primary =
|
|
8372
|
+
const primary = h10("button", `ez-qi-act ${open ? "ez-qi-tick" : "ez-qi-edit"}`);
|
|
7514
8373
|
primary.append(
|
|
7515
8374
|
open ? icon(CheckIcon, TICK_ICON) : icon(Edit02Icon, EDIT_ICON)
|
|
7516
8375
|
);
|
|
7517
8376
|
primary.title = open ? `\u5132\u5B58\uFF08${MOD_LABEL}+Enter\uFF09` : "\u6539\u9019\u5247\u6A19\u8A3B\uFF08\u9001\u51FA\u524D\u90FD\u9084\u80FD\u6539\uFF09";
|
|
7518
8377
|
primary.onclick = open ? () => void saveEdit() : () => openEdit(a);
|
|
7519
|
-
const dismiss =
|
|
8378
|
+
const dismiss = h10("button", "ez-qi-act ez-qi-del");
|
|
7520
8379
|
dismiss.append(icon(Cancel01Icon, 13));
|
|
7521
8380
|
dismiss.title = open ? "\u53D6\u6D88\uFF08Esc\uFF09" : "\u79FB\u9664\u9019\u5247\u6A19\u8A3B";
|
|
7522
8381
|
dismiss.onclick = open ? () => closeEdit("cancelled") : () => void api(`/annotations/${a.id}`, { method: "DELETE" });
|
|
@@ -7540,6 +8399,12 @@
|
|
|
7540
8399
|
if (a.comment || a.references?.length || a.attachments?.length) li.append(row.box);
|
|
7541
8400
|
const files = fileChips(row.unplacedFiles);
|
|
7542
8401
|
if (files) li.append(files);
|
|
8402
|
+
const videos = a.attachments?.filter((f) => f.video && f.video.state !== "ready") ?? [];
|
|
8403
|
+
if (videos.length) {
|
|
8404
|
+
const line = h10("div", "ez-qi-video");
|
|
8405
|
+
videoLines.set(line, videos);
|
|
8406
|
+
li.append(line);
|
|
8407
|
+
}
|
|
7543
8408
|
queueList.appendChild(li);
|
|
7544
8409
|
});
|
|
7545
8410
|
capQueue();
|
|
@@ -7555,17 +8420,17 @@
|
|
|
7555
8420
|
return parts.join(" \xB7 ") || a.anchor.page || "";
|
|
7556
8421
|
}
|
|
7557
8422
|
function buildSaid(entry, isUser) {
|
|
7558
|
-
const said =
|
|
8423
|
+
const said = h10("div", isUser ? "ez-bubble" : "ez-said");
|
|
7559
8424
|
const items = entry.items ?? [];
|
|
7560
8425
|
if (items.length) {
|
|
7561
8426
|
const key = entry.batchId ?? String(entry.ts);
|
|
7562
8427
|
const expanded = expandedBatches.has(key);
|
|
7563
8428
|
const collapsed = items.length > ITEM_LIMIT + 1 && !expanded;
|
|
7564
8429
|
const shown = collapsed ? items.slice(0, ITEM_LIMIT) : items;
|
|
7565
|
-
const list =
|
|
8430
|
+
const list = h10("ol", "ez-bubble-list");
|
|
7566
8431
|
shown.forEach((item, i) => {
|
|
7567
|
-
const li =
|
|
7568
|
-
const body =
|
|
8432
|
+
const li = h10("li", "ez-bubble-item");
|
|
8433
|
+
const body = h10("div", "ez-bi-body");
|
|
7569
8434
|
const rendered = commentEl(
|
|
7570
8435
|
item.comment,
|
|
7571
8436
|
item.references,
|
|
@@ -7577,12 +8442,12 @@
|
|
|
7577
8442
|
if (rendered.box.childNodes.length) body.append(rendered.box);
|
|
7578
8443
|
const files = fileChips(rendered.unplacedFiles);
|
|
7579
8444
|
if (files) body.append(files);
|
|
7580
|
-
li.append(
|
|
8445
|
+
li.append(h10("span", "ez-bi-num", `${i + 1}.`), body);
|
|
7581
8446
|
list.appendChild(li);
|
|
7582
8447
|
});
|
|
7583
8448
|
said.appendChild(list);
|
|
7584
8449
|
if (collapsed) {
|
|
7585
|
-
const more =
|
|
8450
|
+
const more = h10("button", "ez-bubble-more", `\u9084\u6709 ${items.length - ITEM_LIMIT} \u5247`);
|
|
7586
8451
|
more.onclick = () => {
|
|
7587
8452
|
expandedBatches.add(key);
|
|
7588
8453
|
render();
|
|
@@ -7609,9 +8474,9 @@
|
|
|
7609
8474
|
return said;
|
|
7610
8475
|
}
|
|
7611
8476
|
function chipEl(name, glyph, kind, title) {
|
|
7612
|
-
const chip =
|
|
8477
|
+
const chip = h10("span", kind ? `ez-chip ez-chip-${kind}` : "ez-chip");
|
|
7613
8478
|
if (glyph) chip.append(icon(glyph, 11));
|
|
7614
|
-
chip.append(
|
|
8479
|
+
chip.append(h10("span", "ez-chip-name", name));
|
|
7615
8480
|
if (title) chip.title = title;
|
|
7616
8481
|
return chip;
|
|
7617
8482
|
}
|
|
@@ -7619,12 +8484,12 @@
|
|
|
7619
8484
|
var skillChipEl = (name) => chipEl(`$${name}`, null, "skill");
|
|
7620
8485
|
function fileChips(names) {
|
|
7621
8486
|
if (!names.length) return null;
|
|
7622
|
-
const row =
|
|
8487
|
+
const row = h10("div", "ez-file-chips");
|
|
7623
8488
|
for (const name of names) row.appendChild(chipEl(name, File02Icon));
|
|
7624
8489
|
return row;
|
|
7625
8490
|
}
|
|
7626
8491
|
function commentEl(text, refs, files, className, skills) {
|
|
7627
|
-
const box =
|
|
8492
|
+
const box = h10("div", className);
|
|
7628
8493
|
const numbered = new Map(
|
|
7629
8494
|
(refs ?? []).flatMap((r) => typeof r === "string" ? [] : [[r.n, r.label]])
|
|
7630
8495
|
);
|
|
@@ -7724,9 +8589,9 @@
|
|
|
7724
8589
|
function paintStatus() {
|
|
7725
8590
|
statusPill.toggleAttribute("data-alert", daemonGone);
|
|
7726
8591
|
if (daemonGone) {
|
|
7727
|
-
const how =
|
|
7728
|
-
how.append("\u5728\u5C08\u6848\u76EE\u9304\u57F7\u884C ",
|
|
7729
|
-
statusPill.replaceChildren(
|
|
8592
|
+
const how = h10("span");
|
|
8593
|
+
how.append("\u5728\u5C08\u6848\u76EE\u9304\u57F7\u884C ", h10("code", "ez-status-code", "npx -y @cychien/ezdesign@latest"), " \u91CD\u65B0\u555F\u52D5");
|
|
8594
|
+
statusPill.replaceChildren(h10("span", "ez-status-title", "ezdesign \u5DF2\u505C\u6B62\u904B\u4F5C"), how);
|
|
7730
8595
|
statusPill.hidden = false;
|
|
7731
8596
|
return;
|
|
7732
8597
|
}
|
|
@@ -7738,12 +8603,17 @@
|
|
|
7738
8603
|
const off = snapshot?.state === "ended" || daemonGone || stagedApp === null;
|
|
7739
8604
|
for (const { btn } of annotateBtns) btn.disabled = off;
|
|
7740
8605
|
}
|
|
8606
|
+
function paintDevServer() {
|
|
8607
|
+
if (!snapshot) return;
|
|
8608
|
+
devServerPanel.update(snapshot.devServer, { shown: stagedApp !== null, onAppTab: canvasUi?.activeTab === "app" });
|
|
8609
|
+
}
|
|
7741
8610
|
function render() {
|
|
7742
8611
|
if (!snapshot) return;
|
|
7743
8612
|
const s = snapshot;
|
|
7744
8613
|
stageApp(s.app ?? null);
|
|
7745
8614
|
canvasUi ?? (canvasUi = installCanvas(canvasPorts()));
|
|
7746
8615
|
canvasUi.render(s);
|
|
8616
|
+
paintDevServer();
|
|
7747
8617
|
paintPage();
|
|
7748
8618
|
const ended = s.state === "ended";
|
|
7749
8619
|
if (ended) abortPick("ended");
|
|
@@ -7763,10 +8633,10 @@
|
|
|
7763
8633
|
onBranch = !!s.chats?.find((c) => c.current)?.parentChatId;
|
|
7764
8634
|
paintVeil();
|
|
7765
8635
|
frames.postAll({ type: "ez:in-explore", on: onBranch });
|
|
7766
|
-
agentWrap.hidden = !s.acp;
|
|
8636
|
+
agentWrap.hidden = !s.acp && s.agentOnline;
|
|
7767
8637
|
paintHarness();
|
|
7768
8638
|
controlRow.hidden = agentWrap.hidden && configWrap.hidden;
|
|
7769
|
-
if (
|
|
8639
|
+
if (!agentWrap.hidden && !agents.length) void loadAgents();
|
|
7770
8640
|
paintAgents();
|
|
7771
8641
|
if (s.acp?.cancelling) {
|
|
7772
8642
|
agentStatus.className = "ez-badge ez-working";
|
|
@@ -7790,17 +8660,19 @@
|
|
|
7790
8660
|
agentStatus.title = s.acp?.state === "exited" && s.acp.error || "";
|
|
7791
8661
|
reviewPanelBtn.toggleAttribute("data-working", agentStatus.classList.contains("ez-working"));
|
|
7792
8662
|
paintQueue(s.annotations);
|
|
8663
|
+
digests.observe(s.pendingVideos ?? []);
|
|
8664
|
+
paintVideos();
|
|
7793
8665
|
convList.textContent = "";
|
|
7794
8666
|
let prevRole = null;
|
|
7795
8667
|
let livePlaced = false;
|
|
7796
8668
|
for (const entry of threadOrder(s.conversation)) {
|
|
7797
8669
|
if (entry.role === "system") {
|
|
7798
|
-
convList.appendChild(
|
|
8670
|
+
convList.appendChild(h10("div", "ez-msg-system", entry.text));
|
|
7799
8671
|
prevRole = null;
|
|
7800
8672
|
continue;
|
|
7801
8673
|
}
|
|
7802
8674
|
const grouped = entry.role === prevRole;
|
|
7803
|
-
const item =
|
|
8675
|
+
const item = h10("div", `ez-msg ez-msg-${entry.role}${grouped ? " ez-msg-cont" : ""}`);
|
|
7804
8676
|
const isUser = entry.role === "user";
|
|
7805
8677
|
item.append(buildSaid(entry, isUser));
|
|
7806
8678
|
convList.appendChild(item);
|
|
@@ -7821,28 +8693,28 @@
|
|
|
7821
8693
|
}
|
|
7822
8694
|
if (s.acp?.state === "exited" && s.acp.error) {
|
|
7823
8695
|
convList.appendChild(
|
|
7824
|
-
|
|
8696
|
+
h10("div", "ez-msg-system ez-msg-system-plain", `agent \u5DF2\u96E2\u7DDA\uFF1A${s.acp.error}`)
|
|
7825
8697
|
);
|
|
7826
8698
|
}
|
|
7827
8699
|
convList.scrollTop = convList.scrollHeight;
|
|
7828
8700
|
paintConvFades();
|
|
7829
8701
|
}
|
|
7830
8702
|
function liveTurnEl(s, prevRole) {
|
|
7831
|
-
const row =
|
|
7832
|
-
const dots =
|
|
8703
|
+
const row = h10("div", `ez-msg ez-msg-agent${prevRole === "agent" ? " ez-msg-cont" : ""}`);
|
|
8704
|
+
const dots = h10("div", "ez-thinking");
|
|
7833
8705
|
dots.setAttribute("role", "status");
|
|
7834
8706
|
const opening = s.acp?.state === "starting";
|
|
7835
8707
|
dots.setAttribute("aria-label", s.agentProgress ?? (opening ? "Agent \u6E96\u5099\u4E2D" : "Agent \u4FEE\u6539\u4E2D"));
|
|
7836
|
-
for (let i = 0; i < 3; i++) dots.appendChild(
|
|
7837
|
-
if (s.agentProgress) dots.appendChild(
|
|
7838
|
-
const turn =
|
|
8708
|
+
for (let i = 0; i < 3; i++) dots.appendChild(h10("span", "ez-dot"));
|
|
8709
|
+
if (s.agentProgress) dots.appendChild(h10("span", "ez-progress", s.agentProgress));
|
|
8710
|
+
const turn = h10("div", "ez-acp-turn");
|
|
7839
8711
|
if (s.acp && s.acp.state === "working") turn.append(acpFeedEl(s.acp));
|
|
7840
8712
|
turn.append(dots);
|
|
7841
8713
|
row.append(turn);
|
|
7842
8714
|
return row;
|
|
7843
8715
|
}
|
|
7844
8716
|
function acpFeedEl(acp) {
|
|
7845
|
-
const box =
|
|
8717
|
+
const box = h10("div", "ez-acp-feed");
|
|
7846
8718
|
const latest = acp.feed.at(-1);
|
|
7847
8719
|
for (const item of acp.feed) {
|
|
7848
8720
|
switch (item.kind) {
|
|
@@ -7850,18 +8722,18 @@
|
|
|
7850
8722
|
box.appendChild(markdownEl(item.text, "ez-md ez-acp-say"));
|
|
7851
8723
|
break;
|
|
7852
8724
|
case "thought":
|
|
7853
|
-
if (item === latest) box.appendChild(
|
|
8725
|
+
if (item === latest) box.appendChild(h10("div", "ez-acp-thought", item.text.slice(-160)));
|
|
7854
8726
|
break;
|
|
7855
8727
|
case "tool": {
|
|
7856
|
-
const line =
|
|
7857
|
-
line.append(
|
|
8728
|
+
const line = h10("div", `ez-acp-tool ez-acp-tool-${item.status}`);
|
|
8729
|
+
line.append(h10("span", "ez-acp-dot"), h10("span", "ez-acp-text", item.title));
|
|
7858
8730
|
box.appendChild(line);
|
|
7859
8731
|
break;
|
|
7860
8732
|
}
|
|
7861
8733
|
case "plan":
|
|
7862
8734
|
for (const entry of item.entries) {
|
|
7863
|
-
const line =
|
|
7864
|
-
line.append(
|
|
8735
|
+
const line = h10("div", `ez-acp-plan ez-acp-plan-${entry.status}`);
|
|
8736
|
+
line.append(h10("span", "ez-acp-tick"), h10("span", "ez-acp-text", entry.content));
|
|
7865
8737
|
box.appendChild(line);
|
|
7866
8738
|
}
|
|
7867
8739
|
break;
|
|
@@ -7870,8 +8742,8 @@
|
|
|
7870
8742
|
return box;
|
|
7871
8743
|
}
|
|
7872
8744
|
function acpAskEl(ask) {
|
|
7873
|
-
const card =
|
|
7874
|
-
if (ask.title) card.append(
|
|
8745
|
+
const card = h10("div", "ez-acp-ask");
|
|
8746
|
+
if (ask.title) card.append(h10("div", "ez-acp-ask-title", ask.title));
|
|
7875
8747
|
const values = /* @__PURE__ */ new Map();
|
|
7876
8748
|
const choicesOnly = ask.fields.every((f) => f.kind === "select");
|
|
7877
8749
|
const customKeys = new Set(
|
|
@@ -7894,7 +8766,7 @@
|
|
|
7894
8766
|
const submit = () => {
|
|
7895
8767
|
if (complete()) send({ answers: Object.fromEntries(values) });
|
|
7896
8768
|
};
|
|
7897
|
-
const submitBtn =
|
|
8769
|
+
const submitBtn = h10("button", "ez-acp-opt ez-acp-opt-primary", "\u9001\u51FA");
|
|
7898
8770
|
submitBtn.onclick = submit;
|
|
7899
8771
|
const refresh = () => {
|
|
7900
8772
|
submitBtn.hidden = sendsOnPick();
|
|
@@ -7908,7 +8780,7 @@
|
|
|
7908
8780
|
ask.fields.forEach((field, i) => {
|
|
7909
8781
|
let labelId;
|
|
7910
8782
|
if (field.text || mixed && field.optional) {
|
|
7911
|
-
const label =
|
|
8783
|
+
const label = h10(
|
|
7912
8784
|
"div",
|
|
7913
8785
|
"ez-acp-ask-q",
|
|
7914
8786
|
`${field.text ?? ""}${mixed && field.optional ? "\uFF08\u9078\u586B\uFF09" : ""}`
|
|
@@ -7920,9 +8792,9 @@
|
|
|
7920
8792
|
card.append(acpFieldEl(field, values, changed, submit, labelId));
|
|
7921
8793
|
});
|
|
7922
8794
|
if (ask.kind === "question" || !choicesOnly || !askSendsOnPick(ask.fields, false)) {
|
|
7923
|
-
const actions =
|
|
8795
|
+
const actions = h10("div", "ez-acp-ask-actions");
|
|
7924
8796
|
if (ask.kind === "question") {
|
|
7925
|
-
const skip =
|
|
8797
|
+
const skip = h10("button", "ez-acp-opt", "\u7565\u904E");
|
|
7926
8798
|
skip.onclick = () => send({ decline: true });
|
|
7927
8799
|
actions.append(skip);
|
|
7928
8800
|
}
|
|
@@ -7939,9 +8811,9 @@
|
|
|
7939
8811
|
return el2;
|
|
7940
8812
|
};
|
|
7941
8813
|
const optionButton = (option) => {
|
|
7942
|
-
const btn =
|
|
7943
|
-
btn.append(
|
|
7944
|
-
if (option.description) btn.append(
|
|
8814
|
+
const btn = h10("button", `ez-acp-opt${option.hint ? ` ez-acp-opt-${option.hint}` : ""}`);
|
|
8815
|
+
btn.append(h10("span", void 0, option.name));
|
|
8816
|
+
if (option.description) btn.append(h10("span", "ez-acp-opt-desc", option.description));
|
|
7945
8817
|
btn.title = option.description ?? "";
|
|
7946
8818
|
return btn;
|
|
7947
8819
|
};
|
|
@@ -7962,7 +8834,7 @@
|
|
|
7962
8834
|
}
|
|
7963
8835
|
};
|
|
7964
8836
|
const textField = (key, opts) => {
|
|
7965
|
-
const area =
|
|
8837
|
+
const area = h10("textarea", "ez-acp-field");
|
|
7966
8838
|
area.rows = 1;
|
|
7967
8839
|
if (opts.max !== void 0) area.maxLength = opts.max;
|
|
7968
8840
|
if (opts.placeholder) area.placeholder = opts.placeholder;
|
|
@@ -7989,7 +8861,7 @@
|
|
|
7989
8861
|
if (field.kind !== "select" && field.kind !== "multiselect") return row;
|
|
7990
8862
|
const custom = field.custom;
|
|
7991
8863
|
if (!custom) return row;
|
|
7992
|
-
const group =
|
|
8864
|
+
const group = h10("div", "ez-acp-group");
|
|
7993
8865
|
const box = textField(custom.key, {
|
|
7994
8866
|
placeholder: field.kind === "multiselect" ? "\u5176\u4ED6\u7B54\u6848\uFF08\u9078\u586B\uFF09" : "\u81EA\u5DF1\u56DE\u7B54\uFF0C\u6216\u88DC\u5145\u8AAA\u660E\uFF08\u9078\u586B\uFF09",
|
|
7995
8867
|
onInput: () => {
|
|
@@ -8001,7 +8873,7 @@
|
|
|
8001
8873
|
};
|
|
8002
8874
|
switch (field.kind) {
|
|
8003
8875
|
case "select": {
|
|
8004
|
-
const row = labelled(
|
|
8876
|
+
const row = labelled(h10("div", "ez-acp-ask-options"), "radiogroup");
|
|
8005
8877
|
const radios = field.options.map(radioButton);
|
|
8006
8878
|
const clearPick = () => {
|
|
8007
8879
|
values.delete(field.key);
|
|
@@ -8026,7 +8898,7 @@
|
|
|
8026
8898
|
return group;
|
|
8027
8899
|
}
|
|
8028
8900
|
case "multiselect": {
|
|
8029
|
-
const row = labelled(
|
|
8901
|
+
const row = labelled(h10("div", "ez-acp-ask-options"), "group");
|
|
8030
8902
|
const picked = new Set(field.default ?? []);
|
|
8031
8903
|
const sync = () => {
|
|
8032
8904
|
if (picked.size) values.set(field.key, [...picked]);
|
|
@@ -8055,7 +8927,7 @@
|
|
|
8055
8927
|
});
|
|
8056
8928
|
}
|
|
8057
8929
|
case "boolean": {
|
|
8058
|
-
const row = labelled(
|
|
8930
|
+
const row = labelled(h10("div", "ez-acp-ask-options"), "radiogroup");
|
|
8059
8931
|
const radios = [
|
|
8060
8932
|
radioButton({ id: "true", name: "\u662F" }),
|
|
8061
8933
|
radioButton({ id: "false", name: "\u5426" })
|
|
@@ -8073,7 +8945,7 @@
|
|
|
8073
8945
|
return row;
|
|
8074
8946
|
}
|
|
8075
8947
|
case "number": {
|
|
8076
|
-
const input = labelled(
|
|
8948
|
+
const input = labelled(h10("input", "ez-acp-field ez-acp-field-number"));
|
|
8077
8949
|
input.type = "number";
|
|
8078
8950
|
if (field.min !== void 0) input.min = String(field.min);
|
|
8079
8951
|
if (field.max !== void 0) input.max = String(field.max);
|