@co0ontty/wand 1.31.1 → 1.31.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web-ui/content/scripts.js +147 -45
- package/dist/web-ui/content/styles.css +146 -0
- package/package.json +1 -1
|
@@ -106,6 +106,13 @@
|
|
|
106
106
|
terminalHealthTimer: null,
|
|
107
107
|
lastTerminalResyncAt: 0,
|
|
108
108
|
terminalAutoFollow: true,
|
|
109
|
+
// 程序触发的滚动(wand 主动 scrollTo / wterm 内部因 _shouldScrollToBottom=true
|
|
110
|
+
// 拽 scrollTop=scrollHeight)落到 scroll handler 时会被误判为"用户滚回严格
|
|
111
|
+
// 底部",把 autoFollow 反转回 true,把用户刚 wheel 上滚的意图吞掉。
|
|
112
|
+
// 存"窗口截止时间戳"而非"开始时间戳":不同调用方按各自动画长度延长窗口
|
|
113
|
+
// (瞬时 120ms 覆盖一次 rAF + 事件分发;smooth 500ms 覆盖 Chromium smooth
|
|
114
|
+
// scroll 动画),多次调用用 Math.max 合并、不会被短窗口缩短。
|
|
115
|
+
terminalProgrammaticScrollUntil: 0,
|
|
109
116
|
terminalScrollIdleTimer: null,
|
|
110
117
|
terminalScrollIdleMs: 1800,
|
|
111
118
|
terminalScrollThreshold: 12,
|
|
@@ -311,6 +318,59 @@
|
|
|
311
318
|
})()
|
|
312
319
|
};
|
|
313
320
|
|
|
321
|
+
// ── 统一线性图标库 ──
|
|
322
|
+
// 替代页面里散落的 emoji(🛡 / ⌨ / 📁 / 🔔 …)。这些 emoji 在系统字体里渲染成
|
|
323
|
+
// 彩色卡通形态,与项目温暖米色 + 棕橙的复古主题视觉冲突明显。这里集中维护
|
|
324
|
+
// currentColor 线性 SVG,让图标跟随父级文字颜色变化,hover / active 状态自然继承。
|
|
325
|
+
var ICON_PATHS = {
|
|
326
|
+
// shape sets — 24x24 viewbox, currentColor stroke
|
|
327
|
+
shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>',
|
|
328
|
+
shieldCheck: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/>',
|
|
329
|
+
keyboard: '<rect x="2" y="6" width="20" height="12" rx="2"/><line x1="6" y1="10" x2="6" y2="10"/><line x1="10" y1="10" x2="10" y2="10"/><line x1="14" y1="10" x2="14" y2="10"/><line x1="18" y1="10" x2="18" y2="10"/><line x1="6" y1="14" x2="6" y2="14"/><line x1="18" y1="14" x2="18" y2="14"/><line x1="9" y1="14" x2="15" y2="14"/>',
|
|
330
|
+
cloud: '<path d="M17.5 19a4.5 4.5 0 1 0-1-8.9 6 6 0 0 0-11.5 1.7A4 4 0 0 0 6 19h11.5z"/>',
|
|
331
|
+
terminal: '<polyline points="4 7 9 12 4 17"/><line x1="12" y1="17" x2="20" y2="17"/>',
|
|
332
|
+
chat: '<path d="M21 12a8 8 0 0 1-12.9 6.3L3 20l1.7-5.1A8 8 0 1 1 21 12z"/>',
|
|
333
|
+
folder: '<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',
|
|
334
|
+
folderOpen:'<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2"/><path d="M3 9h18l-2 8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>',
|
|
335
|
+
trash: '<polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 13a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/>',
|
|
336
|
+
slash: '<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>',
|
|
337
|
+
chevronDown: '<polyline points="6 9 12 15 18 9"/>',
|
|
338
|
+
chevronUp: '<polyline points="6 15 12 9 18 15"/>',
|
|
339
|
+
chevronRight:'<polyline points="9 6 15 12 9 18"/>',
|
|
340
|
+
bell: '<path d="M18 16v-5a6 6 0 1 0-12 0v5l-2 2h16z"/><path d="M10 21a2 2 0 0 0 4 0"/>',
|
|
341
|
+
music: '<path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/>',
|
|
342
|
+
vibrate: '<rect x="9" y="4" width="6" height="16" rx="1"/><path d="M5 8v8"/><path d="M3 10v4"/><path d="M19 8v8"/><path d="M21 10v4"/>',
|
|
343
|
+
globe: '<circle cx="12" cy="12" r="9"/><line x1="3" y1="12" x2="21" y2="12"/><path d="M12 3a14 14 0 0 1 0 18"/><path d="M12 3a14 14 0 0 0 0 18"/>',
|
|
344
|
+
smartphone:'<rect x="6" y="2" width="12" height="20" rx="2.5"/><line x1="11" y1="18" x2="13" y2="18"/>',
|
|
345
|
+
desktop: '<rect x="3" y="4" width="18" height="12" rx="2"/><line x1="8" y1="20" x2="16" y2="20"/><line x1="12" y1="16" x2="12" y2="20"/>',
|
|
346
|
+
link: '<path d="M10 14a4.5 4.5 0 0 0 6.36 0l3-3a4.5 4.5 0 1 0-6.36-6.36l-1.42 1.41"/><path d="M14 10a4.5 4.5 0 0 0-6.36 0l-3 3a4.5 4.5 0 1 0 6.36 6.36l1.42-1.41"/>',
|
|
347
|
+
palette: '<circle cx="13.5" cy="6.5" r="1"/><circle cx="17.5" cy="10.5" r="1"/><circle cx="8.5" cy="7.5" r="1"/><circle cx="6.5" cy="12.5" r="1"/><path d="M12 3a9 9 0 1 0 0 18 1.5 1.5 0 0 0 1.1-2.5 1.5 1.5 0 0 1 1.1-2.5h2.3A4.5 4.5 0 0 0 21 11.5C21 6.8 16.97 3 12 3z"/>',
|
|
348
|
+
play: '<polygon points="6 4 20 12 6 20 6 4"/>',
|
|
349
|
+
inbox: '<polyline points="22 13 16 13 14 16 10 16 8 13 2 13"/><path d="M5 5h14l3 8v6a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-6z"/>',
|
|
350
|
+
zap: '<polygon points="13 2 4 14 11 14 10 22 20 9 13 9 13 2"/>',
|
|
351
|
+
wrench: '<path d="M14.7 6.3a4 4 0 1 1 4 4l-9 9-3.5 1 1-3.5 7.5-7.5z"/>',
|
|
352
|
+
edit: '<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4z"/>',
|
|
353
|
+
check: '<polyline points="5 12 10 17 19 7"/>',
|
|
354
|
+
signal: '<path d="M2 12a15 15 0 0 1 20 0"/><path d="M5 16a10 10 0 0 1 14 0"/><path d="M9 20a4 4 0 0 1 6 0"/><circle cx="12" cy="20" r="0.5" fill="currentColor"/>',
|
|
355
|
+
file: '<path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="14 3 14 9 20 9"/>',
|
|
356
|
+
image: '<rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="9" cy="10" r="1.5"/><polyline points="3 18 9 12 14 17 21 12"/>',
|
|
357
|
+
sigma: '<polyline points="18 4 6 4 13 12 6 20 18 20"/>'
|
|
358
|
+
};
|
|
359
|
+
// 渲染 SVG 字符串。size 默认 14,strokeWidth 默认 1.8(与现有 send/stop 按钮线宽接近)。
|
|
360
|
+
// cls 用于添加额外 class(如 .composer-pill-icon),便于 CSS 微调。
|
|
361
|
+
function iconSvg(name, opts) {
|
|
362
|
+
var path = ICON_PATHS[name];
|
|
363
|
+
if (!path) return "";
|
|
364
|
+
opts = opts || {};
|
|
365
|
+
var size = opts.size || 14;
|
|
366
|
+
var stroke = opts.strokeWidth || 1.8;
|
|
367
|
+
var cls = opts.cls ? ' class="' + opts.cls + '"' : "";
|
|
368
|
+
var fill = opts.fill || "none";
|
|
369
|
+
return '<svg' + cls + ' width="' + size + '" height="' + size + '" viewBox="0 0 24 24"' +
|
|
370
|
+
' fill="' + fill + '" stroke="currentColor" stroke-width="' + stroke + '"' +
|
|
371
|
+
' stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' + path + '</svg>';
|
|
372
|
+
}
|
|
373
|
+
|
|
314
374
|
// ── Structured session status bar (in-flight timer) ──
|
|
315
375
|
var _statusBarTimerId = null;
|
|
316
376
|
var _statusBarStartTime = 0;
|
|
@@ -1306,7 +1366,7 @@
|
|
|
1306
1366
|
app.innerHTML =
|
|
1307
1367
|
'<div class="boot-loading">' +
|
|
1308
1368
|
'<div class="boot-loading-card">' +
|
|
1309
|
-
'<div class="boot-loading-text" style="font-size:1.3em;margin-bottom:12px"
|
|
1369
|
+
'<div class="boot-loading-text" style="font-size:1.3em;margin-bottom:12px;display:flex;align-items:center;justify-content:center;gap:8px">' + iconSvg("signal", { size: 20, strokeWidth: 1.8 }) + '<span>无法连接到服务器</span></div>' +
|
|
1310
1370
|
'<div class="boot-loading-text" style="opacity:0.7;font-size:0.95em">请检查网络连接或确认 Wand 服务正在运行。</div>' +
|
|
1311
1371
|
'<button onclick="location.reload()" style="margin-top:18px;padding:8px 24px;border-radius:8px;border:1px solid rgba(150,118,85,0.3);background:rgba(255,255,255,0.8);cursor:pointer;font-size:0.95em">重试</button>' +
|
|
1312
1372
|
'</div>' +
|
|
@@ -1411,10 +1471,10 @@
|
|
|
1411
1471
|
'</span>' +
|
|
1412
1472
|
'<span class="approval-stats-popup" id="approval-stats-popup">' +
|
|
1413
1473
|
'<span class="approval-stats-popup-title">自动批准统计</span>' +
|
|
1414
|
-
(stats.command > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon"
|
|
1415
|
-
(stats.file > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon"
|
|
1416
|
-
(stats.tool > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon"
|
|
1417
|
-
'<span class="approval-stats-row approval-stats-row-total"><span class="approval-stats-row-icon"
|
|
1474
|
+
(stats.command > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon">' + iconSvg("terminal", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">命令执行</span><span class="approval-stats-row-count">' + stats.command + '</span></span>' : '') +
|
|
1475
|
+
(stats.file > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon">' + iconSvg("edit", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">文件写入</span><span class="approval-stats-row-count">' + stats.file + '</span></span>' : '') +
|
|
1476
|
+
(stats.tool > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon">' + iconSvg("wrench", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">其他工具</span><span class="approval-stats-row-count">' + stats.tool + '</span></span>' : '') +
|
|
1477
|
+
'<span class="approval-stats-row approval-stats-row-total"><span class="approval-stats-row-icon">' + iconSvg("sigma", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">合计</span><span class="approval-stats-row-count">' + stats.total + '</span></span>' +
|
|
1418
1478
|
'</span>' +
|
|
1419
1479
|
'</span>';
|
|
1420
1480
|
}
|
|
@@ -1680,20 +1740,20 @@
|
|
|
1680
1740
|
'<p class="blank-chat-subtitle">支持终端 PTY 会话与结构化 chat 会话,两种模式可并存。</p>' +
|
|
1681
1741
|
'<div class="blank-chat-tools">' +
|
|
1682
1742
|
'<button class="blank-chat-tool-btn" id="welcome-tool-claude" type="button">' +
|
|
1683
|
-
'<span class="tool-icon"
|
|
1743
|
+
'<span class="tool-icon">' + iconSvg("terminal", { size: 16, strokeWidth: 1.8 }) + '</span>新建终端会话' +
|
|
1684
1744
|
'</button>' +
|
|
1685
1745
|
'<button class="blank-chat-tool-btn" id="welcome-tool-codex" type="button">' +
|
|
1686
|
-
'<span class="tool-icon">⌘</span>新建 Codex 会话' +
|
|
1746
|
+
'<span class="tool-icon tool-icon-text">⌘</span>新建 Codex 会话' +
|
|
1687
1747
|
'</button>' +
|
|
1688
1748
|
'<button class="blank-chat-tool-btn" id="welcome-tool-structured" type="button">' +
|
|
1689
|
-
'<span class="tool-icon"
|
|
1749
|
+
'<span class="tool-icon">' + iconSvg("chat", { size: 16, strokeWidth: 1.8 }) + '</span>新建结构化会话' +
|
|
1690
1750
|
'</button>' +
|
|
1691
1751
|
'</div>' +
|
|
1692
1752
|
'<div class="blank-chat-cwd-wrap">' +
|
|
1693
1753
|
'<div class="blank-chat-cwd" id="blank-chat-cwd" role="button" tabindex="0" title="点击切换工作目录">' +
|
|
1694
|
-
'<span class="blank-chat-cwd-icon"
|
|
1754
|
+
'<span class="blank-chat-cwd-icon">' + iconSvg("folder", { size: 13, strokeWidth: 1.8 }) + '</span>' +
|
|
1695
1755
|
'<span class="blank-chat-cwd-path" id="blank-chat-cwd-path">' + escapeHtml(getEffectiveCwd()) + '</span>' +
|
|
1696
|
-
'<span class="blank-chat-cwd-arrow" id="blank-chat-cwd-arrow"
|
|
1756
|
+
'<span class="blank-chat-cwd-arrow" id="blank-chat-cwd-arrow">' + iconSvg("chevronDown", { size: 11, strokeWidth: 2 }) + '</span>' +
|
|
1697
1757
|
'</div>' +
|
|
1698
1758
|
'<div class="blank-chat-cwd-dropdown hidden" id="blank-chat-cwd-dropdown"></div>' +
|
|
1699
1759
|
'</div>' +
|
|
@@ -1771,7 +1831,7 @@
|
|
|
1771
1831
|
'</span>' +
|
|
1772
1832
|
'</span>' +
|
|
1773
1833
|
renderAutoApproveChip(selectedSession) +
|
|
1774
|
-
'<button id="terminal-interactive-toggle-top" class="composer-pill composer-pill-chip composer-interactive-toggle' + (state.terminalInteractive ? " active" : "") + '" type="button" title="切换终端交互模式"
|
|
1834
|
+
'<button id="terminal-interactive-toggle-top" class="composer-pill composer-pill-chip composer-interactive-toggle' + (state.terminalInteractive ? " active" : "") + '" type="button" title="切换终端交互模式" aria-label="切换终端交互模式">' + iconSvg("keyboard", { size: 13, strokeWidth: 1.7, cls: "composer-pill-icon" }) + '</button>' +
|
|
1775
1835
|
'<span class="permission-actions hidden" id="permission-actions">' +
|
|
1776
1836
|
'<span class="permission-actions-divider"></span>' +
|
|
1777
1837
|
'<span class="permission-actions-label" id="permission-actions-label">等待授权</span>' +
|
|
@@ -1806,7 +1866,7 @@
|
|
|
1806
1866
|
? (function() {
|
|
1807
1867
|
var bits = "";
|
|
1808
1868
|
if (selectedSession.provider === "claude" && selectedSession.claudeSessionId) {
|
|
1809
|
-
bits += '<span id="claude-session-id-badge" class="claude-session-id-badge" data-claude-id="' + escapeHtml(selectedSession.claudeSessionId) + '" title="点击复制 Claude 会话 ID"
|
|
1869
|
+
bits += '<span id="claude-session-id-badge" class="claude-session-id-badge" data-claude-id="' + escapeHtml(selectedSession.claudeSessionId) + '" title="点击复制 Claude 会话 ID">' + iconSvg("cloud", { size: 11, strokeWidth: 1.7, cls: "claude-session-id-icon" }) + '<span class="claude-session-id-text">' + escapeHtml(selectedSession.claudeSessionId.slice(0, 8)) + '</span></span>';
|
|
1810
1870
|
}
|
|
1811
1871
|
if (!isStructuredSession(selectedSession) && selectedSession.exitCode !== undefined && selectedSession.exitCode !== null) {
|
|
1812
1872
|
if (bits) bits += '<span class="session-info-separator">|</span>';
|
|
@@ -1827,12 +1887,12 @@
|
|
|
1827
1887
|
'</div>' +
|
|
1828
1888
|
'<div class="modal-body">' +
|
|
1829
1889
|
'<div class="folder-picker-quick-row">' +
|
|
1830
|
-
'<button class="folder-picker-quick-btn" data-path="/tmp"
|
|
1831
|
-
'<button class="folder-picker-quick-btn" data-path="/"
|
|
1890
|
+
'<button class="folder-picker-quick-btn btn-with-icon" data-path="/tmp">' + iconSvg("trash", { size: 13, strokeWidth: 1.7 }) + '<span>临时目录</span></button>' +
|
|
1891
|
+
'<button class="folder-picker-quick-btn btn-with-icon" data-path="/">' + iconSvg("folder", { size: 13, strokeWidth: 1.7 }) + '<span>根目录</span></button>' +
|
|
1832
1892
|
'</div>' +
|
|
1833
1893
|
'<div id="folder-breadcrumb" class="folder-breadcrumb"></div>' +
|
|
1834
1894
|
'<div class="folder-picker">' +
|
|
1835
|
-
'<span class="folder-picker-icon"
|
|
1895
|
+
'<span class="folder-picker-icon">' + iconSvg("folder", { size: 15, strokeWidth: 1.7 }) + '</span>' +
|
|
1836
1896
|
'<input type="text" id="folder-picker-input" class="folder-picker-input" value="" placeholder="输入或选择工作目录..." autocomplete="off" />' +
|
|
1837
1897
|
'</div>' +
|
|
1838
1898
|
'<div id="folder-picker-dropdown" class="folder-picker-dropdown hidden"></div>' +
|
|
@@ -2744,7 +2804,7 @@
|
|
|
2744
2804
|
'</div>' +
|
|
2745
2805
|
'<div class="settings-update-section" id="web-update-section">' +
|
|
2746
2806
|
'<div class="settings-section-head">' +
|
|
2747
|
-
'<span class="settings-section-icon"
|
|
2807
|
+
'<span class="settings-section-icon">' + iconSvg("globe", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2748
2808
|
'<div class="settings-section-head-text">' +
|
|
2749
2809
|
'<h4 class="settings-section-heading">Web 端</h4>' +
|
|
2750
2810
|
'<p class="settings-section-sub">浏览器访问的服务版本</p>' +
|
|
@@ -2773,7 +2833,7 @@
|
|
|
2773
2833
|
'</div>' +
|
|
2774
2834
|
'<div class="settings-update-section hidden" id="android-apk-section">' +
|
|
2775
2835
|
'<div class="settings-section-head">' +
|
|
2776
|
-
'<span class="settings-section-icon"
|
|
2836
|
+
'<span class="settings-section-icon">' + iconSvg("smartphone", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2777
2837
|
'<div class="settings-section-head-text">' +
|
|
2778
2838
|
'<h4 class="settings-section-heading">Android App</h4>' +
|
|
2779
2839
|
'<p class="settings-section-sub">原生客户端版本与 APK 下载</p>' +
|
|
@@ -2807,7 +2867,7 @@
|
|
|
2807
2867
|
'</div>' +
|
|
2808
2868
|
'<div class="settings-update-section hidden" id="macos-dmg-section">' +
|
|
2809
2869
|
'<div class="settings-section-head">' +
|
|
2810
|
-
'<span class="settings-section-icon"
|
|
2870
|
+
'<span class="settings-section-icon">' + iconSvg("desktop", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2811
2871
|
'<div class="settings-section-head-text">' +
|
|
2812
2872
|
'<h4 class="settings-section-heading">macOS App</h4>' +
|
|
2813
2873
|
'<p class="settings-section-sub">原生客户端版本与 DMG 下载</p>' +
|
|
@@ -2841,7 +2901,7 @@
|
|
|
2841
2901
|
'</div>' +
|
|
2842
2902
|
'<div class="settings-update-section" id="android-connect-section">' +
|
|
2843
2903
|
'<div class="settings-section-head">' +
|
|
2844
|
-
'<span class="settings-section-icon"
|
|
2904
|
+
'<span class="settings-section-icon">' + iconSvg("link", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2845
2905
|
'<div class="settings-section-head-text">' +
|
|
2846
2906
|
'<h4 class="settings-section-heading">App 连接码</h4>' +
|
|
2847
2907
|
'<p class="settings-section-sub">粘贴到 Android App 即可自动连接,无需密码;改密码后失效。</p>' +
|
|
@@ -2869,7 +2929,7 @@
|
|
|
2869
2929
|
'</div>' +
|
|
2870
2930
|
'<div class="settings-notification-section">' +
|
|
2871
2931
|
'<div class="settings-section-head">' +
|
|
2872
|
-
'<span class="settings-section-icon"
|
|
2932
|
+
'<span class="settings-section-icon">' + iconSvg("bell", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2873
2933
|
'<div class="settings-section-head-text">' +
|
|
2874
2934
|
'<h4 class="settings-section-heading">通知偏好</h4>' +
|
|
2875
2935
|
'<p class="settings-section-sub">提示音与应用内通知气泡</p>' +
|
|
@@ -2903,7 +2963,7 @@
|
|
|
2903
2963
|
'</div>' +
|
|
2904
2964
|
'<div id="native-sound-section" class="settings-notification-section hidden">' +
|
|
2905
2965
|
'<div class="settings-section-head">' +
|
|
2906
|
-
'<span class="settings-section-icon"
|
|
2966
|
+
'<span class="settings-section-icon">' + iconSvg("music", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2907
2967
|
'<div class="settings-section-head-text">' +
|
|
2908
2968
|
'<h4 class="settings-section-heading">系统通知铃声</h4>' +
|
|
2909
2969
|
'<p class="settings-section-sub">选择 Android 系统通知使用的铃声</p>' +
|
|
@@ -2911,12 +2971,12 @@
|
|
|
2911
2971
|
'</div>' +
|
|
2912
2972
|
'<div class="settings-row-with-action">' +
|
|
2913
2973
|
'<select id="native-sound-select" class="field-input field-select"></select>' +
|
|
2914
|
-
'<button id="native-sound-preview" class="btn btn-secondary btn-sm" type="button"
|
|
2974
|
+
'<button id="native-sound-preview" class="btn btn-secondary btn-sm btn-with-icon" type="button">' + iconSvg("play", { size: 11, strokeWidth: 1.8, fill: "currentColor" }) + '<span>试听</span></button>' +
|
|
2915
2975
|
'</div>' +
|
|
2916
2976
|
'</div>' +
|
|
2917
2977
|
'<div id="native-haptic-section" class="settings-notification-section hidden">' +
|
|
2918
2978
|
'<div class="settings-section-head">' +
|
|
2919
|
-
'<span class="settings-section-icon"
|
|
2979
|
+
'<span class="settings-section-icon">' + iconSvg("vibrate", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2920
2980
|
'<div class="settings-section-head-text">' +
|
|
2921
2981
|
'<h4 class="settings-section-heading">触感反馈</h4>' +
|
|
2922
2982
|
'<p class="settings-section-sub">按钮操作和任务完成时提供振动反馈</p>' +
|
|
@@ -2934,7 +2994,7 @@
|
|
|
2934
2994
|
'</div>' +
|
|
2935
2995
|
'<div class="settings-notification-section">' +
|
|
2936
2996
|
'<div class="settings-section-head">' +
|
|
2937
|
-
'<span class="settings-section-icon"
|
|
2997
|
+
'<span class="settings-section-icon">' + iconSvg("globe", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
2938
2998
|
'<div class="settings-section-head-text">' +
|
|
2939
2999
|
'<h4 class="settings-section-heading">浏览器通知</h4>' +
|
|
2940
3000
|
'<p class="settings-section-sub">来自系统通知中心的弹窗</p>' +
|
|
@@ -3052,7 +3112,7 @@
|
|
|
3052
3112
|
(typeof WandNative !== "undefined" && typeof WandNative.getAppIcon === "function" ?
|
|
3053
3113
|
'<div class="settings-app-icon-block">' +
|
|
3054
3114
|
'<div class="settings-section-head">' +
|
|
3055
|
-
'<span class="settings-section-icon"
|
|
3115
|
+
'<span class="settings-section-icon">' + iconSvg("palette", { size: 18, strokeWidth: 1.7 }) + '</span>' +
|
|
3056
3116
|
'<div class="settings-section-head-text">' +
|
|
3057
3117
|
'<h4 class="settings-section-heading">应用图标</h4>' +
|
|
3058
3118
|
'<p class="settings-section-sub">选择 App 启动器图标,返回桌面后生效</p>' +
|
|
@@ -4975,9 +5035,9 @@
|
|
|
4975
5035
|
// 新建会话时显示简化的目录选择器(单行紧凑设计)
|
|
4976
5036
|
return '<div class="folder-picker-compact" id="folder-picker-container">' +
|
|
4977
5037
|
'<div class="folder-picker-compact-row">' +
|
|
4978
|
-
'<span class="folder-picker-compact-icon"
|
|
5038
|
+
'<span class="folder-picker-compact-icon">' + iconSvg("folder", { size: 13, strokeWidth: 1.7 }) + '</span>' +
|
|
4979
5039
|
'<input type="text" id="folder-picker-input" class="folder-picker-compact-input" value="' + escapeHtml(currentDir) + '" placeholder="工作目录" autocomplete="off" />' +
|
|
4980
|
-
'<button type="button" id="folder-picker-toggle" class="folder-picker-toggle" title="选择目录"
|
|
5040
|
+
'<button type="button" id="folder-picker-toggle" class="folder-picker-toggle" title="选择目录" aria-label="选择目录">' + iconSvg("chevronDown", { size: 11, strokeWidth: 2 }) + '</button>' +
|
|
4981
5041
|
'</div>' +
|
|
4982
5042
|
'<div id="folder-picker-dropdown" class="folder-picker-dropdown hidden">' +
|
|
4983
5043
|
'<div class="folder-picker-quick-row">' +
|
|
@@ -5007,7 +5067,7 @@
|
|
|
5007
5067
|
}
|
|
5008
5068
|
|
|
5009
5069
|
return '<div class="working-dir-indicator" id="working-dir-indicator" title="' + escapeHtml(displayDir) + '" data-path="' + escapeHtml(displayDir) + '">' +
|
|
5010
|
-
'<span class="working-dir-indicator-icon"
|
|
5070
|
+
'<span class="working-dir-indicator-icon">' + iconSvg("folder", { size: 12, strokeWidth: 1.7 }) + '</span>' +
|
|
5011
5071
|
'<span class="working-dir-indicator-path">' + escapeHtml(displayPath) + '</span>' +
|
|
5012
5072
|
'</div>';
|
|
5013
5073
|
}
|
|
@@ -7081,6 +7141,16 @@
|
|
|
7081
7141
|
if (!state.terminal) return;
|
|
7082
7142
|
var viewport = getTerminalViewport();
|
|
7083
7143
|
if (!viewport) return;
|
|
7144
|
+
// 打"程序触发滚动"窗口:紧跟着的 scroll 事件是 wand 自己拽出来的,
|
|
7145
|
+
// scroll handler 在窗口内跳过 autoFollow 修改,避免"程序拽底 →
|
|
7146
|
+
// scroll 事件 → handler 看到在底 → autoFollow=true"的反馈环把
|
|
7147
|
+
// 用户刚 wheel 上滚的意图覆盖掉。smooth 模式 Chromium 滚动动画约
|
|
7148
|
+
// 300-500ms,瞬时滚动只需覆盖一次 rAF + 事件分发延迟。
|
|
7149
|
+
var windowMs = smooth ? 500 : 120;
|
|
7150
|
+
state.terminalProgrammaticScrollUntil = Math.max(
|
|
7151
|
+
state.terminalProgrammaticScrollUntil,
|
|
7152
|
+
Date.now() + windowMs
|
|
7153
|
+
);
|
|
7084
7154
|
if (smooth) {
|
|
7085
7155
|
viewport.scrollTo({ top: viewport.scrollHeight, behavior: "smooth" });
|
|
7086
7156
|
} else {
|
|
@@ -7487,7 +7557,36 @@
|
|
|
7487
7557
|
if (!state.wideParserState) state.wideParserState = createWideParserState();
|
|
7488
7558
|
var padded = widePadAnsi(data, state.wideParserState);
|
|
7489
7559
|
var framed = processSyncOutputFraming(padded);
|
|
7560
|
+
// wterm.write 内部用 5px 阈值判定"在底部",下一帧 _doRender 据此强制
|
|
7561
|
+
// scrollTop = scrollHeight。这与 wand 的 autoFollow("真正到底"才为
|
|
7562
|
+
// true,2px 阈值)独立,会把用户主动向上滚的几像素吞掉。覆写为 wand
|
|
7563
|
+
// 的 autoFollow 状态,让 autoFollow 成为唯一真相。
|
|
7564
|
+
//
|
|
7565
|
+
// 时序关键:必须在 terminal.write() 之前先覆写一次,否则 wterm 在 write
|
|
7566
|
+
// 内部解析 chunk 时可能同步触发 _doRender → 提前完成 scrollTop=scrollHeight,
|
|
7567
|
+
// write 之后再覆写就晚了一帧,用户上滚位置已被吞。write 之后再覆写一次
|
|
7568
|
+
// 兜底:wterm 在解析 newline / cursor move / scroll region 时可能把
|
|
7569
|
+
// _shouldScrollToBottom 改回 true。
|
|
7570
|
+
var follow = state.terminalAutoFollow !== false;
|
|
7571
|
+
if ("_shouldScrollToBottom" in terminal) {
|
|
7572
|
+
terminal._shouldScrollToBottom = follow;
|
|
7573
|
+
}
|
|
7490
7574
|
if (framed) terminal.write(framed);
|
|
7575
|
+
if ("_shouldScrollToBottom" in terminal) {
|
|
7576
|
+
terminal._shouldScrollToBottom = follow;
|
|
7577
|
+
}
|
|
7578
|
+
// wterm 按 follow=true 真的 scrollTop=scrollHeight 时会触发一次程序性的
|
|
7579
|
+
// scroll 事件 — 打窗口,让 scroll handler 不要误判为"用户滚回底部"。
|
|
7580
|
+
// **只在 follow=true 时打**:follow=false 时 wterm 不会拽底,没有程序事件
|
|
7581
|
+
// 要过滤;如果这里也打标,Claude 流式输出 chunk <120ms 一个会让窗口永
|
|
7582
|
+
// 不过期,scroll handler 永远 early return,用户哪怕滚回严格底部 autoFollow
|
|
7583
|
+
// 也回不到 true,再也走不出"上滚阅读"模式。
|
|
7584
|
+
if (follow) {
|
|
7585
|
+
state.terminalProgrammaticScrollUntil = Math.max(
|
|
7586
|
+
state.terminalProgrammaticScrollUntil,
|
|
7587
|
+
Date.now() + 120
|
|
7588
|
+
);
|
|
7589
|
+
}
|
|
7491
7590
|
// R6: 在 chunk 热路径上识别原地重绘序列(CSI nA/B/C/D/f/H/J/K),
|
|
7492
7591
|
// 节流安排一次 softResync 兜底。Claude 用相对光标位移重画菜单时,
|
|
7493
7592
|
// 如果 NEW-A 的 sync output buffer 因某种原因没拦截到完整帧(比如
|
|
@@ -7495,13 +7594,6 @@
|
|
|
7495
7594
|
// 错位。此 fallback 仅在真出现错位序列时触发,正常输出零开销。
|
|
7496
7595
|
// 与 R2 策略 A 配合:移除被动 5 处触发后,这是唯一的主动救场路径。
|
|
7497
7596
|
maybeScheduleResyncForChunk(data);
|
|
7498
|
-
// wterm.write 内部用 5px 阈值判定"在底部",下一帧 _doRender 据此强制
|
|
7499
|
-
// scrollTop = scrollHeight。这与 wand 的 autoFollow("真正到底"才为
|
|
7500
|
-
// true,2px 阈值)独立,会把用户主动向上滚的几像素吞掉。覆写为 wand
|
|
7501
|
-
// 的 autoFollow 状态,让 autoFollow 成为唯一真相。
|
|
7502
|
-
if ("_shouldScrollToBottom" in terminal) {
|
|
7503
|
-
terminal._shouldScrollToBottom = state.terminalAutoFollow !== false;
|
|
7504
|
-
}
|
|
7505
7597
|
}
|
|
7506
7598
|
|
|
7507
7599
|
function resetWideParserState() {
|
|
@@ -7919,6 +8011,16 @@
|
|
|
7919
8011
|
var viewport = getTerminalViewport();
|
|
7920
8012
|
if (viewport) {
|
|
7921
8013
|
state.terminalViewportScrollHandler = function() {
|
|
8014
|
+
// 程序触发的 scroll(wand 主动 scrollTo / wterm 内部
|
|
8015
|
+
// _doRender 因 _shouldScrollToBottom=true 拽 scrollTop=scrollHeight)
|
|
8016
|
+
// 也会进这里。如果不过滤,handler 会看到 isTerminalAtBottom()=true
|
|
8017
|
+
// 把 autoFollow 反转回 true,把用户刚上滚的意图吞掉,下一帧 chunk
|
|
8018
|
+
// 到达又被拽底,形成"上滚→拽底"反馈环。窗口长度由调用方按
|
|
8019
|
+
// 各自动画长度决定(瞬时 120ms / smooth 500ms)。
|
|
8020
|
+
if (Date.now() < state.terminalProgrammaticScrollUntil) {
|
|
8021
|
+
updateTerminalJumpToBottomButton();
|
|
8022
|
+
return;
|
|
8023
|
+
}
|
|
7922
8024
|
// 严格"真正到底"才恢复 autoFollow:避免 wheel 设 false 后被
|
|
7923
8025
|
// 紧接着的 scroll 事件因"接近底部 12px"而反转回 true。
|
|
7924
8026
|
if (isTerminalAtBottom()) {
|
|
@@ -8368,8 +8470,8 @@
|
|
|
8368
8470
|
if (isAutoApproveImpliedByMode(session)) return "";
|
|
8369
8471
|
var enabled = !!session.autoApprovePermissions;
|
|
8370
8472
|
return enabled
|
|
8371
|
-
? '<span id="auto-approve-toggle" class="composer-pill composer-pill-chip auto-approve-indicator active" title="自动批准已启用 — 点击关闭"
|
|
8372
|
-
: '<span id="auto-approve-toggle" class="composer-pill composer-pill-chip auto-approve-indicator" title="自动批准已关闭 — 点击开启"
|
|
8473
|
+
? '<span id="auto-approve-toggle" class="composer-pill composer-pill-chip auto-approve-indicator active" title="自动批准已启用 — 点击关闭">' + iconSvg("shieldCheck", { size: 12, strokeWidth: 1.7, cls: "composer-pill-icon" }) + '<span class="composer-pill-label">自动</span></span>'
|
|
8474
|
+
: '<span id="auto-approve-toggle" class="composer-pill composer-pill-chip auto-approve-indicator" title="自动批准已关闭 — 点击开启">' + iconSvg("shield", { size: 12, strokeWidth: 1.7, cls: "composer-pill-icon" }) + '<span class="composer-pill-label">手动</span></span>';
|
|
8373
8475
|
}
|
|
8374
8476
|
|
|
8375
8477
|
function fetchAvailableModels() {
|
|
@@ -11429,7 +11531,7 @@
|
|
|
11429
11531
|
var a = items[i];
|
|
11430
11532
|
var thumb = a.previewUrl
|
|
11431
11533
|
? '<img src="' + escapeHtml(a.previewUrl) + '" alt="">'
|
|
11432
|
-
: '<span class="att-icon"
|
|
11534
|
+
: '<span class="att-icon">' + iconSvg("file", { size: 13, strokeWidth: 1.7 }) + '</span>';
|
|
11433
11535
|
html += '<span class="attachment-pill" data-index="' + i + '">' +
|
|
11434
11536
|
thumb +
|
|
11435
11537
|
'<span class="att-name" title="' + escapeHtml(a.name) + '">' + escapeHtml(a.name) + '</span>' +
|
|
@@ -12428,7 +12530,7 @@
|
|
|
12428
12530
|
'</button>' +
|
|
12429
12531
|
'<div class="queue-bar-panel" data-queue-panel="1" role="region" aria-label="排队消息列表">' +
|
|
12430
12532
|
'<div class="queue-bar-panel-header">' +
|
|
12431
|
-
'<span class="queue-bar-panel-title"
|
|
12533
|
+
'<span class="queue-bar-panel-title">' + iconSvg("inbox", { size: 13, strokeWidth: 1.7, cls: "queue-bar-panel-title-icon" }) + '<span>排队中 (' + count + ')</span></span>' +
|
|
12432
12534
|
'<button type="button" class="queue-bar-clear" data-action="clear"' +
|
|
12433
12535
|
(count === 0 ? " disabled" : "") + '>清空</button>' +
|
|
12434
12536
|
'<button type="button" class="queue-bar-collapse" data-action="collapse" aria-label="收起">' +
|
|
@@ -16124,10 +16226,10 @@
|
|
|
16124
16226
|
'</span>' +
|
|
16125
16227
|
'<span class="approval-stats-popup" id="approval-stats-popup">' +
|
|
16126
16228
|
'<span class="approval-stats-popup-title">自动批准统计</span>' +
|
|
16127
|
-
(stats.command > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon"
|
|
16128
|
-
(stats.file > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon"
|
|
16129
|
-
(stats.tool > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon"
|
|
16130
|
-
'<span class="approval-stats-row approval-stats-row-total"><span class="approval-stats-row-icon"
|
|
16229
|
+
(stats.command > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon">' + iconSvg("terminal", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">命令执行</span><span class="approval-stats-row-count">' + stats.command + '</span></span>' : '') +
|
|
16230
|
+
(stats.file > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon">' + iconSvg("edit", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">文件写入</span><span class="approval-stats-row-count">' + stats.file + '</span></span>' : '') +
|
|
16231
|
+
(stats.tool > 0 ? '<span class="approval-stats-row"><span class="approval-stats-row-icon">' + iconSvg("wrench", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">其他工具</span><span class="approval-stats-row-count">' + stats.tool + '</span></span>' : '') +
|
|
16232
|
+
'<span class="approval-stats-row approval-stats-row-total"><span class="approval-stats-row-icon">' + iconSvg("sigma", { size: 12, strokeWidth: 1.8 }) + '</span><span class="approval-stats-row-label">合计</span><span class="approval-stats-row-count">' + stats.total + '</span></span>' +
|
|
16131
16233
|
'</span>';
|
|
16132
16234
|
// Pulse animation on the badge
|
|
16133
16235
|
var badge = container.querySelector(".approval-stats-badge");
|
|
@@ -16243,11 +16345,11 @@
|
|
|
16243
16345
|
if (enabled) {
|
|
16244
16346
|
toggle.className = base + " active";
|
|
16245
16347
|
toggle.title = "自动批准已启用 — 点击关闭";
|
|
16246
|
-
toggle.
|
|
16348
|
+
toggle.innerHTML = iconSvg("shieldCheck", { size: 12, strokeWidth: 1.7, cls: "composer-pill-icon" }) + '<span class="composer-pill-label">自动</span>';
|
|
16247
16349
|
} else {
|
|
16248
16350
|
toggle.className = base;
|
|
16249
16351
|
toggle.title = "自动批准已关闭 — 点击开启";
|
|
16250
|
-
toggle.
|
|
16352
|
+
toggle.innerHTML = iconSvg("shield", { size: 12, strokeWidth: 1.7, cls: "composer-pill-icon" }) + '<span class="composer-pill-label">手动</span>';
|
|
16251
16353
|
}
|
|
16252
16354
|
}
|
|
16253
16355
|
|
|
@@ -15644,4 +15644,150 @@
|
|
|
15644
15644
|
.wand-dialog-footer .btn { flex: 1 1 auto; }
|
|
15645
15645
|
}
|
|
15646
15646
|
|
|
15647
|
+
/* =====================================================================
|
|
15648
|
+
线性 SVG 图标适配层 —— 把散落各处的 emoji 换成 currentColor SVG 之后,
|
|
15649
|
+
这里集中处理"原本给文本字号 / line-height 的容器现在塞了一个 svg"
|
|
15650
|
+
的对齐问题。命名上沿用旧 class,只补尺寸与 flex 居中。
|
|
15651
|
+
===================================================================== */
|
|
15652
|
+
|
|
15653
|
+
/* 通用:任何 svg 在带 .btn-with-icon 的按钮里都做 inline-flex 8px gap */
|
|
15654
|
+
.btn-with-icon {
|
|
15655
|
+
display: inline-flex;
|
|
15656
|
+
align-items: center;
|
|
15657
|
+
gap: 6px;
|
|
15658
|
+
}
|
|
15659
|
+
.btn-with-icon > svg { flex-shrink: 0; }
|
|
15660
|
+
|
|
15661
|
+
/* composer pill 内的 svg 图标(自动批准 / 终端交互)—— 让 svg 沿基线对齐 */
|
|
15662
|
+
.composer-pill-icon {
|
|
15663
|
+
display: inline-block;
|
|
15664
|
+
vertical-align: -2px;
|
|
15665
|
+
}
|
|
15666
|
+
.composer-pill-label {
|
|
15667
|
+
display: inline-block;
|
|
15668
|
+
letter-spacing: 0.02em;
|
|
15669
|
+
}
|
|
15670
|
+
/* 终端交互按钮里只放 svg —— 撤销原来的字号微调(emoji 时代留下的) */
|
|
15671
|
+
.composer-interactive-toggle {
|
|
15672
|
+
font-size: 0.625rem;
|
|
15673
|
+
padding: 0 8px;
|
|
15674
|
+
min-height: 22px;
|
|
15675
|
+
}
|
|
15676
|
+
|
|
15677
|
+
/* settings section-head 圆角小徽章 —— 现在装 SVG,移除原 font-size */
|
|
15678
|
+
.settings-section-icon {
|
|
15679
|
+
font-size: 0;
|
|
15680
|
+
line-height: 0;
|
|
15681
|
+
}
|
|
15682
|
+
.settings-section-icon > svg { display: block; }
|
|
15683
|
+
|
|
15684
|
+
/* 空白首页 tool button 里的 svg */
|
|
15685
|
+
.blank-chat-tool-btn .tool-icon {
|
|
15686
|
+
display: inline-flex;
|
|
15687
|
+
align-items: center;
|
|
15688
|
+
justify-content: center;
|
|
15689
|
+
width: 18px;
|
|
15690
|
+
height: 18px;
|
|
15691
|
+
font-size: 1.125rem; /* 保留给 tool-icon-text 变体(Codex ⌘ 等) */
|
|
15692
|
+
}
|
|
15693
|
+
.blank-chat-tool-btn .tool-icon > svg { display: block; }
|
|
15694
|
+
.blank-chat-tool-btn .tool-icon-text {
|
|
15695
|
+
width: auto;
|
|
15696
|
+
height: auto;
|
|
15697
|
+
font-family: var(--font-mono);
|
|
15698
|
+
font-size: 1rem;
|
|
15699
|
+
line-height: 1;
|
|
15700
|
+
}
|
|
15701
|
+
|
|
15702
|
+
/* 空白首页 CWD 行的文件夹图标 + 下拉箭头 */
|
|
15703
|
+
.blank-chat-cwd-icon {
|
|
15704
|
+
display: inline-flex;
|
|
15705
|
+
align-items: center;
|
|
15706
|
+
justify-content: center;
|
|
15707
|
+
font-size: 0;
|
|
15708
|
+
line-height: 0;
|
|
15709
|
+
}
|
|
15710
|
+
.blank-chat-cwd-icon > svg { display: block; }
|
|
15711
|
+
.blank-chat-cwd-arrow {
|
|
15712
|
+
display: inline-flex;
|
|
15713
|
+
align-items: center;
|
|
15714
|
+
justify-content: center;
|
|
15715
|
+
font-size: 0;
|
|
15716
|
+
line-height: 0;
|
|
15717
|
+
transition: transform var(--transition-fast);
|
|
15718
|
+
}
|
|
15719
|
+
.blank-chat-cwd-arrow > svg { display: block; }
|
|
15720
|
+
|
|
15721
|
+
/* 文件夹选择器:模态框里 input 前的文件夹图标 + 快捷按钮 */
|
|
15722
|
+
.folder-picker-icon {
|
|
15723
|
+
display: inline-flex;
|
|
15724
|
+
align-items: center;
|
|
15725
|
+
justify-content: center;
|
|
15726
|
+
font-size: 0;
|
|
15727
|
+
line-height: 0;
|
|
15728
|
+
}
|
|
15729
|
+
.folder-picker-icon > svg { display: block; }
|
|
15730
|
+
.folder-picker-quick-btn.btn-with-icon { gap: 5px; }
|
|
15731
|
+
|
|
15732
|
+
/* Claude session id 徽章:icon + text */
|
|
15733
|
+
.claude-session-id-badge {
|
|
15734
|
+
display: inline-flex;
|
|
15735
|
+
align-items: center;
|
|
15736
|
+
gap: 4px;
|
|
15737
|
+
}
|
|
15738
|
+
.claude-session-id-icon { flex-shrink: 0; }
|
|
15739
|
+
.claude-session-id-text { font-family: var(--font-mono); }
|
|
15740
|
+
|
|
15741
|
+
/* 批准统计弹窗的行图标 —— 现在是 svg */
|
|
15742
|
+
.approval-stats-row-icon {
|
|
15743
|
+
display: inline-flex;
|
|
15744
|
+
align-items: center;
|
|
15745
|
+
justify-content: center;
|
|
15746
|
+
width: 14px;
|
|
15747
|
+
height: 14px;
|
|
15748
|
+
font-size: 0;
|
|
15749
|
+
line-height: 0;
|
|
15750
|
+
}
|
|
15751
|
+
.approval-stats-row-icon > svg { display: block; }
|
|
15752
|
+
|
|
15753
|
+
/* 附件 pill 缩略图 svg */
|
|
15754
|
+
.attachment-pill .att-icon > svg { display: block; }
|
|
15755
|
+
|
|
15756
|
+
/* 排队面板标题 (排队中) —— 现在 icon + text 用 inline-flex 排 */
|
|
15757
|
+
.queue-bar-panel-title {
|
|
15758
|
+
display: inline-flex;
|
|
15759
|
+
align-items: center;
|
|
15760
|
+
gap: 5px;
|
|
15761
|
+
}
|
|
15762
|
+
.queue-bar-panel-title-icon { flex-shrink: 0; }
|
|
15763
|
+
|
|
15764
|
+
/* 紧凑目录选择器(新建会话时显示的小条)的图标 + 折叠箭头 */
|
|
15765
|
+
.folder-picker-compact-icon {
|
|
15766
|
+
display: inline-flex;
|
|
15767
|
+
align-items: center;
|
|
15768
|
+
justify-content: center;
|
|
15769
|
+
font-size: 0;
|
|
15770
|
+
line-height: 0;
|
|
15771
|
+
}
|
|
15772
|
+
.folder-picker-compact-icon > svg { display: block; }
|
|
15773
|
+
.folder-picker-toggle {
|
|
15774
|
+
display: inline-flex;
|
|
15775
|
+
align-items: center;
|
|
15776
|
+
justify-content: center;
|
|
15777
|
+
font-size: 0;
|
|
15778
|
+
line-height: 0;
|
|
15779
|
+
}
|
|
15780
|
+
.folder-picker-toggle > svg { display: block; }
|
|
15781
|
+
.folder-picker-toggle.open { transform: rotate(180deg); }
|
|
15782
|
+
|
|
15783
|
+
/* 顶部工作目录指示器的小图标 */
|
|
15784
|
+
.working-dir-indicator-icon {
|
|
15785
|
+
display: inline-flex;
|
|
15786
|
+
align-items: center;
|
|
15787
|
+
justify-content: center;
|
|
15788
|
+
font-size: 0;
|
|
15789
|
+
line-height: 0;
|
|
15790
|
+
}
|
|
15791
|
+
.working-dir-indicator-icon > svg { display: block; }
|
|
15792
|
+
|
|
15647
15793
|
/* 结束标记 */
|