Skip to content

Commit 4ecf099

Browse files
committed
Refine viewer controls and turn navigation
1 parent fe4ab55 commit 4ecf099

6 files changed

Lines changed: 415 additions & 125 deletions

File tree

docs/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ Raw Inspector 的一次导航由 `RawInspectorController` 串联:更新 Store
309309

310310
System diff 只在用户按需打开时计算。小输入由 `system-diff-model.js` 使用有总行数、矩阵单元、字符数和单行长度上限的精确行级 LCS;任一上限被触发后,模型线性确认共同前后缀,并在至多 256 个动态内容块上计算指纹摘要,避免大 System 提示词在浏览器创建无界 `行数 × 行数` 矩阵或数千个 DOM 行。Renderer 只消费显式 DTO,并明确区分“行变化”和“内容块变化”;原始结构仍以 System 原文为证据。完整门限和退化语义见 [System Diff View 契约](system-diff-view-contract.md)
311311

312-
顶部 Trace 搜索和 Raw 区块搜索均遵守浏览器 IME composition 生命周期:中文、日文、韩文等输入法组词期间不替换输入框 DOM,只有选词完成后才触发过滤和重绘。Trace 搜索与事件筛选是顶部主操作;会话请求数、回复数、子 Agent、工具事件和 Raw 体积收进按需展开的统计面板,避免高频操作被低频数字挤出首屏。
312+
顶部 Trace 搜索和 Raw 区块搜索均遵守浏览器 IME composition 生命周期:中文、日文、韩文等输入法组词期间不替换输入框 DOM,只有选词完成后才触发过滤和重绘。Trace 搜索与事件筛选是顶部主操作;界面语言、翻译语言和独立的 latest-only 图标保留在外层,会话请求数、回复数、子 Agent、工具事件、Raw 体积与捕获方式收进按需展开的会话概览,避免高频操作被低频数字挤出首屏。主题是跨会话外观偏好,以左栏紧凑图标选择器呈现,不占用 Trace 工作区
313313

314314
Turn Rail 已作为首个 Viewer Client feature 从全局脚本迁出。`client.js` 只注入当前 Turn 集合、active id、文案和状态回调;窗口密度、边缘提示、悬停层级、点击跳转与滚动激活由 `TurnRailController` 所有。纯窗口策略和滚动选择规则有独立契约测试,后续 feature 也应遵循“依赖注入、纯策略可测、应用层只装配”的边界。
315315

