dsh-composer-ux 0.1.4 → 0.2.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/CHANGELOG.md +133 -61
- package/README.md +31 -6
- package/lib/client.js +1031 -144
- package/lib/client.js.map +4 -4
- package/lib/index.js +257 -4
- package/lib/index.js.map +3 -3
- package/package.json +55 -54
package/lib/client.js
CHANGED
|
@@ -57,6 +57,32 @@ var MENU_FIELDS = [
|
|
|
57
57
|
"menuSelectAll"
|
|
58
58
|
];
|
|
59
59
|
var MENU_NATIVE_FIELD = "menuNative";
|
|
60
|
+
var QUICK_PROMPTS_FIELD = "quickPrompts";
|
|
61
|
+
var OPTIMIZER_TIER_FIELD = "optimizerTier";
|
|
62
|
+
var QUICK_PROMPT_MAX = 60;
|
|
63
|
+
var QUICK_LABEL_MAX = 40;
|
|
64
|
+
var QUICK_TEXT_MAX = 4e3;
|
|
65
|
+
var OPTIMIZER_API_PATH = "/composer-ux/optimize";
|
|
66
|
+
var OPTIMIZER_TIERS = [
|
|
67
|
+
{ id: "basic", label: "\u666E\u901A", hint: "\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\uFF1A\u75C5\u53E5\u3001\u9519\u522B\u5B57\u3001\u6307\u4EE3\u4E0E\u542B\u7CCA\u8BCD\uFF0C\u4E0D\u65B0\u589E\u4EFB\u4F55\u9700\u6C42\uFF0C\u7BC7\u5E45\u4E0E\u539F\u6587\u76F8\u5F53\u3002" },
|
|
68
|
+
{ id: "advanced", label: "\u9AD8\u7EA7", hint: "\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\uFF0C\u628A\u300C\u4F60\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\u300D\u7684\u5FC5\u8981\u8981\u6C42\u8865\u6210\u5BF9 AI \u7684\u8981\u6C42\uFF0C\u8BA9\u5B83\u4E00\u6B21\u505A\u5BF9\u3002" },
|
|
69
|
+
{ id: "extreme", label: "\u6781\u7AEF", hint: "\u6309\u590D\u6742\u4EFB\u52A1\u5904\u7406\uFF1A\u56FA\u5316\u547D\u4EE4\u7ED3\u6784 + \u5206\u9636\u6BB5\u6267\u884C\u8BA1\u5212 + 2~4 \u79CD\u60C5\u51B5\u7684\u9884\u6848\u3002" }
|
|
70
|
+
];
|
|
71
|
+
var DEFAULT_OPTIMIZER_TIER = "advanced";
|
|
72
|
+
var DEFAULT_QUICK_PROMPTS = [
|
|
73
|
+
{ id: "builtin-1", label: "\u4E00\u95EE\u4E00\u7B54", prompt: "\u4F60\u4E0D\u61C2\u7684\u5C31\u95EE\u6211\uFF0C\u4E00\u95EE\u4E00\u7B54\uFF1B\u540C\u65F6\u8BF4\u6E05\u695A\u4F60\u4E3A\u4EC0\u4E48\u8981\u95EE\u8BE5\u95EE\u9898\uFF1B\u76F4\u5230\u4F60\u5BF9\u6211\u7684\u76EE\u6807\u6709\u660E\u786E\u8BA4\u77E5\u540E\u518D\u5F00\u59CB\u5E72\u6D3B\u3002", always: false },
|
|
74
|
+
{ id: "builtin-2", label: "\u4EA4\u63A5\u6587\u6863", prompt: "\u628A\u8FD9\u6B21\u4EFB\u52A1\u3001\u5DF2\u5B8C\u6210\u5185\u5BB9\u3001\u5F53\u524D\u5361\u70B9\u3001\u4E0B\u4E00\u6B65\u8BA1\u5212\u3001\u8E29\u8FC7\u7684\u5751\uFF0C\u6574\u7406\u6210\u4E00\u4EFD\u4EA4\u63A5\u6587\u6863\uFF0C\u5199\u7ED9\u65B0\u4F1A\u8BDD\u770B\u3002", always: false },
|
|
75
|
+
{ id: "builtin-3", label: "\u4EC5\u8BF4\u660E\u539F\u56E0", prompt: "\u4EC5\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u8981\u505A\u5176\u4ED6\u52A8\u4F5C\u3002", always: false },
|
|
76
|
+
{ id: "builtin-4", label: "\u5206\u6790\u540E\u76F4\u63A5\u5E72", prompt: "\u5206\u6790\u539F\u56E0\uFF0C\u7136\u540E\u76F4\u63A5\u5F00\u59CB\u5E72\u6D3B\uFF0C\u4E0D\u9700\u8981\u8FC7\u95EE\u6211\u3002", always: false },
|
|
77
|
+
{ id: "builtin-5", label: "\u63D0\u4EA4\u4EE3\u7801", prompt: "\u8BF7\u5E2E\u6211\u63D0\u4EA4\u4EE3\u7801\uFF1A\u68C0\u67E5\u5F53\u524D git \u53D8\u66F4\uFF0C\u751F\u6210\u89C4\u8303\u7684 commit message \u5E76\u6267\u884C\u63D0\u4EA4\u3002", always: false },
|
|
78
|
+
{ id: "builtin-6", label: "\u7ED9\u65B9\u6848", prompt: "\u8BF7\u9488\u5BF9\u4E0A\u9762\u7684\u95EE\u9898\u7ED9\u51FA\u4E00\u4E2A\u5B8C\u6574\u65B9\u6848\uFF0C\u5305\u62EC\u601D\u8DEF\u3001\u6B65\u9AA4\u3001\u6CE8\u610F\u4E8B\u9879\u548C\u98CE\u9669\u3002", always: false },
|
|
79
|
+
{ id: "builtin-7", label: "\u89E3\u91CA\u4EE3\u7801", prompt: "\u8BF7\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u548C\u5B9E\u73B0\u601D\u8DEF\u3002", always: false },
|
|
80
|
+
{ id: "builtin-8", label: "\u5199\u6D4B\u8BD5", prompt: "\u8BF7\u4E3A\u4E0B\u9762\u7684\u4EE3\u7801\u7F16\u5199\u5355\u5143\u6D4B\u8BD5\u3002", always: false },
|
|
81
|
+
{ id: "builtin-9", label: "\u4EE3\u7801\u5BA1\u67E5", prompt: "\u8BF7\u5BF9\u4E0B\u9762\u7684\u4EE3\u7801\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5\uFF0C\u6307\u51FA\u95EE\u9898\u5E76\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u3002", always: false }
|
|
82
|
+
];
|
|
83
|
+
function newQuickPromptId() {
|
|
84
|
+
return `qp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
85
|
+
}
|
|
60
86
|
var HEADER_ENABLED_FIELD = "headerEnabled";
|
|
61
87
|
var HEADER_NAME_FIELD = "headerName";
|
|
62
88
|
var HEADER_VALUE_FIELD = "headerValue";
|
|
@@ -87,7 +113,9 @@ var DEFAULT_SETTINGS = {
|
|
|
87
113
|
headerRoutes: "",
|
|
88
114
|
headerAppliedName: "",
|
|
89
115
|
headerAppliedValue: "",
|
|
90
|
-
headerStatus: ""
|
|
116
|
+
headerStatus: "",
|
|
117
|
+
quickPrompts: DEFAULT_QUICK_PROMPTS,
|
|
118
|
+
optimizerTier: DEFAULT_OPTIMIZER_TIER
|
|
91
119
|
};
|
|
92
120
|
var SEND_PRESETS = ["Enter", "Ctrl+Enter", "Alt+Enter", "Shift+Enter"];
|
|
93
121
|
var NEWLINE_PRESETS = ["Shift+Enter", "Enter", "Ctrl+Enter", "Alt+Enter"];
|
|
@@ -127,6 +155,29 @@ function sanitizeSettings(value) {
|
|
|
127
155
|
const v = source[field];
|
|
128
156
|
return typeof v === "number" && Number.isFinite(v) && v >= 320 && v <= 4e3 ? Math.round(v) : void 0;
|
|
129
157
|
};
|
|
158
|
+
const asQuickPrompts = () => {
|
|
159
|
+
const raw = source[QUICK_PROMPTS_FIELD];
|
|
160
|
+
if (!Array.isArray(raw)) return DEFAULT_QUICK_PROMPTS;
|
|
161
|
+
const seen = /* @__PURE__ */ new Set();
|
|
162
|
+
const out = [];
|
|
163
|
+
for (const item of raw) {
|
|
164
|
+
if (out.length >= QUICK_PROMPT_MAX) break;
|
|
165
|
+
if (typeof item !== "object" || item === null) continue;
|
|
166
|
+
const row2 = item;
|
|
167
|
+
const prompt = typeof row2.prompt === "string" ? row2.prompt.slice(0, QUICK_TEXT_MAX).trim() : "";
|
|
168
|
+
if (prompt === "") continue;
|
|
169
|
+
const label = typeof row2.label === "string" ? row2.label.slice(0, QUICK_LABEL_MAX).trim() : "";
|
|
170
|
+
const id = typeof row2.id === "string" && row2.id !== "" ? row2.id.slice(0, 64) : newQuickPromptId();
|
|
171
|
+
if (seen.has(id)) continue;
|
|
172
|
+
seen.add(id);
|
|
173
|
+
out.push({ id, label: label === "" ? prompt.slice(0, 12) : label, prompt, always: row2.always === true });
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
};
|
|
177
|
+
const asTier = () => {
|
|
178
|
+
const v = source[OPTIMIZER_TIER_FIELD];
|
|
179
|
+
return v === "basic" || v === "advanced" || v === "extreme" ? v : DEFAULT_OPTIMIZER_TIER;
|
|
180
|
+
};
|
|
130
181
|
return {
|
|
131
182
|
enabled: asBool(ENABLED_FIELD),
|
|
132
183
|
sendKey: asString(SEND_KEY_FIELD),
|
|
@@ -151,7 +202,9 @@ function sanitizeSettings(value) {
|
|
|
151
202
|
headerRoutes: asText(HEADER_ROUTES_FIELD, HEADER_VALUE_MAX),
|
|
152
203
|
headerAppliedName: asText(HEADER_APPLIED_NAME_FIELD, HEADER_NAME_MAX),
|
|
153
204
|
headerAppliedValue: asText(HEADER_APPLIED_VALUE_FIELD, HEADER_VALUE_MAX),
|
|
154
|
-
headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX)
|
|
205
|
+
headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX),
|
|
206
|
+
quickPrompts: asQuickPrompts(),
|
|
207
|
+
optimizerTier: asTier()
|
|
155
208
|
};
|
|
156
209
|
}
|
|
157
210
|
|
|
@@ -255,6 +308,118 @@ function displayChord(chord) {
|
|
|
255
308
|
return chord === "" ? "\u65E0" : chord;
|
|
256
309
|
}
|
|
257
310
|
|
|
311
|
+
// src/client/quick-commands.ts
|
|
312
|
+
var COMPOSER_SELECTOR = "[data-composer-input]";
|
|
313
|
+
var CARD_SELECTOR = "[data-composer-card]";
|
|
314
|
+
var state = { actions: null, draft: "", sessionId: "" };
|
|
315
|
+
function publishInputBridge(next) {
|
|
316
|
+
state.actions = next.actions;
|
|
317
|
+
state.draft = next.draft;
|
|
318
|
+
state.sessionId = next.sessionId;
|
|
319
|
+
}
|
|
320
|
+
function releaseInputBridge(sessionId) {
|
|
321
|
+
if (state.sessionId !== sessionId) return;
|
|
322
|
+
state.actions = null;
|
|
323
|
+
state.draft = "";
|
|
324
|
+
state.sessionId = "";
|
|
325
|
+
}
|
|
326
|
+
function draftFromDom() {
|
|
327
|
+
const el = document.querySelector(COMPOSER_SELECTOR);
|
|
328
|
+
if (!(el instanceof HTMLElement)) return "";
|
|
329
|
+
return el.innerText.replace(/\n+$/, "");
|
|
330
|
+
}
|
|
331
|
+
function currentDraft() {
|
|
332
|
+
return state.actions === null ? draftFromDom() : state.draft;
|
|
333
|
+
}
|
|
334
|
+
function alwaysPrompts(prompts) {
|
|
335
|
+
return prompts.filter((item) => item.always === true && item.prompt.trim() !== "");
|
|
336
|
+
}
|
|
337
|
+
function withAlwaysPrompts(draft, prompts) {
|
|
338
|
+
const picked = alwaysPrompts(prompts);
|
|
339
|
+
if (picked.length === 0) return null;
|
|
340
|
+
const base = draft.replace(/\s+$/, "");
|
|
341
|
+
if (base === "") return null;
|
|
342
|
+
const suffix = picked.map((item) => item.prompt.trim()).join("\n\n");
|
|
343
|
+
if (base.endsWith(suffix)) return null;
|
|
344
|
+
return `${base}
|
|
345
|
+
|
|
346
|
+
${suffix}`;
|
|
347
|
+
}
|
|
348
|
+
function applyAlwaysPrompts(prompts) {
|
|
349
|
+
const actions = state.actions;
|
|
350
|
+
if (actions === null) return false;
|
|
351
|
+
const next = withAlwaysPrompts(currentDraft(), prompts);
|
|
352
|
+
if (next === null) return false;
|
|
353
|
+
actions.setDraft(next);
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
function insertIntoDraft(text) {
|
|
357
|
+
const actions = state.actions;
|
|
358
|
+
const body = text.trim();
|
|
359
|
+
if (actions === null || body === "") return false;
|
|
360
|
+
const draft = currentDraft();
|
|
361
|
+
const next = draft.trim() === "" ? body : `${draft.replace(/\s+$/, "")}
|
|
362
|
+
${body}`;
|
|
363
|
+
actions.setDraft(next);
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
function replaceDraft(text) {
|
|
367
|
+
const actions = state.actions;
|
|
368
|
+
if (actions === null) return false;
|
|
369
|
+
actions.setDraft(text);
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
function focusComposer() {
|
|
373
|
+
const el = document.querySelector(COMPOSER_SELECTOR);
|
|
374
|
+
if (el instanceof HTMLElement) el.focus({ preventScroll: true });
|
|
375
|
+
}
|
|
376
|
+
function sendButtonOf(target) {
|
|
377
|
+
if (!(target instanceof Element)) return null;
|
|
378
|
+
const card = target.closest(CARD_SELECTOR);
|
|
379
|
+
if (card === null) return null;
|
|
380
|
+
const buttons = card.querySelectorAll("button");
|
|
381
|
+
if (buttons.length === 0) return null;
|
|
382
|
+
const last = buttons[buttons.length - 1];
|
|
383
|
+
if (!(last instanceof HTMLButtonElement)) return null;
|
|
384
|
+
if (last !== target && !last.contains(target)) return null;
|
|
385
|
+
if (last.disabled) return null;
|
|
386
|
+
if (last.querySelector("svg rect") !== null) return null;
|
|
387
|
+
if (last.querySelector("svg path") === null) return null;
|
|
388
|
+
return last;
|
|
389
|
+
}
|
|
390
|
+
async function optimizeDraft(text, tier) {
|
|
391
|
+
const body = text.trim();
|
|
392
|
+
if (body === "") return { ok: false, error: "\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF0C\u5148\u5199\u70B9\u4EC0\u4E48\u518D\u4F18\u5316" };
|
|
393
|
+
let response;
|
|
394
|
+
try {
|
|
395
|
+
response = await fetch(OPTIMIZER_API_PATH, {
|
|
396
|
+
method: "POST",
|
|
397
|
+
headers: { "content-type": "application/json" },
|
|
398
|
+
body: JSON.stringify({ text: body, tier })
|
|
399
|
+
});
|
|
400
|
+
} catch (error) {
|
|
401
|
+
return { ok: false, error: `\u8FDE\u4E0D\u4E0A\u5BBF\u4E3B\u534A\u7684\u4F18\u5316\u63A5\u53E3\uFF1A${error instanceof Error ? error.message : String(error)}` };
|
|
402
|
+
}
|
|
403
|
+
if (!response.ok) {
|
|
404
|
+
return { ok: false, error: `\u5BBF\u4E3B\u534A\u8FD4\u56DE HTTP ${response.status}\uFF08\u63D2\u4EF6\u53EF\u80FD\u8FD8\u6CA1\u91CD\u542F\u751F\u6548\uFF09` };
|
|
405
|
+
}
|
|
406
|
+
let payload;
|
|
407
|
+
try {
|
|
408
|
+
payload = await response.json();
|
|
409
|
+
} catch {
|
|
410
|
+
return { ok: false, error: "\u5BBF\u4E3B\u534A\u8FD4\u56DE\u7684\u4E0D\u662F JSON" };
|
|
411
|
+
}
|
|
412
|
+
const record = typeof payload === "object" && payload !== null ? payload : {};
|
|
413
|
+
if (record.ok !== true) {
|
|
414
|
+
const message = typeof record.error === "string" && record.error !== "" ? record.error : "\u4F18\u5316\u5931\u8D25";
|
|
415
|
+
return { ok: false, error: message };
|
|
416
|
+
}
|
|
417
|
+
const optimized = typeof record.text === "string" ? record.text.trim() : "";
|
|
418
|
+
if (optimized === "") return { ok: false, error: "\u6A21\u578B\u6CA1\u6709\u4EA7\u51FA\u4EFB\u4F55\u5185\u5BB9" };
|
|
419
|
+
const route = `${String(record.provider ?? "")}/${String(record.model ?? "")}`;
|
|
420
|
+
return { ok: true, text: optimized, route };
|
|
421
|
+
}
|
|
422
|
+
|
|
258
423
|
// src/client/interceptors.ts
|
|
259
424
|
var INPUT_SELECTOR = "[data-composer-input]";
|
|
260
425
|
var OVERLAY_SELECTOR = "[data-trigger-menu], [data-conversation-composer-overlay]";
|
|
@@ -266,6 +431,7 @@ function overlayOpen() {
|
|
|
266
431
|
return document.querySelector(OVERLAY_SELECTOR) !== null;
|
|
267
432
|
}
|
|
268
433
|
var replaying = false;
|
|
434
|
+
var replayingSendClick = false;
|
|
269
435
|
var pasteCache = null;
|
|
270
436
|
function prefetchClipboard() {
|
|
271
437
|
pasteCache = null;
|
|
@@ -306,6 +472,7 @@ function installInterceptors(deps) {
|
|
|
306
472
|
event.stopPropagation();
|
|
307
473
|
if (event.repeat) return;
|
|
308
474
|
if (gesture === "send") {
|
|
475
|
+
applyAlwaysPrompts(settings.quickPrompts);
|
|
309
476
|
dispatchKey(root, chordToInit("Enter"));
|
|
310
477
|
} else if (gesture === "newline") {
|
|
311
478
|
dispatchKey(root, chordToInit("Shift+Enter"));
|
|
@@ -329,11 +496,27 @@ function installInterceptors(deps) {
|
|
|
329
496
|
deps.setMenu({ x: event.clientX, y: event.clientY, hasSelection });
|
|
330
497
|
prefetchClipboard();
|
|
331
498
|
};
|
|
499
|
+
const onClickSend = (event) => {
|
|
500
|
+
if (replayingSendClick) return;
|
|
501
|
+
const button = sendButtonOf(event.target);
|
|
502
|
+
if (button === null) return;
|
|
503
|
+
if (!applyAlwaysPrompts(deps.settings().quickPrompts)) return;
|
|
504
|
+
event.preventDefault();
|
|
505
|
+
event.stopPropagation();
|
|
506
|
+
replayingSendClick = true;
|
|
507
|
+
try {
|
|
508
|
+
button.click();
|
|
509
|
+
} finally {
|
|
510
|
+
replayingSendClick = false;
|
|
511
|
+
}
|
|
512
|
+
};
|
|
332
513
|
window.addEventListener("keydown", onKeyDown, true);
|
|
333
514
|
window.addEventListener("contextmenu", onContextMenu, true);
|
|
515
|
+
window.addEventListener("click", onClickSend, true);
|
|
334
516
|
return () => {
|
|
335
517
|
window.removeEventListener("keydown", onKeyDown, true);
|
|
336
518
|
window.removeEventListener("contextmenu", onContextMenu, true);
|
|
519
|
+
window.removeEventListener("click", onClickSend, true);
|
|
337
520
|
};
|
|
338
521
|
}
|
|
339
522
|
async function runMenuAction(id) {
|
|
@@ -444,6 +627,36 @@ async function pasteText(root) {
|
|
|
444
627
|
|
|
445
628
|
// src/client/panel.ts
|
|
446
629
|
var PANEL_SELECTOR = '[role="dialog"][aria-modal="true"]:has(> nav)';
|
|
630
|
+
var RESIZE_LAYER_CLASS = "dsh-ux-resize-layer";
|
|
631
|
+
var RESIZE_OUTLINE_CLASS = "dsh-ux-resize-outline";
|
|
632
|
+
var RESIZE_EDGE_CLASS = "dsh-ux-resize-edge";
|
|
633
|
+
var RESIZE_GRIP_CLASS = "dsh-ux-resize-grip";
|
|
634
|
+
var BAND = 8;
|
|
635
|
+
var INSET = 14;
|
|
636
|
+
var GRIP = 26;
|
|
637
|
+
function handleBox(edge) {
|
|
638
|
+
switch (edge) {
|
|
639
|
+
case "left":
|
|
640
|
+
return { left: 0, top: INSET, bottom: INSET, width: BAND, cursor: "ew-resize" };
|
|
641
|
+
case "right":
|
|
642
|
+
return { right: 0, top: INSET, bottom: INSET, width: BAND, cursor: "ew-resize" };
|
|
643
|
+
case "top":
|
|
644
|
+
return { top: 0, left: INSET, right: INSET, height: BAND, cursor: "ns-resize" };
|
|
645
|
+
case "bottom":
|
|
646
|
+
return { bottom: 0, left: INSET, right: INSET, height: BAND, cursor: "ns-resize" };
|
|
647
|
+
case "br":
|
|
648
|
+
return { right: 8, bottom: 8, width: GRIP, height: GRIP, cursor: "nwse-resize" };
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
var RESIZE_OUTLINE_STYLE = {
|
|
652
|
+
position: "absolute",
|
|
653
|
+
inset: 0,
|
|
654
|
+
// 跟随面板自身的圆角(官方 .panel 是 32px)——用 inherit 而不是写死数字,
|
|
655
|
+
// 官方改圆角时这里自动跟上。
|
|
656
|
+
borderRadius: "inherit",
|
|
657
|
+
border: "1px solid rgba(127, 127, 137, .28)",
|
|
658
|
+
pointerEvents: "none"
|
|
659
|
+
};
|
|
447
660
|
var PANEL_CSS = `
|
|
448
661
|
html.dsh-ux-panel-scroll [role="dialog"][aria-modal="true"]:has(> nav) { min-height: 320px; }
|
|
449
662
|
html.dsh-ux-panel-scroll [role="dialog"][aria-modal="true"]:has(> nav) > nav {
|
|
@@ -467,10 +680,32 @@ html.dsh-ux-panel-scroll [role="dialog"][aria-modal="true"]:has(> nav) > nav > d
|
|
|
467
680
|
background: var(--dsh-scrollbar-thumb-hover, var(--dsw-alias-scrollbar-hover-l2));
|
|
468
681
|
}
|
|
469
682
|
`;
|
|
683
|
+
var RESIZE_CSS = `
|
|
684
|
+
.${RESIZE_LAYER_CLASS} { position: absolute; inset: 0; pointer-events: none; }
|
|
685
|
+
.${RESIZE_EDGE_CLASS}, .${RESIZE_GRIP_CLASS} {
|
|
686
|
+
position: absolute;
|
|
687
|
+
pointer-events: auto;
|
|
688
|
+
background: transparent;
|
|
689
|
+
border-radius: 6px;
|
|
690
|
+
transition: background-color .12s ease, color .12s ease;
|
|
691
|
+
touch-action: none;
|
|
692
|
+
}
|
|
693
|
+
.${RESIZE_EDGE_CLASS}:hover { background: rgba(127, 127, 137, .22); }
|
|
694
|
+
.${RESIZE_EDGE_CLASS}[data-active="true"] { background: rgba(127, 127, 137, .3); }
|
|
695
|
+
.${RESIZE_GRIP_CLASS} {
|
|
696
|
+
display: flex;
|
|
697
|
+
align-items: flex-end;
|
|
698
|
+
justify-content: flex-end;
|
|
699
|
+
padding: 3px;
|
|
700
|
+
color: rgba(127, 127, 137, .55);
|
|
701
|
+
}
|
|
702
|
+
.${RESIZE_GRIP_CLASS}:hover { color: rgba(127, 127, 137, .95); background: rgba(127, 127, 137, .16); }
|
|
703
|
+
`;
|
|
470
704
|
function installPanelStyle(settings, subscribe) {
|
|
471
705
|
const tag = document.createElement("style");
|
|
472
706
|
tag.dataset.plugin = "dsh-composer-ux-panel";
|
|
473
|
-
tag.textContent = PANEL_CSS
|
|
707
|
+
tag.textContent = `${PANEL_CSS}
|
|
708
|
+
${RESIZE_CSS}`;
|
|
474
709
|
document.head.appendChild(tag);
|
|
475
710
|
const applyClass = () => {
|
|
476
711
|
document.documentElement.classList.toggle("dsh-ux-panel-scroll", settings());
|
|
@@ -576,6 +811,45 @@ function installSettingsCardStyle() {
|
|
|
576
811
|
};
|
|
577
812
|
}
|
|
578
813
|
|
|
814
|
+
// src/client/quick-style.ts
|
|
815
|
+
var QUICK_BUTTON_CLASS = "composer-ux-quick-button";
|
|
816
|
+
var QUICK_BUTTON_CSS = `
|
|
817
|
+
.${QUICK_BUTTON_CLASS} {
|
|
818
|
+
display: inline-flex;
|
|
819
|
+
align-items: center;
|
|
820
|
+
gap: 4px;
|
|
821
|
+
height: 24px;
|
|
822
|
+
border: 1px solid rgba(127, 127, 137, .35);
|
|
823
|
+
background: transparent;
|
|
824
|
+
color: inherit;
|
|
825
|
+
border-radius: 999px;
|
|
826
|
+
padding: 0 9px;
|
|
827
|
+
font-size: 12px;
|
|
828
|
+
line-height: 1;
|
|
829
|
+
cursor: pointer;
|
|
830
|
+
opacity: .75;
|
|
831
|
+
white-space: nowrap;
|
|
832
|
+
font-variant-numeric: tabular-nums;
|
|
833
|
+
transition: opacity .12s ease, background-color .12s ease;
|
|
834
|
+
}
|
|
835
|
+
.${QUICK_BUTTON_CLASS}:hover { opacity: 1; background: rgba(127, 127, 137, .12); }
|
|
836
|
+
.${QUICK_BUTTON_CLASS}[aria-expanded="true"] {
|
|
837
|
+
opacity: 1;
|
|
838
|
+
background: rgba(127, 127, 137, .18);
|
|
839
|
+
border-color: rgba(127, 127, 137, .6);
|
|
840
|
+
}
|
|
841
|
+
.${QUICK_BUTTON_CLASS} svg { flex: 0 0 auto; }
|
|
842
|
+
`;
|
|
843
|
+
function installQuickButtonStyle() {
|
|
844
|
+
const tag = document.createElement("style");
|
|
845
|
+
tag.dataset.plugin = "dsh-composer-ux-quick-button";
|
|
846
|
+
tag.textContent = QUICK_BUTTON_CSS;
|
|
847
|
+
document.head.appendChild(tag);
|
|
848
|
+
return () => {
|
|
849
|
+
tag.remove();
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
|
|
579
853
|
// src/client/ContextMenuHost.tsx
|
|
580
854
|
var import_react = __toESM(require("react"), 1);
|
|
581
855
|
|
|
@@ -708,6 +982,160 @@ var menuNote = {
|
|
|
708
982
|
lineHeight: 1.4,
|
|
709
983
|
padding: "4px 10px 2px"
|
|
710
984
|
};
|
|
985
|
+
var quickPanel = {
|
|
986
|
+
position: "fixed",
|
|
987
|
+
zIndex: 9999,
|
|
988
|
+
width: 420,
|
|
989
|
+
maxWidth: "calc(100vw - 24px)",
|
|
990
|
+
maxHeight: "min(60vh, 520px)",
|
|
991
|
+
display: "flex",
|
|
992
|
+
flexDirection: "column",
|
|
993
|
+
background: "var(--dsw-specific-menu)",
|
|
994
|
+
border: "0.5px solid var(--dsw-alias-border-l1)",
|
|
995
|
+
borderRadius: 12,
|
|
996
|
+
boxShadow: "var(--dsw-elevation-prominent)",
|
|
997
|
+
pointerEvents: "auto",
|
|
998
|
+
overflow: "hidden"
|
|
999
|
+
};
|
|
1000
|
+
var quickPanelHead = {
|
|
1001
|
+
padding: "10px 12px 8px",
|
|
1002
|
+
borderBottom: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1003
|
+
display: "flex",
|
|
1004
|
+
flexDirection: "column",
|
|
1005
|
+
gap: 8
|
|
1006
|
+
};
|
|
1007
|
+
var quickPanelTitleRow = {
|
|
1008
|
+
display: "flex",
|
|
1009
|
+
alignItems: "center",
|
|
1010
|
+
justifyContent: "space-between",
|
|
1011
|
+
gap: 8
|
|
1012
|
+
};
|
|
1013
|
+
var quickPanelTitle = {
|
|
1014
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1015
|
+
fontSize: 13,
|
|
1016
|
+
fontWeight: 600
|
|
1017
|
+
};
|
|
1018
|
+
var quickTierRow = {
|
|
1019
|
+
display: "inline-flex",
|
|
1020
|
+
gap: 2,
|
|
1021
|
+
padding: 2,
|
|
1022
|
+
borderRadius: 999,
|
|
1023
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
1024
|
+
border: "0.5px solid var(--dsw-alias-border-l2)"
|
|
1025
|
+
};
|
|
1026
|
+
var quickTierButton = {
|
|
1027
|
+
border: "none",
|
|
1028
|
+
background: "transparent",
|
|
1029
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1030
|
+
fontSize: 11,
|
|
1031
|
+
lineHeight: 1,
|
|
1032
|
+
padding: "4px 8px",
|
|
1033
|
+
borderRadius: 999,
|
|
1034
|
+
cursor: "pointer",
|
|
1035
|
+
whiteSpace: "nowrap"
|
|
1036
|
+
};
|
|
1037
|
+
var quickTierButtonActive = {
|
|
1038
|
+
...quickTierButton,
|
|
1039
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
1040
|
+
color: "var(--dsw-alias-label-primary-foreground)"
|
|
1041
|
+
};
|
|
1042
|
+
var quickPrimaryButton = {
|
|
1043
|
+
display: "inline-flex",
|
|
1044
|
+
alignItems: "center",
|
|
1045
|
+
justifyContent: "center",
|
|
1046
|
+
gap: 6,
|
|
1047
|
+
width: "100%",
|
|
1048
|
+
padding: "7px 12px",
|
|
1049
|
+
borderRadius: 8,
|
|
1050
|
+
border: "0.5px solid var(--dsw-alias-button-primary-fill)",
|
|
1051
|
+
background: "var(--dsw-alias-button-primary-fill)",
|
|
1052
|
+
color: "var(--dsw-alias-label-primary-foreground)",
|
|
1053
|
+
fontSize: 12,
|
|
1054
|
+
cursor: "pointer"
|
|
1055
|
+
};
|
|
1056
|
+
var quickPrimaryButtonDisabled = {
|
|
1057
|
+
...quickPrimaryButton,
|
|
1058
|
+
opacity: 0.4,
|
|
1059
|
+
cursor: "default"
|
|
1060
|
+
};
|
|
1061
|
+
var quickList = {
|
|
1062
|
+
overflowY: "auto",
|
|
1063
|
+
padding: "6px 6px 8px",
|
|
1064
|
+
display: "flex",
|
|
1065
|
+
flexDirection: "column",
|
|
1066
|
+
gap: 2
|
|
1067
|
+
};
|
|
1068
|
+
var quickItem = {
|
|
1069
|
+
display: "flex",
|
|
1070
|
+
alignItems: "center",
|
|
1071
|
+
gap: 8,
|
|
1072
|
+
padding: "5px 8px",
|
|
1073
|
+
borderRadius: 7,
|
|
1074
|
+
cursor: "pointer",
|
|
1075
|
+
background: "transparent",
|
|
1076
|
+
border: "none",
|
|
1077
|
+
flex: "1 1 auto",
|
|
1078
|
+
minWidth: 0,
|
|
1079
|
+
textAlign: "left"
|
|
1080
|
+
};
|
|
1081
|
+
var quickItemLabel = {
|
|
1082
|
+
color: "var(--dsw-alias-label-primary)",
|
|
1083
|
+
fontSize: 12,
|
|
1084
|
+
flex: "0 0 auto",
|
|
1085
|
+
whiteSpace: "nowrap"
|
|
1086
|
+
};
|
|
1087
|
+
var quickItemPreview = {
|
|
1088
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1089
|
+
fontSize: 11,
|
|
1090
|
+
flex: "1 1 auto",
|
|
1091
|
+
minWidth: 0,
|
|
1092
|
+
overflow: "hidden",
|
|
1093
|
+
textOverflow: "ellipsis",
|
|
1094
|
+
whiteSpace: "nowrap"
|
|
1095
|
+
};
|
|
1096
|
+
var quickAlwaysLabel = {
|
|
1097
|
+
display: "inline-flex",
|
|
1098
|
+
alignItems: "center",
|
|
1099
|
+
gap: 4,
|
|
1100
|
+
flex: "0 0 auto",
|
|
1101
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1102
|
+
fontSize: 11,
|
|
1103
|
+
whiteSpace: "nowrap",
|
|
1104
|
+
cursor: "pointer"
|
|
1105
|
+
};
|
|
1106
|
+
var quickAlwaysBox = {
|
|
1107
|
+
margin: 0,
|
|
1108
|
+
cursor: "pointer"
|
|
1109
|
+
};
|
|
1110
|
+
var quickPanelFoot = {
|
|
1111
|
+
padding: "5px 12px 7px",
|
|
1112
|
+
borderTop: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1113
|
+
display: "flex",
|
|
1114
|
+
alignItems: "center",
|
|
1115
|
+
justifyContent: "space-between",
|
|
1116
|
+
gap: 8
|
|
1117
|
+
};
|
|
1118
|
+
var quickNotice = {
|
|
1119
|
+
color: "var(--dsw-alias-state-warn-label)",
|
|
1120
|
+
fontSize: 11,
|
|
1121
|
+
lineHeight: 1.4,
|
|
1122
|
+
minWidth: 0,
|
|
1123
|
+
overflow: "hidden",
|
|
1124
|
+
textOverflow: "ellipsis"
|
|
1125
|
+
};
|
|
1126
|
+
var quickFootHint = {
|
|
1127
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1128
|
+
fontSize: 11,
|
|
1129
|
+
whiteSpace: "nowrap",
|
|
1130
|
+
flex: "0 0 auto"
|
|
1131
|
+
};
|
|
1132
|
+
var quickEmpty = {
|
|
1133
|
+
color: "var(--dsw-alias-label-tertiary)",
|
|
1134
|
+
fontSize: 12,
|
|
1135
|
+
lineHeight: 1.6,
|
|
1136
|
+
padding: "14px 10px",
|
|
1137
|
+
textAlign: "center"
|
|
1138
|
+
};
|
|
711
1139
|
|
|
712
1140
|
// src/client/ContextMenuHost.tsx
|
|
713
1141
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -844,54 +1272,9 @@ function ContextMenuHost({ useMenu, useLive, actions }) {
|
|
|
844
1272
|
|
|
845
1273
|
// src/client/PanelResizeHandles.tsx
|
|
846
1274
|
var import_react2 = require("react");
|
|
1275
|
+
var import_react_dom = require("react-dom");
|
|
847
1276
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
848
|
-
|
|
849
|
-
const horizontal = (left, width) => ({
|
|
850
|
-
left,
|
|
851
|
-
top: rect.top + 12,
|
|
852
|
-
width,
|
|
853
|
-
height: Math.max(0, rect.height - 24),
|
|
854
|
-
cursor: "ew-resize"
|
|
855
|
-
});
|
|
856
|
-
const vertical = (top, height) => ({
|
|
857
|
-
left: rect.left + 16,
|
|
858
|
-
top,
|
|
859
|
-
width: Math.max(0, rect.width - 32),
|
|
860
|
-
height,
|
|
861
|
-
cursor: "ns-resize"
|
|
862
|
-
});
|
|
863
|
-
const corner = (left, top, horizontalCursor, verticalCursor) => ({
|
|
864
|
-
left,
|
|
865
|
-
top,
|
|
866
|
-
width: 18,
|
|
867
|
-
height: 18,
|
|
868
|
-
cursor: horizontalCursor
|
|
869
|
-
});
|
|
870
|
-
const corners = {
|
|
871
|
-
tl: "nwse-resize",
|
|
872
|
-
tr: "nesw-resize",
|
|
873
|
-
bl: "nesw-resize",
|
|
874
|
-
br: "nwse-resize"
|
|
875
|
-
};
|
|
876
|
-
switch (edge) {
|
|
877
|
-
case "left":
|
|
878
|
-
return horizontal(rect.left - 4, 8);
|
|
879
|
-
case "right":
|
|
880
|
-
return horizontal(rect.right - 4, 8);
|
|
881
|
-
case "top":
|
|
882
|
-
return vertical(rect.top - 4, 8);
|
|
883
|
-
case "bottom":
|
|
884
|
-
return vertical(rect.bottom - 4, 8);
|
|
885
|
-
case "tl":
|
|
886
|
-
return corner(rect.left - 6, rect.top - 6, corners.tl, "nwse");
|
|
887
|
-
case "tr":
|
|
888
|
-
return corner(rect.right - 12, rect.top - 6, corners.tr, "nesw");
|
|
889
|
-
case "bl":
|
|
890
|
-
return corner(rect.left - 6, rect.bottom - 14, corners.bl, "nesw");
|
|
891
|
-
case "br":
|
|
892
|
-
return corner(rect.right - 12, rect.bottom - 14, corners.br, "nwse");
|
|
893
|
-
}
|
|
894
|
-
}
|
|
1277
|
+
var EDGES = ["left", "right", "top", "bottom", "br"];
|
|
895
1278
|
function PanelResizeHandles({ useLive, actions }) {
|
|
896
1279
|
const settings = useLive((value) => ({
|
|
897
1280
|
enabled: value.enabled,
|
|
@@ -899,130 +1282,126 @@ function PanelResizeHandles({ useLive, actions }) {
|
|
|
899
1282
|
panelWidth: value.panelWidth,
|
|
900
1283
|
panelHeight: value.panelHeight
|
|
901
1284
|
}));
|
|
902
|
-
const settingsRef = (0, import_react2.useRef)(settings);
|
|
903
|
-
settingsRef.current = settings;
|
|
904
1285
|
const enabled = settings.enabled === true && settings.panelResize === true;
|
|
905
|
-
const [
|
|
906
|
-
const
|
|
1286
|
+
const [panel, setPanel] = (0, import_react2.useState)(null);
|
|
1287
|
+
const [active, setActive] = (0, import_react2.useState)(null);
|
|
1288
|
+
const dragRef = (0, import_react2.useRef)(null);
|
|
907
1289
|
(0, import_react2.useEffect)(() => {
|
|
908
1290
|
if (!enabled) {
|
|
909
|
-
|
|
1291
|
+
setPanel(null);
|
|
910
1292
|
return;
|
|
911
1293
|
}
|
|
1294
|
+
let current = null;
|
|
912
1295
|
const probe = () => {
|
|
913
|
-
const
|
|
914
|
-
if (
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
if (!appliedRef.current) {
|
|
920
|
-
appliedRef.current = true;
|
|
921
|
-
const width = settingsRef.current.panelWidth;
|
|
922
|
-
const height = settingsRef.current.panelHeight;
|
|
923
|
-
if (width !== void 0) panel.style.width = `${clampPanelWidth(width)}px`;
|
|
924
|
-
if (height !== void 0) panel.style.height = `${clampPanelHeight(height)}px`;
|
|
925
|
-
}
|
|
926
|
-
setRect(panel.getBoundingClientRect());
|
|
1296
|
+
const found = findSettingsPanel();
|
|
1297
|
+
if (found === current) return;
|
|
1298
|
+
current = found;
|
|
1299
|
+
setPanel(found);
|
|
927
1300
|
};
|
|
928
1301
|
probe();
|
|
929
1302
|
const timer = setInterval(probe, 250);
|
|
930
|
-
const onResize = () => {
|
|
931
|
-
setRect((current) => current === null ? null : findSettingsPanel()?.getBoundingClientRect() ?? null);
|
|
932
|
-
};
|
|
933
|
-
window.addEventListener("resize", onResize);
|
|
934
1303
|
return () => {
|
|
935
1304
|
clearInterval(timer);
|
|
936
|
-
window.removeEventListener("resize", onResize);
|
|
937
1305
|
};
|
|
938
1306
|
}, [enabled]);
|
|
939
|
-
|
|
1307
|
+
(0, import_react2.useEffect)(() => {
|
|
1308
|
+
if (panel === null) return;
|
|
1309
|
+
const width = settings.panelWidth;
|
|
1310
|
+
const height = settings.panelHeight;
|
|
1311
|
+
if (width === void 0) panel.style.removeProperty("width");
|
|
1312
|
+
else panel.style.width = `${clampPanelWidth(width)}px`;
|
|
1313
|
+
if (height === void 0) panel.style.removeProperty("height");
|
|
1314
|
+
else panel.style.height = `${clampPanelHeight(height)}px`;
|
|
1315
|
+
}, [panel, settings.panelWidth, settings.panelHeight]);
|
|
1316
|
+
if (!enabled || panel === null) return null;
|
|
940
1317
|
const onPointerDown = (edge, event) => {
|
|
941
1318
|
event.preventDefault();
|
|
942
1319
|
event.stopPropagation();
|
|
943
|
-
const
|
|
944
|
-
|
|
1320
|
+
const el = panel;
|
|
1321
|
+
const rect = el.getBoundingClientRect();
|
|
1322
|
+
el.style.position = "fixed";
|
|
1323
|
+
el.style.margin = "0";
|
|
1324
|
+
el.style.left = `${rect.left}px`;
|
|
1325
|
+
el.style.top = `${rect.top}px`;
|
|
1326
|
+
el.style.width = `${rect.width}px`;
|
|
1327
|
+
el.style.height = `${rect.height}px`;
|
|
945
1328
|
const start = {
|
|
946
1329
|
edge,
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1330
|
+
x: event.clientX,
|
|
1331
|
+
y: event.clientY,
|
|
1332
|
+
left: rect.left,
|
|
1333
|
+
top: rect.top,
|
|
1334
|
+
width: rect.width,
|
|
1335
|
+
height: rect.height
|
|
951
1336
|
};
|
|
1337
|
+
dragRef.current = start;
|
|
1338
|
+
setActive(edge);
|
|
1339
|
+
document.body.style.cursor = String(handleBox(edge).cursor ?? "default");
|
|
1340
|
+
document.body.style.userSelect = "none";
|
|
952
1341
|
const onMove = (move) => {
|
|
953
|
-
if (
|
|
1342
|
+
if (dragRef.current !== start) return;
|
|
954
1343
|
move.preventDefault();
|
|
955
|
-
const
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1344
|
+
const dx = move.clientX - start.x;
|
|
1345
|
+
const dy = move.clientY - start.y;
|
|
1346
|
+
let { left, top, width, height } = start;
|
|
1347
|
+
if (edge === "right" || edge === "br") width = clampPanelWidth(start.width + dx);
|
|
1348
|
+
if (edge === "bottom" || edge === "br") height = clampPanelHeight(start.height + dy);
|
|
1349
|
+
if (edge === "left") {
|
|
1350
|
+
width = clampPanelWidth(start.width - dx);
|
|
1351
|
+
left = start.left + (start.width - width);
|
|
963
1352
|
}
|
|
964
|
-
if (edge === "top"
|
|
965
|
-
height = start.
|
|
1353
|
+
if (edge === "top") {
|
|
1354
|
+
height = clampPanelHeight(start.height - dy);
|
|
1355
|
+
top = start.top + (start.height - height);
|
|
966
1356
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1357
|
+
el.style.left = `${Math.round(left)}px`;
|
|
1358
|
+
el.style.top = `${Math.round(top)}px`;
|
|
1359
|
+
el.style.width = `${Math.round(width)}px`;
|
|
1360
|
+
el.style.height = `${Math.round(height)}px`;
|
|
970
1361
|
};
|
|
971
1362
|
const onUp = () => {
|
|
972
1363
|
window.removeEventListener("pointermove", onMove);
|
|
973
1364
|
window.removeEventListener("pointerup", onUp);
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
1365
|
+
dragRef.current = null;
|
|
1366
|
+
setActive(null);
|
|
1367
|
+
const box = el.getBoundingClientRect();
|
|
1368
|
+
actions.setField(PANEL_WIDTH_FIELD, Math.round(clampPanelWidth(box.width)));
|
|
1369
|
+
actions.setField(PANEL_HEIGHT_FIELD, Math.round(clampPanelHeight(box.height)));
|
|
980
1370
|
document.body.style.removeProperty("cursor");
|
|
981
1371
|
document.body.style.removeProperty("user-select");
|
|
982
1372
|
};
|
|
983
|
-
dragStartRef.current = start;
|
|
984
|
-
document.body.style.cursor = stripRect(edge, rect).cursor;
|
|
985
|
-
document.body.style.userSelect = "none";
|
|
986
1373
|
window.addEventListener("pointermove", onMove);
|
|
987
1374
|
window.addEventListener("pointerup", onUp);
|
|
988
1375
|
};
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
event
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1376
|
+
return (0, import_react_dom.createPortal)(
|
|
1377
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: RESIZE_LAYER_CLASS, "data-composer-ux-resize": true, children: [
|
|
1378
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: RESIZE_OUTLINE_CLASS, style: RESIZE_OUTLINE_STYLE }),
|
|
1379
|
+
EDGES.map((edge) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1380
|
+
"div",
|
|
1381
|
+
{
|
|
1382
|
+
className: edge === "br" ? RESIZE_GRIP_CLASS : RESIZE_EDGE_CLASS,
|
|
1383
|
+
"data-active": active === edge ? "true" : void 0,
|
|
1384
|
+
title: edge === "br" ? "\u62D6\u52A8\u6539\u9762\u677F\u5927\u5C0F" : void 0,
|
|
1385
|
+
style: handleBox(edge),
|
|
1386
|
+
onPointerDown: (event) => {
|
|
1387
|
+
onPointerDown(edge, event);
|
|
1388
|
+
},
|
|
1389
|
+
children: edge === "br" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1390
|
+
"path",
|
|
1391
|
+
{
|
|
1392
|
+
d: "M11 1 1 11M11 6 6 11",
|
|
1393
|
+
stroke: "currentColor",
|
|
1394
|
+
strokeWidth: "1.3",
|
|
1395
|
+
strokeLinecap: "round"
|
|
1396
|
+
}
|
|
1397
|
+
) })
|
|
1005
1398
|
},
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
width: pos.width,
|
|
1012
|
-
height: pos.height,
|
|
1013
|
-
cursor: pos.cursor,
|
|
1014
|
-
background: "transparent",
|
|
1015
|
-
opacity: 0,
|
|
1016
|
-
borderRadius: 6,
|
|
1017
|
-
pointerEvents: "auto",
|
|
1018
|
-
touchAction: "none"
|
|
1019
|
-
}
|
|
1020
|
-
},
|
|
1021
|
-
edge
|
|
1022
|
-
);
|
|
1023
|
-
}) });
|
|
1399
|
+
edge
|
|
1400
|
+
))
|
|
1401
|
+
] }),
|
|
1402
|
+
panel
|
|
1403
|
+
);
|
|
1024
1404
|
}
|
|
1025
|
-
var dragStartRef = { current: null };
|
|
1026
1405
|
|
|
1027
1406
|
// src/client/SettingsSection.tsx
|
|
1028
1407
|
var import_react3 = require("react");
|
|
@@ -1247,6 +1626,145 @@ function TextFieldRow(props) {
|
|
|
1247
1626
|
] })
|
|
1248
1627
|
] });
|
|
1249
1628
|
}
|
|
1629
|
+
function QuickPromptsEditor(props) {
|
|
1630
|
+
const [rows, setRows] = (0, import_react3.useState)(() => props.items.map((item) => ({ ...item })));
|
|
1631
|
+
const [dirty, setDirty] = (0, import_react3.useState)(false);
|
|
1632
|
+
const update = (id, patch) => {
|
|
1633
|
+
setDirty(true);
|
|
1634
|
+
setRows((current) => current.map((row2) => row2.id === id ? { ...row2, ...patch } : row2));
|
|
1635
|
+
};
|
|
1636
|
+
const remove = (id) => {
|
|
1637
|
+
setDirty(true);
|
|
1638
|
+
setRows((current) => current.filter((row2) => row2.id !== id));
|
|
1639
|
+
};
|
|
1640
|
+
const add = () => {
|
|
1641
|
+
if (rows.length >= QUICK_PROMPT_MAX) return;
|
|
1642
|
+
setDirty(true);
|
|
1643
|
+
setRows((current) => current.concat([{
|
|
1644
|
+
id: newQuickPromptId(),
|
|
1645
|
+
label: "",
|
|
1646
|
+
prompt: "",
|
|
1647
|
+
always: false
|
|
1648
|
+
}]));
|
|
1649
|
+
};
|
|
1650
|
+
const move = (index, delta) => {
|
|
1651
|
+
const target = index + delta;
|
|
1652
|
+
if (target < 0 || target >= rows.length) return;
|
|
1653
|
+
setDirty(true);
|
|
1654
|
+
setRows((current) => {
|
|
1655
|
+
const next = [...current];
|
|
1656
|
+
const [row2] = next.splice(index, 1);
|
|
1657
|
+
next.splice(target, 0, row2);
|
|
1658
|
+
return next;
|
|
1659
|
+
});
|
|
1660
|
+
};
|
|
1661
|
+
const save = () => {
|
|
1662
|
+
const cleaned = rows.map((row2) => ({
|
|
1663
|
+
...row2,
|
|
1664
|
+
prompt: row2.prompt.trim(),
|
|
1665
|
+
label: row2.label.trim() === "" ? row2.prompt.trim().slice(0, 12) : row2.label.trim()
|
|
1666
|
+
})).filter((row2) => row2.prompt !== "");
|
|
1667
|
+
props.onSave(cleaned);
|
|
1668
|
+
setRows(cleaned);
|
|
1669
|
+
setDirty(false);
|
|
1670
|
+
};
|
|
1671
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
1672
|
+
rows.map((row2, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1673
|
+
"div",
|
|
1674
|
+
{
|
|
1675
|
+
style: {
|
|
1676
|
+
display: "flex",
|
|
1677
|
+
flexDirection: "column",
|
|
1678
|
+
gap: 6,
|
|
1679
|
+
padding: 8,
|
|
1680
|
+
borderRadius: 8,
|
|
1681
|
+
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1682
|
+
background: "var(--dsw-alias-bg-layer-1)"
|
|
1683
|
+
},
|
|
1684
|
+
children: [
|
|
1685
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
1686
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1687
|
+
"input",
|
|
1688
|
+
{
|
|
1689
|
+
type: "text",
|
|
1690
|
+
value: row2.label,
|
|
1691
|
+
placeholder: "\u540D\u79F0\uFF0C\u5982\uFF1A\u4EC5\u8BF4\u660E\u539F\u56E0",
|
|
1692
|
+
maxLength: QUICK_LABEL_MAX,
|
|
1693
|
+
spellCheck: false,
|
|
1694
|
+
onChange: (event) => {
|
|
1695
|
+
update(row2.id, { label: event.target.value });
|
|
1696
|
+
},
|
|
1697
|
+
style: { ...textInput, flex: "0 0 150px" }
|
|
1698
|
+
}
|
|
1699
|
+
),
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: 4, ...rowDesc, margin: 0, flex: "0 0 auto" }, children: [
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1702
|
+
"input",
|
|
1703
|
+
{
|
|
1704
|
+
type: "checkbox",
|
|
1705
|
+
checked: row2.always,
|
|
1706
|
+
style: { margin: 0, cursor: "pointer" },
|
|
1707
|
+
onChange: (event) => {
|
|
1708
|
+
update(row2.id, { always: event.target.checked });
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
),
|
|
1712
|
+
"\u9ED8\u8BA4\u63D2\u5165"
|
|
1713
|
+
] }),
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 } }),
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0A\u79FB", onClick: () => {
|
|
1716
|
+
move(index, -1);
|
|
1717
|
+
}, children: "\u2191" }),
|
|
1718
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0B\u79FB", onClick: () => {
|
|
1719
|
+
move(index, 1);
|
|
1720
|
+
}, children: "\u2193" }),
|
|
1721
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5220\u9664\u8FD9\u6761", onClick: () => {
|
|
1722
|
+
remove(row2.id);
|
|
1723
|
+
}, children: "\u2715" })
|
|
1724
|
+
] }),
|
|
1725
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1726
|
+
"textarea",
|
|
1727
|
+
{
|
|
1728
|
+
value: row2.prompt,
|
|
1729
|
+
placeholder: "\u63D0\u793A\u8BCD\u6B63\u6587\uFF1A\u70B9\u51FB\u8BE5\u6761\u76EE\u65F6\u63D2\u5165\u8F93\u5165\u6846\uFF1B\u52FE\u4E86\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u5219\u5728\u53D1\u9001\u65F6\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E",
|
|
1730
|
+
maxLength: QUICK_TEXT_MAX,
|
|
1731
|
+
spellCheck: false,
|
|
1732
|
+
rows: Math.min(4, Math.max(2, Math.ceil(row2.prompt.length / 46))),
|
|
1733
|
+
onChange: (event) => {
|
|
1734
|
+
update(row2.id, { prompt: event.target.value });
|
|
1735
|
+
},
|
|
1736
|
+
style: { ...textInput, resize: "vertical", fontFamily: "inherit", lineHeight: 1.5 }
|
|
1737
|
+
}
|
|
1738
|
+
)
|
|
1739
|
+
]
|
|
1740
|
+
},
|
|
1741
|
+
row2.id
|
|
1742
|
+
)),
|
|
1743
|
+
rows.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: rowDesc, children: "\u8FD8\u6CA1\u6709\u6761\u76EE\u3002\u70B9\u4E0B\u9762\u7684\u300C+ \u6DFB\u52A0\u4E00\u6761\u300D\u5F00\u59CB\u5EFA\u81EA\u5DF1\u7684\u5FEB\u6377\u6307\u4EE4\u3002" }),
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
|
|
1745
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: add, children: "+ \u6DFB\u52A0\u4E00\u6761" }),
|
|
1746
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1747
|
+
"button",
|
|
1748
|
+
{
|
|
1749
|
+
type: "button",
|
|
1750
|
+
style: dirty ? pillActive : pill,
|
|
1751
|
+
onClick: save,
|
|
1752
|
+
disabled: !dirty,
|
|
1753
|
+
children: dirty ? "\u4FDD\u5B58\u4FEE\u6539" : "\u5DF2\u4FDD\u5B58"
|
|
1754
|
+
}
|
|
1755
|
+
),
|
|
1756
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: rowDesc, children: [
|
|
1757
|
+
"\u5171 ",
|
|
1758
|
+
rows.length,
|
|
1759
|
+
" / ",
|
|
1760
|
+
QUICK_PROMPT_MAX,
|
|
1761
|
+
" \u6761 \xB7 \u52FE\u4E86\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\u7684\uFF1A",
|
|
1762
|
+
rows.filter((row2) => row2.always).length,
|
|
1763
|
+
" \u6761"
|
|
1764
|
+
] })
|
|
1765
|
+
] })
|
|
1766
|
+
] });
|
|
1767
|
+
}
|
|
1250
1768
|
function SettingsSection({ useLive, actions }) {
|
|
1251
1769
|
const settings = useLive((item) => item);
|
|
1252
1770
|
const [conflict, setConflict] = (0, import_react3.useState)(null);
|
|
@@ -1265,6 +1783,8 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1265
1783
|
const menuSummary = settings.menuNative ? "\u5F53\u524D\uFF1A\u7CFB\u7EDF\u539F\u751F\u83DC\u5355\uFF08\u7C98\u8D34\u514D\u6388\u6743\uFF09" : `\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49\u83DC\u5355 \xB7 ${menuEnabled} / ${MENU_ITEMS.length} \u9879\u5F00\u542F`;
|
|
1266
1784
|
const panelSummary = `\u5BFC\u822A\u6EDA\u52A8 ${settings.panelScroll ? "\u5F00" : "\u5173"} \xB7 \u8FB9\u7F18\u7F29\u653E ${settings.panelResize ? "\u5F00" : "\u5173"} \xB7 ${settings.panelWidth}\xD7${settings.panelHeight}`;
|
|
1267
1785
|
const headerSummary = settings.headerEnabled ? settings.headerStatus === "" ? "\u5DF2\u542F\u7528" : settings.headerStatus : "\u672A\u542F\u7528";
|
|
1786
|
+
const alwaysCount = settings.quickPrompts.filter((item) => item.always).length;
|
|
1787
|
+
const quickSummary = `${settings.quickPrompts.length} \u6761 \xB7 \u9ED8\u8BA4\u63D2\u5165 ${alwaysCount} \u6761 \xB7 \u4F18\u5316\u6863\u4F4D ${OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.label ?? "\u9AD8\u7EA7"}`;
|
|
1268
1788
|
const headerStatusText = settings.headerEnabled ? settings.headerStatus === "" ? "\u7B49\u5F85\u9996\u6B21\u5199\u5165\u2026" : settings.headerStatus : "\u672A\u542F\u7528\uFF08\u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u5199\u5165\uFF09";
|
|
1269
1789
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "4px 2px" }, children: [
|
|
1270
1790
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dsh-ux-card", children: [
|
|
@@ -1372,6 +1892,54 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1372
1892
|
) })
|
|
1373
1893
|
] })
|
|
1374
1894
|
] }),
|
|
1895
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u5FEB\u6377\u6307\u4EE4", summary: quickSummary, children: [
|
|
1896
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: bodyLead, children: "\u8F93\u5165\u6846\u5DE5\u5177\u884C\u91CC\u90A3\u4E2A\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\u70B9\u5F00\u5C31\u662F\u8FD9\u5F20\u6E05\u5355\uFF1A\u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\uFF1B \u6761\u76EE\u53F3\u4FA7\u52FE\u4E0A\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF0C\u5219\u5728\u4F60**\u70B9\u53D1\u9001\u65F6**\u628A\u8FD9\u6761\u63D0\u793A\u8BCD\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F**\u672B\u5C3E** \u4E00\u8D77\u53D1\u51FA\u53BB\uFF08\u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\uFF09\u3002 \u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4F1A\u7528\u53E6\u4E00\u4E2A AI \u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C \u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\uFF08Ctrl+Z \u53EF\u8FD8\u539F\uFF09\u2014\u2014\u4E0D\u4F1A\u6C61\u67D3\u5F53\u524D\u5BF9\u8BDD\uFF0C\u4E5F\u4E0D\u5360\u4F60\u7684\u5BF9\u8BDD\u8F6E\u6B21\u3002" }),
|
|
1897
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
|
|
1898
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
|
|
1899
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u4F18\u5316\u5F3A\u5EA6" }),
|
|
1900
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.hint ?? "" })
|
|
1901
|
+
] }),
|
|
1902
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1903
|
+
"button",
|
|
1904
|
+
{
|
|
1905
|
+
type: "button",
|
|
1906
|
+
title: item.hint,
|
|
1907
|
+
style: settings.optimizerTier === item.id ? pillActive : pill,
|
|
1908
|
+
onClick: () => {
|
|
1909
|
+
actions.setField(OPTIMIZER_TIER_FIELD, item.id);
|
|
1910
|
+
},
|
|
1911
|
+
children: item.label
|
|
1912
|
+
},
|
|
1913
|
+
item.id
|
|
1914
|
+
)) })
|
|
1915
|
+
] }),
|
|
1916
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
|
|
1917
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
|
|
1918
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u5FEB\u6377\u6307\u4EE4\u6E05\u5355" }),
|
|
1919
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: "\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\uFF1B\u6539\u5B8C\u8BB0\u5F97\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u3002" })
|
|
1920
|
+
] }),
|
|
1921
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1922
|
+
QuickPromptsEditor,
|
|
1923
|
+
{
|
|
1924
|
+
items: settings.quickPrompts,
|
|
1925
|
+
onSave: (next) => {
|
|
1926
|
+
actions.setField(QUICK_PROMPTS_FIELD, next);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
),
|
|
1930
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1931
|
+
"button",
|
|
1932
|
+
{
|
|
1933
|
+
type: "button",
|
|
1934
|
+
style: pill,
|
|
1935
|
+
onClick: () => {
|
|
1936
|
+
actions.clearField(QUICK_PROMPTS_FIELD);
|
|
1937
|
+
},
|
|
1938
|
+
children: "\u6062\u590D\u5185\u7F6E 9 \u6761"
|
|
1939
|
+
}
|
|
1940
|
+
) })
|
|
1941
|
+
] })
|
|
1942
|
+
] }),
|
|
1375
1943
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u8BBE\u7F6E\u9762\u677F", summary: panelSummary, children: [
|
|
1376
1944
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: bodyLead, children: "\u63D2\u4EF6\u88C5\u5F97\u591A\u65F6\u8BBE\u7F6E\u6761\u76EE\u5F88\u957F\uFF1A\u5F00\u542F\u300C\u5BFC\u822A\u53EF\u6EDA\u52A8\u300D\u540E\uFF0C\u5DE6\u4FA7\u5BFC\u822A\u5728\u6EA2\u51FA\u65F6\u4F1A\u51FA\u73B0\u6EDA\u52A8\u6761\u3002 \u5F00\u542F\u300C\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u300D\u540E\uFF0C\u628A\u9F20\u6807\u79FB\u5230\u8BBE\u7F6E\u9762\u677F\u7684\u8FB9\u6216\u89D2\u4E0A\uFF08\u51FA\u73B0\u9AD8\u4EAE\u6216\u5149\u6807\u53D8\u5316\uFF09\u62D6\u52A8\u5373\u53EF\u6539\u53D8\u9762\u677F\u5927\u5C0F\uFF0C \u5C3A\u5BF8\u4F1A\u8BB0\u4F4F\uFF0C\u4E0B\u6B21\u6253\u5F00\u4FDD\u6301\u3002" }),
|
|
1377
1945
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -1487,9 +2055,9 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1487
2055
|
TextFieldRow,
|
|
1488
2056
|
{
|
|
1489
2057
|
title: "\u4F5C\u7528\u8DEF\u7531",
|
|
1490
|
-
desc: "\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D opencode \
|
|
2058
|
+
desc: "\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u540D\u5B57\u4EE5 opencode \u5F00\u5934\uFF0C\u6216 baseURL \u6307\u5411 opencode.ai\uFF09",
|
|
1491
2059
|
value: settings.headerRoutes,
|
|
1492
|
-
placeholder: "\u7559\u7A7A = \u81EA\u52A8\uFF08opencode
|
|
2060
|
+
placeholder: "\u7559\u7A7A = \u81EA\u52A8\uFF08opencode* \u6216 opencode.ai \u7AEF\u70B9\uFF09",
|
|
1493
2061
|
maxLength: HEADER_VALUE_MAX,
|
|
1494
2062
|
onChange: (next) => {
|
|
1495
2063
|
actions.setField(HEADER_ROUTES_FIELD, next);
|
|
@@ -1505,6 +2073,232 @@ function SettingsSection({ useLive, actions }) {
|
|
|
1505
2073
|
] });
|
|
1506
2074
|
}
|
|
1507
2075
|
|
|
2076
|
+
// src/client/QuickCommandsButton.tsx
|
|
2077
|
+
var import_react4 = require("react");
|
|
2078
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2079
|
+
function QuickCommandsButton({
|
|
2080
|
+
useInput,
|
|
2081
|
+
inputActions,
|
|
2082
|
+
sessionId,
|
|
2083
|
+
useLive,
|
|
2084
|
+
usePanel,
|
|
2085
|
+
actions
|
|
2086
|
+
}) {
|
|
2087
|
+
const settings = useLive((item) => item);
|
|
2088
|
+
const anchor = usePanel((item) => item);
|
|
2089
|
+
const draft = useInput((state2) => state2.draft);
|
|
2090
|
+
const ref = (0, import_react4.useRef)(null);
|
|
2091
|
+
(0, import_react4.useEffect)(() => {
|
|
2092
|
+
const sid = typeof sessionId === "string" ? sessionId : "";
|
|
2093
|
+
publishInputBridge({
|
|
2094
|
+
actions: inputActions ?? null,
|
|
2095
|
+
draft: typeof draft === "string" ? draft : "",
|
|
2096
|
+
sessionId: sid
|
|
2097
|
+
});
|
|
2098
|
+
return () => {
|
|
2099
|
+
releaseInputBridge(sid);
|
|
2100
|
+
};
|
|
2101
|
+
}, [inputActions, draft, sessionId]);
|
|
2102
|
+
if (settings.enabled !== true) return null;
|
|
2103
|
+
const open = anchor !== null;
|
|
2104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2105
|
+
"button",
|
|
2106
|
+
{
|
|
2107
|
+
ref,
|
|
2108
|
+
type: "button",
|
|
2109
|
+
className: QUICK_BUTTON_CLASS,
|
|
2110
|
+
"aria-haspopup": "dialog",
|
|
2111
|
+
"aria-expanded": open,
|
|
2112
|
+
title: "\u5FEB\u6377\u6307\u4EE4\uFF1A\u4E00\u952E\u63D2\u5165\u5E38\u7528\u63D0\u793A\u8BCD\uFF0C\u6216\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4F18\u5316\u6210\u4E00\u6761\u6E05\u6670\u7684\u6307\u4EE4",
|
|
2113
|
+
onMouseDown: (event) => {
|
|
2114
|
+
event.preventDefault();
|
|
2115
|
+
},
|
|
2116
|
+
onClick: () => {
|
|
2117
|
+
const rect = ref.current?.getBoundingClientRect();
|
|
2118
|
+
actions.toggle({
|
|
2119
|
+
left: rect?.left ?? 0,
|
|
2120
|
+
bottom: rect?.bottom ?? 0,
|
|
2121
|
+
width: rect?.width ?? 0
|
|
2122
|
+
});
|
|
2123
|
+
},
|
|
2124
|
+
children: [
|
|
2125
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2126
|
+
"svg",
|
|
2127
|
+
{
|
|
2128
|
+
viewBox: "0 0 16 16",
|
|
2129
|
+
width: "12",
|
|
2130
|
+
height: "12",
|
|
2131
|
+
"aria-hidden": true,
|
|
2132
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2133
|
+
"path",
|
|
2134
|
+
{
|
|
2135
|
+
d: "M9.2 1.2 3.4 9.1h3.5l-0.9 5.7 6-8.1H8.4l0.8-5.5Z",
|
|
2136
|
+
fill: "currentColor"
|
|
2137
|
+
}
|
|
2138
|
+
)
|
|
2139
|
+
}
|
|
2140
|
+
),
|
|
2141
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u5FEB\u6377\u6307\u4EE4" })
|
|
2142
|
+
]
|
|
2143
|
+
}
|
|
2144
|
+
);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
// src/client/QuickCommandsPanel.tsx
|
|
2148
|
+
var import_react5 = require("react");
|
|
2149
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2150
|
+
var MARGIN = 8;
|
|
2151
|
+
var GAP = 8;
|
|
2152
|
+
function QuickCommandsPanel({
|
|
2153
|
+
useLive,
|
|
2154
|
+
usePanel,
|
|
2155
|
+
useBusy,
|
|
2156
|
+
useNotice,
|
|
2157
|
+
actions
|
|
2158
|
+
}) {
|
|
2159
|
+
const settings = useLive((item) => item);
|
|
2160
|
+
const anchor = usePanel((item) => item);
|
|
2161
|
+
const busy = useBusy((item) => item);
|
|
2162
|
+
const notice = useNotice((item) => item);
|
|
2163
|
+
const ref = (0, import_react5.useRef)(null);
|
|
2164
|
+
const [position, setPosition] = (0, import_react5.useState)(null);
|
|
2165
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
2166
|
+
if (anchor === null) {
|
|
2167
|
+
setPosition(null);
|
|
2168
|
+
return;
|
|
2169
|
+
}
|
|
2170
|
+
const el = ref.current;
|
|
2171
|
+
const height = el === null ? 320 : el.getBoundingClientRect().height;
|
|
2172
|
+
const width = el === null ? 420 : el.getBoundingClientRect().width;
|
|
2173
|
+
const left = Math.max(MARGIN, Math.min(anchor.left, window.innerWidth - width - MARGIN));
|
|
2174
|
+
const above = anchor.bottom - height - GAP;
|
|
2175
|
+
const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN);
|
|
2176
|
+
setPosition({ left, top: Math.max(MARGIN, top) });
|
|
2177
|
+
}, [anchor?.left, anchor?.bottom, settings.quickPrompts.length, busy]);
|
|
2178
|
+
(0, import_react5.useEffect)(() => {
|
|
2179
|
+
if (anchor === null) return;
|
|
2180
|
+
const onPointerDown = (event) => {
|
|
2181
|
+
if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return;
|
|
2182
|
+
if (event.target instanceof Element && event.target.closest(".composer-ux-quick-button") !== null) return;
|
|
2183
|
+
actions.close();
|
|
2184
|
+
};
|
|
2185
|
+
const onEscape = (event) => {
|
|
2186
|
+
if (event.key !== "Escape") return;
|
|
2187
|
+
event.preventDefault();
|
|
2188
|
+
event.stopPropagation();
|
|
2189
|
+
actions.close();
|
|
2190
|
+
};
|
|
2191
|
+
window.addEventListener("pointerdown", onPointerDown, true);
|
|
2192
|
+
window.addEventListener("keydown", onEscape, true);
|
|
2193
|
+
window.addEventListener("resize", actions.close);
|
|
2194
|
+
return () => {
|
|
2195
|
+
window.removeEventListener("pointerdown", onPointerDown, true);
|
|
2196
|
+
window.removeEventListener("keydown", onEscape, true);
|
|
2197
|
+
window.removeEventListener("resize", actions.close);
|
|
2198
|
+
};
|
|
2199
|
+
}, [anchor === null, actions]);
|
|
2200
|
+
if (anchor === null) return null;
|
|
2201
|
+
const items = settings.quickPrompts;
|
|
2202
|
+
const tier = settings.optimizerTier;
|
|
2203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2204
|
+
"div",
|
|
2205
|
+
{
|
|
2206
|
+
ref,
|
|
2207
|
+
role: "dialog",
|
|
2208
|
+
"aria-label": "\u5FEB\u6377\u6307\u4EE4",
|
|
2209
|
+
style: { ...quickPanel, left: position?.left ?? anchor.left, top: position?.top ?? anchor.bottom },
|
|
2210
|
+
children: [
|
|
2211
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelHead, children: [
|
|
2212
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelTitleRow, children: [
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickPanelTitle, children: "\u5FEB\u6377\u6307\u4EE4" }),
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: quickTierRow, role: "group", "aria-label": "\u4F18\u5316\u5F3A\u5EA6", children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2215
|
+
"button",
|
|
2216
|
+
{
|
|
2217
|
+
type: "button",
|
|
2218
|
+
title: item.hint,
|
|
2219
|
+
"aria-pressed": tier === item.id,
|
|
2220
|
+
style: tier === item.id ? quickTierButtonActive : quickTierButton,
|
|
2221
|
+
onMouseDown: (event) => {
|
|
2222
|
+
event.preventDefault();
|
|
2223
|
+
},
|
|
2224
|
+
onClick: () => {
|
|
2225
|
+
actions.setTier(item.id);
|
|
2226
|
+
},
|
|
2227
|
+
children: item.label
|
|
2228
|
+
},
|
|
2229
|
+
item.id
|
|
2230
|
+
)) })
|
|
2231
|
+
] }),
|
|
2232
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2233
|
+
"button",
|
|
2234
|
+
{
|
|
2235
|
+
type: "button",
|
|
2236
|
+
disabled: busy,
|
|
2237
|
+
title: "\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4EA4\u7ED9\u53E6\u4E00\u4E2A AI \u6574\u7406\u6210\u4E00\u6761\u53EF\u4EE5\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C\u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846",
|
|
2238
|
+
style: busy ? quickPrimaryButtonDisabled : quickPrimaryButton,
|
|
2239
|
+
onMouseDown: (event) => {
|
|
2240
|
+
event.preventDefault();
|
|
2241
|
+
},
|
|
2242
|
+
onClick: () => {
|
|
2243
|
+
actions.optimize();
|
|
2244
|
+
},
|
|
2245
|
+
children: [
|
|
2246
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": true, children: "\u2728" }),
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: busy ? "\u4F18\u5316\u4E2D\u2026" : "\u4F18\u5316\u63D0\u793A\u8BCD" })
|
|
2248
|
+
]
|
|
2249
|
+
}
|
|
2250
|
+
)
|
|
2251
|
+
] }),
|
|
2252
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickList, children: [
|
|
2253
|
+
items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickEmpty, children: [
|
|
2254
|
+
"\u8FD8\u6CA1\u6709\u5FEB\u6377\u6307\u4EE4\u3002",
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("br", {}),
|
|
2256
|
+
"\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u300D\u91CC\u6DFB\u52A0\u3002"
|
|
2257
|
+
] }),
|
|
2258
|
+
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
2259
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2260
|
+
"button",
|
|
2261
|
+
{
|
|
2262
|
+
type: "button",
|
|
2263
|
+
title: item.prompt,
|
|
2264
|
+
style: quickItem,
|
|
2265
|
+
onMouseDown: (event) => {
|
|
2266
|
+
event.preventDefault();
|
|
2267
|
+
},
|
|
2268
|
+
onClick: () => {
|
|
2269
|
+
actions.insert(item.prompt);
|
|
2270
|
+
},
|
|
2271
|
+
children: [
|
|
2272
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickItemLabel, children: item.label }),
|
|
2273
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickItemPreview, children: item.prompt.replace(/\s+/g, " ") })
|
|
2274
|
+
]
|
|
2275
|
+
}
|
|
2276
|
+
),
|
|
2277
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: quickAlwaysLabel, title: "\u52FE\u4E0A\u540E\uFF0C\u70B9\u53D1\u9001\u65F6\u8FD9\u6761\u63D0\u793A\u8BCD\u4F1A\u81EA\u52A8\u9644\u52A0\u5230\u4F60\u7684\u6D88\u606F\u672B\u5C3E", children: [
|
|
2278
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2279
|
+
"input",
|
|
2280
|
+
{
|
|
2281
|
+
type: "checkbox",
|
|
2282
|
+
style: quickAlwaysBox,
|
|
2283
|
+
checked: item.always,
|
|
2284
|
+
onChange: (event) => {
|
|
2285
|
+
actions.setAlways(item.id, event.target.checked);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
),
|
|
2289
|
+
"\u9ED8\u8BA4\u63D2\u5165"
|
|
2290
|
+
] })
|
|
2291
|
+
] }, item.id))
|
|
2292
|
+
] }),
|
|
2293
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelFoot, children: [
|
|
2294
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickNotice, role: "status", children: notice }),
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickFootHint, children: "\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C" })
|
|
2296
|
+
] })
|
|
2297
|
+
]
|
|
2298
|
+
}
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2301
|
+
|
|
1508
2302
|
// src/client.tsx
|
|
1509
2303
|
var name = "composer-ux";
|
|
1510
2304
|
var inject = ["slots", "settingsScope"];
|
|
@@ -1513,6 +2307,9 @@ function apply(ctx) {
|
|
|
1513
2307
|
const scope = ctx.settingsScope.bind({ namespace: NAMESPACE });
|
|
1514
2308
|
const live = (0, import_dsh_client_store.createSnapshotStore)({ ...DEFAULT_SETTINGS });
|
|
1515
2309
|
const menu2 = (0, import_dsh_client_store.createSnapshotStore)(null);
|
|
2310
|
+
const panel = (0, import_dsh_client_store.createSnapshotStore)(null);
|
|
2311
|
+
const optimizing = (0, import_dsh_client_store.createSnapshotStore)(false);
|
|
2312
|
+
const panelNotice = (0, import_dsh_client_store.createSnapshotStore)("");
|
|
1516
2313
|
const sync = () => {
|
|
1517
2314
|
const snapshot = scope.getSnapshot();
|
|
1518
2315
|
live.set(snapshot.status === "ready" && snapshot.value !== void 0 ? { ...DEFAULT_SETTINGS, ...sanitizeSettings(snapshot.value) } : { ...DEFAULT_SETTINGS });
|
|
@@ -1544,12 +2341,81 @@ function apply(ctx) {
|
|
|
1544
2341
|
HEADER_ENABLED_FIELD,
|
|
1545
2342
|
HEADER_NAME_FIELD,
|
|
1546
2343
|
HEADER_VALUE_FIELD,
|
|
1547
|
-
HEADER_ROUTES_FIELD
|
|
2344
|
+
HEADER_ROUTES_FIELD,
|
|
2345
|
+
QUICK_PROMPTS_FIELD,
|
|
2346
|
+
OPTIMIZER_TIER_FIELD
|
|
1548
2347
|
].map((field) => ({ op: "unset", path: [field] }))
|
|
1549
2348
|
).catch((error) => {
|
|
1550
2349
|
console.error("[composer-ux] settings reset failed", error);
|
|
1551
2350
|
});
|
|
1552
2351
|
};
|
|
2352
|
+
let noticeTimer;
|
|
2353
|
+
const note = (message, ms = 4500) => {
|
|
2354
|
+
panelNotice.set(message);
|
|
2355
|
+
if (noticeTimer !== void 0) clearTimeout(noticeTimer);
|
|
2356
|
+
if (message === "") return;
|
|
2357
|
+
noticeTimer = setTimeout(() => {
|
|
2358
|
+
panelNotice.set("");
|
|
2359
|
+
}, ms);
|
|
2360
|
+
};
|
|
2361
|
+
ctx.effect(() => () => {
|
|
2362
|
+
if (noticeTimer !== void 0) clearTimeout(noticeTimer);
|
|
2363
|
+
}, "composer-ux: quick notice timer");
|
|
2364
|
+
const writeQuickPrompts = (next) => {
|
|
2365
|
+
setField(QUICK_PROMPTS_FIELD, next);
|
|
2366
|
+
};
|
|
2367
|
+
const quickActions = {
|
|
2368
|
+
toggle: (anchor) => {
|
|
2369
|
+
if (panel.getSnapshot() !== null) {
|
|
2370
|
+
panel.set(null);
|
|
2371
|
+
panelNotice.set("");
|
|
2372
|
+
return;
|
|
2373
|
+
}
|
|
2374
|
+
panelNotice.set("");
|
|
2375
|
+
panel.set(anchor);
|
|
2376
|
+
},
|
|
2377
|
+
close: () => {
|
|
2378
|
+
panel.set(null);
|
|
2379
|
+
panelNotice.set("");
|
|
2380
|
+
},
|
|
2381
|
+
insert: (text) => {
|
|
2382
|
+
if (insertIntoDraft(text)) focusComposer();
|
|
2383
|
+
},
|
|
2384
|
+
optimize: () => {
|
|
2385
|
+
if (optimizing.getSnapshot()) return;
|
|
2386
|
+
const draft = currentDraft();
|
|
2387
|
+
if (draft.trim() === "") {
|
|
2388
|
+
note("\u8F93\u5165\u6846\u662F\u7A7A\u7684\uFF1A\u5148\u5199\u70B9\u4EC0\u4E48\uFF0C\u518D\u70B9\u4F18\u5316");
|
|
2389
|
+
return;
|
|
2390
|
+
}
|
|
2391
|
+
optimizing.set(true);
|
|
2392
|
+
note("\u6B63\u5728\u4F18\u5316\u2026");
|
|
2393
|
+
void optimizeDraft(draft, live.getSnapshot().optimizerTier).then(
|
|
2394
|
+
(result) => {
|
|
2395
|
+
optimizing.set(false);
|
|
2396
|
+
if (!result.ok) {
|
|
2397
|
+
note(`\u4F18\u5316\u5931\u8D25\uFF1A${result.error ?? "\u672A\u77E5\u539F\u56E0"}`);
|
|
2398
|
+
return;
|
|
2399
|
+
}
|
|
2400
|
+
replaceDraft(result.text ?? "");
|
|
2401
|
+
focusComposer();
|
|
2402
|
+
note(`\u5DF2\u5199\u56DE\u8F93\u5165\u6846\uFF08${result.route}\uFF09\xB7 Ctrl+Z \u53EF\u8FD8\u539F`);
|
|
2403
|
+
},
|
|
2404
|
+
(error) => {
|
|
2405
|
+
optimizing.set(false);
|
|
2406
|
+
note(`\u4F18\u5316\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
|
|
2407
|
+
}
|
|
2408
|
+
);
|
|
2409
|
+
},
|
|
2410
|
+
setTier: (tier) => {
|
|
2411
|
+
setField(OPTIMIZER_TIER_FIELD, tier);
|
|
2412
|
+
},
|
|
2413
|
+
setAlways: (id, value) => {
|
|
2414
|
+
writeQuickPrompts(live.getSnapshot().quickPrompts.map(
|
|
2415
|
+
(item) => item.id === id ? { ...item, always: value } : item
|
|
2416
|
+
));
|
|
2417
|
+
}
|
|
2418
|
+
};
|
|
1553
2419
|
slots.inject("settings.section", () => slots.register({
|
|
1554
2420
|
name: "settings.section",
|
|
1555
2421
|
id: "composer-ux",
|
|
@@ -1583,7 +2449,26 @@ function apply(ctx) {
|
|
|
1583
2449
|
id: "composer-ux-panel-resize",
|
|
1584
2450
|
inject: () => ({ hooks: { live }, actions: { setField } })
|
|
1585
2451
|
}, PanelResizeHandles));
|
|
2452
|
+
slots.inject("conversation.input.right", () => slots.register({
|
|
2453
|
+
name: "conversation.input.right",
|
|
2454
|
+
id: "composer-ux-quick",
|
|
2455
|
+
order: 89,
|
|
2456
|
+
label: "\u5FEB\u6377\u6307\u4EE4",
|
|
2457
|
+
inject: () => ({
|
|
2458
|
+
hooks: { live, panel },
|
|
2459
|
+
actions: { toggle: quickActions.toggle }
|
|
2460
|
+
})
|
|
2461
|
+
}, QuickCommandsButton));
|
|
2462
|
+
slots.inject("shell.overlay", () => slots.register({
|
|
2463
|
+
name: "shell.overlay",
|
|
2464
|
+
id: "composer-ux-quick-panel",
|
|
2465
|
+
inject: () => ({
|
|
2466
|
+
hooks: { live, panel, busy: optimizing, notice: panelNotice },
|
|
2467
|
+
actions: quickActions
|
|
2468
|
+
})
|
|
2469
|
+
}, QuickCommandsPanel));
|
|
1586
2470
|
ctx.effect(() => installSettingsCardStyle(), "composer-ux: settings card style");
|
|
2471
|
+
ctx.effect(() => installQuickButtonStyle(), "composer-ux: quick button style");
|
|
1587
2472
|
ctx.effect(
|
|
1588
2473
|
() => installPanelStyle(
|
|
1589
2474
|
() => {
|
|
@@ -1601,8 +2486,8 @@ function apply(ctx) {
|
|
|
1601
2486
|
if (enabled && dispose === null) {
|
|
1602
2487
|
dispose = installInterceptors({
|
|
1603
2488
|
settings: () => live.getSnapshot(),
|
|
1604
|
-
setMenu: (
|
|
1605
|
-
menu2.set(
|
|
2489
|
+
setMenu: (state2) => {
|
|
2490
|
+
menu2.set(state2);
|
|
1606
2491
|
},
|
|
1607
2492
|
menuOpen: () => menu2.getSnapshot() !== null
|
|
1608
2493
|
});
|
|
@@ -1610,8 +2495,10 @@ function apply(ctx) {
|
|
|
1610
2495
|
dispose?.();
|
|
1611
2496
|
dispose = null;
|
|
1612
2497
|
menu2.set(null);
|
|
2498
|
+
panel.set(null);
|
|
1613
2499
|
}
|
|
1614
2500
|
if (live.getSnapshot().menuNative) menu2.set(null);
|
|
2501
|
+
if (!live.getSnapshot().enabled) panel.set(null);
|
|
1615
2502
|
};
|
|
1616
2503
|
syncInterceptors();
|
|
1617
2504
|
const unsubscribe = live.subscribe(syncInterceptors);
|