src/viewer/client.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ const els = {
162162
pageTitle: document.querySelector("#pageTitle"),
163163
stats: document.querySelector("#stats"),
164164
viewControls: document.querySelector("#viewControls"),
165+
sessionOverviewActions: document.querySelector("#sessionOverviewActions"),
166+
sessionOverviewDisclosure: document.querySelector("#sessionOverviewDisclosure"),
165167
mainPanel: document.querySelector(".main-panel"),
166168
sidebarResizer: document.querySelector("#sidebarResizer"),
167169
watchSummary: document.querySelector("#watchSummary"),
@@ -602,6 +604,14 @@ async function init() {
602604
event.stopPropagation();
603605
translationActionController.retranslate(retranslateButton.dataset.translationRetranslate);
604606
});
607+
document.addEventListener("click", (event) => {
608+
if (els.sessionOverviewDisclosure?.open && !els.sessionOverviewDisclosure.contains(event.target)) {
609+
els.sessionOverviewDisclosure.removeAttribute("open");
610+
}
611+
document.querySelectorAll(".trace-filter-disclosure[open]").forEach((disclosure) => {
612+
if (!disclosure.contains(event.target)) disclosure.removeAttribute("open");
613+
});
614+
});
605615
turnRailController.bind();
606616
paneLayoutController.bind();
607617
document.addEventListener("visibilitychange", () => {
@@ -971,9 +981,20 @@ function renderViewControls() {
971981
const captureMode = state.data?.source?.workbench?.capture_label || "";
972982
const captureModeLabel = captureMode ? captureLabelText(captureMode) : t("sessionInfo");
973983
const captureModeHelp = captureMode ? captureLabelHelp(captureMode) : t("sessionInfo");
974-
els.viewControls.innerHTML =
975-
`<button class="stat stat-button ${state.latestOnly && !traceQueryActive() ? "active" : ""}" type="button" data-latest-only ${traceQueryActive() ? `disabled title="${escapeHtml(t("latestDisabledBySearch"))}"` : ""}>${state.latestOnly && !traceQueryActive() ? t("showAllTurns") : t("latestOnly")}</button>` +
976-
`<button class="stat stat-button session-info-trigger" type="button" data-session-info title="${escapeHtml(captureModeHelp)}">${escapeHtml(captureModeLabel)}</button>`;
984+
const latestOnlyActive = state.latestOnly && !traceQueryActive();
985+
const latestOnlyHelp = traceQueryActive()
986+
? t("latestDisabledBySearch")
987+
: latestOnlyActive
988+
? t("latestOnlyEnabledHelp")
989+
: t("latestOnly");
990+
els.viewControls.innerHTML = `<button class="latest-only-control ${latestOnlyActive ? "active" : ""}" type="button" data-latest-only aria-pressed="${escapeHtml(String(latestOnlyActive))}" aria-label="${escapeHtml(latestOnlyHelp)}" title="${escapeHtml(latestOnlyHelp)}" ${traceQueryActive() ? "disabled" : ""}>
991+
<span class="latest-only-glyph" aria-hidden="true"></span>
992+
</button>`;
993+
els.sessionOverviewActions.innerHTML =
994+
`<button class="session-overview-action session-info-trigger" type="button" data-session-info title="${escapeHtml(captureModeHelp)}">
995+
<span>${escapeHtml(t("captureMode"))}</span>
996+
<strong>${escapeHtml(captureModeLabel)}</strong>
997+
</button>`;
977998
bindViewControlEvents();
978999
bindSessionInfoControls();
9791000
}
@@ -1148,6 +1169,7 @@ function bindSessionInfoControls() {
11481169
}
11491170

11501171
function showSessionInfoModal() {
1172+
els.sessionOverviewDisclosure?.removeAttribute("open");
11511173
els.sessionInfoModal.classList.remove("hidden");
11521174
els.sessionInfoModal.setAttribute("aria-hidden", "false");
11531175
}
@@ -1159,6 +1181,7 @@ function hideSessionInfoModal() {
11591181

11601182
document.addEventListener("keydown", (event) => {
11611183
if (event.key === "Escape" && !els.sessionInfoModal.classList.contains("hidden")) hideSessionInfoModal();
1184+
if (event.key === "Escape") els.sessionOverviewDisclosure?.removeAttribute("open");
11621185
});
11631186

11641187
async function stopActiveWatch(clear) {

src/viewer/index.html

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,18 @@
1616
<div class="app-shell">
1717
<aside class="sidebar">
1818
<div class="brand">
19-
<div class="brand-mark" aria-hidden="true">p</div>
20-
<div class="brand-copy">
21-
<h1>peekMyAgent</h1>
22-
<p data-i18n="brandSubtitle">本地请求观察器</p>
19+
<div class="brand-identity">
20+
<div class="brand-mark" aria-hidden="true">p</div>
21+
<div class="brand-copy">
22+
<h1>peekMyAgent</h1>
23+
<p data-i18n="brandSubtitle">本地请求观察器</p>
24+
</div>
2325
</div>
26+
<label class="sidebar-theme-control" title="选择界面主题" data-i18n-title="themeSelectAria">
27+
<span class="theme-glyph" aria-hidden="true"></span>
28+
<select id="themeSelect" aria-label="选择界面主题" data-i18n-aria-label="themeSelectAria"></select>
29+
<span class="select-chevron" aria-hidden="true"></span>
30+
</label>
2431
</div>
2532
<div class="sidebar-section">
2633
<div class="sidebar-section-title">
@@ -44,16 +51,7 @@ <h2 id="pageTitle" data-i18n="timelineTitle">Agent 请求时间线</h2>
4451
<div class="topbar-actions">
4552
<section id="traceQuery" class="trace-query"></section>
4653
<div class="topbar-control-row">
47-
<details class="stats-disclosure">
48-
<summary class="stat stat-button" data-i18n="sessionStats">统计</summary>
49-
<div id="stats" class="stats" aria-label="会话统计" data-i18n-aria-label="sessionStatsAria"></div>
50-
</details>
51-
<div id="viewControls" class="view-controls"></div>
5254
<div class="language-controls" aria-label="语言设置" data-i18n-aria-label="languageSettingsAria">
53-
<label class="language-control theme-control">
54-
<span data-i18n="themeLabel">主题</span>
55-
<select id="themeSelect" aria-label="选择主题" data-i18n-aria-label="themeSelectAria"></select>
56-
</label>
5755
<label class="language-control">
5856
<span data-i18n="uiLanguageLabel">界面</span>
5957
<select id="uiLanguageSelect"></select>
@@ -63,6 +61,18 @@ <h2 id="pageTitle" data-i18n="timelineTitle">Agent 请求时间线</h2>
6361
<select id="translationLanguageSelect"></select>
6462
</label>
6563
</div>
64+
<div id="viewControls" class="view-controls"></div>
65+
<details class="session-overview-disclosure" id="sessionOverviewDisclosure">
66+
<summary class="session-overview-summary" data-i18n-title="sessionOverviewAria">
67+
<span class="session-overview-glyph" aria-hidden="true"></span>
68+
<span class="visually-hidden" data-i18n="sessionOverview">概览</span>
69+
<span class="select-chevron" aria-hidden="true"></span>
70+
</summary>
71+
<div class="session-overview-popover">
72+
<div id="sessionOverviewActions" class="session-overview-actions"></div>
73+
<div id="stats" class="stats" aria-label="会话统计" data-i18n-aria-label="sessionStatsAria"></div>
74+
</div>
75+
</details>
6676
</div>
6777
</div>
6878
</div>

0 commit comments

Comments
 (0)