Repository navigation
perf(sidebar): windowed session list — only mount the visible row window - #626
Merged
Merged
Conversation
The 2000+ session catalogue rendered every <SessionItem/> eagerly, so first paint paid for 2003 DOM nodes plus 2003 hover/rename/delete state machines. Switch the list to a fixed-height (54px) window: ResizeObserver measures the scroll viewport, a rAF-throttled onScroll computes the visible window, and translateY positions the slice. Empty/loading/error states render unaffected. The first paint shows a small slice; scroll mounts the next window. No new dependency.
Keep the focused session row mounted outside the visible window and let its blur handler save before releasing it. Retain loaded rows when refreshing fails, and share the fixed row height. Add window coverage for focused rows, blur release, shrinking projects, and the initial viewport fallback. Verified 27 related tests, typecheck, lint, and desktop/mobile Chrome component checks for rename preservation, save/cancel, and failed refreshes.
Key saved messages and process groups by their session entry IDs so pagination does not reuse or detach existing message nodes. Add an E2E assertion retaining the latest user-message node across both prepend operations. The new regression assertion fails with index keys and passes with entry IDs at desktop and mobile viewports. Also verified 42 related tests, typecheck, and lint.
agegr
marked this pull request as ready for review
September 5, 2026 07:59
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
agegr
added a commit
to Nuctori/pi-web
that referenced
this pull request
Sep 5, 2026
Bring in the stable session-entry React keys and node-identity regression assertion already merged with PR agegr#626. Resolve the session-reader type import conflict by removing both now-unused SDK types. Validated 867 tests, typecheck, lint, and full desktop/mobile E2E.
heibai010011
pushed a commit
to heibai010011/pi-web
that referenced
this pull request
Sep 7, 2026
上游新功能: - 内置终端面板(node-pty + xterm,API /api/terminal,工作区级进程复用) - 划选文本分支对话(agegr#698)与会话搜索(/api/sessions/search) - 聊天外观设置(agegr#704:字号/行宽/消息间距/气泡样式) - 草稿保留与恢复(agegr#720)、阅读位置记忆(agegr#723) - 窗口化会话列表(agegr#626)、插件更新检查(agegr#611)、Mermaid 预览 - Pi 依赖升级至 0.85.1,CI 工作流 本地特性在合并中保留: - 会话文件夹组织(session-folder-drafts / session-folders)与树视图 - 权限插件内联卡片(InlinePermissionRequest)与扩展模态拆分 - 侧栏"当前工作"时间分段视图、删除会话的全局级联重挂载 - 响应状态胶囊、自定义语法高亮主题、dev Service Worker 清理 测试适配(--test-isolation=none 下共享进程环境): - subagents profiles/settings/subagents 测试在测试体内重新指向各自的 PI_CODING_AGENT_DIR 临时目录,避免跨文件 env 覆盖 - session-folder-drafts 的 CustomEvent 桩透传 init,恢复真实构造器 - FileViewer.state 通过 createRequire 加载 react-syntax-highlighter, 与 jiti 的 CJS 通道一致,避免 realm 内重复加载 - terminal-manager 用命名管道探针检测 ConPTY 沙盒并跳过 PTY 测试 - worktree/pi-web-options/project-command-env 增加 PI_WEB_TEST_NO_SPAWN 跳过开关;directory-browser/subagent-input 跳过需符号链接权限的用例 - useAgentSession/ChatInput 等源码正则断言适配 CRLF 与本地 UI 保留 验证:node --experimental-strip-types --test --test-isolation=none 全部 1031 项测试 1014 通过 / 0 失败 / 17 项沙盒环境跳过; tsc --noEmit 无错误。
sleepinginsummer
pushed a commit
to sleepinginsummer/pi-web
that referenced
this pull request
Sep 9, 2026
…dow (agegr#626) * perf(sidebar): windowed session list — only mount the visible row window The 2000+ session catalogue rendered every <SessionItem/> eagerly, so first paint paid for 2003 DOM nodes plus 2003 hover/rename/delete state machines. Switch the list to a fixed-height (54px) window: ResizeObserver measures the scroll viewport, a rAF-throttled onScroll computes the visible window, and translateY positions the slice. Empty/loading/error states render unaffected. The first paint shows a small slice; scroll mounts the next window. No new dependency. * fix(sidebar): preserve inline edits and cached sessions when windowing Keep the focused session row mounted outside the visible window and let its blur handler save before releasing it. Retain loaded rows when refreshing fails, and share the fixed row height. Add window coverage for focused rows, blur release, shrinking projects, and the initial viewport fallback. Verified 27 related tests, typecheck, lint, and desktop/mobile Chrome component checks for rename preservation, save/cancel, and failed refreshes. * fix(chat): preserve message identity when prepending history Key saved messages and process groups by their session entry IDs so pagination does not reuse or detach existing message nodes. Add an E2E assertion retaining the latest user-message node across both prepend operations. The new regression assertion fails with index keys and passes with entry IDs at desktop and mobile viewports. Also verified 42 related tests, typecheck, and lint. --------- Co-authored-by: Nuctori <Nuctori@users.noreply.github.com> Co-authored-by: Alex Yang <agegcn@gmail.com>
ghost0211
pushed a commit
to ghost0211/pi-web
that referenced
this pull request
Sep 29, 2026
…dow (agegr#626) * perf(sidebar): windowed session list — only mount the visible row window The 2000+ session catalogue rendered every <SessionItem/> eagerly, so first paint paid for 2003 DOM nodes plus 2003 hover/rename/delete state machines. Switch the list to a fixed-height (54px) window: ResizeObserver measures the scroll viewport, a rAF-throttled onScroll computes the visible window, and translateY positions the slice. Empty/loading/error states render unaffected. The first paint shows a small slice; scroll mounts the next window. No new dependency. * fix(sidebar): preserve inline edits and cached sessions when windowing Keep the focused session row mounted outside the visible window and let its blur handler save before releasing it. Retain loaded rows when refreshing fails, and share the fixed row height. Add window coverage for focused rows, blur release, shrinking projects, and the initial viewport fallback. Verified 27 related tests, typecheck, lint, and desktop/mobile Chrome component checks for rename preservation, save/cancel, and failed refreshes. * fix(chat): preserve message identity when prepending history Key saved messages and process groups by their session entry IDs so pagination does not reuse or detach existing message nodes. Add an E2E assertion retaining the latest user-message node across both prepend operations. The new regression assertion fails with index keys and passes with entry IDs at desktop and mobile viewports. Also verified 42 related tests, typecheck, and lint. --------- Co-authored-by: Nuctori <Nuctori@users.noreply.github.com> Co-authored-by: Alex Yang <agegcn@gmail.com> (cherry picked from commit 5f8f47b)
ghost0211
added a commit
to ghost0211/pi-web
that referenced
this pull request
Sep 29, 2026
Batch upstream cherry-picks (agegr/pi-web) into the fork: Fixes - Guard against duplicate built-in command submissions (agegr#762) - Keep shell output across SSE reconnects; resume streaming output - See sessions written by another pi process (agegr#796) - Stop duplicating the first streamed chunk (agegr#835) - Deliver events to every listener when one unsubscribes mid-emit Features - Warn when attached images go to a model without image input (agegr#636) - Preview image attachments in the chat composer (agegr#735) - Render apply_patch tool calls as split diffs (agegr#744) - Scroll-to-latest floating button (agegr#845) Performance & deps - gzip large JSON responses (agegr#731) - Cache unchanged session metadata across scans and restarts (agegr#625) - Windowed session list (adapted to the fork's project-grouped sidebar) (agegr#626) - Next.js 16.3.6 + disable image optimizer; trim production install (agegr#948) Also includes the NSIS shortcut recreation hook (desktop icon fix).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Windowed session list. The sidebar mounts at most the visible window of
SessionItemrows plus a small overscan; the rest are flattened bytranslateY. Empty / loading / error states are unchanged.SESSION_LIST_ITEM_HEIGHT = 54everySessionItemalready rendersat exactly this height (existing constant inside the component).
ResizeObserveron the scroll container keepslistViewportHin syncwith layout changes (sidebar resize, font-size change, browser zoom).
onScrollis rAF-throttled: a frame may receive manyscrolleventsbut emits at most one
setListScrollTopper frame.ResizeObserverhas not yet measured(
listViewportH === 0), the slice uses a 600 px window guess. It isreplaced on the first observer callback, before the user can scroll.
Why
The 2003-session catalog at #599 was a known regression: each
SessionItemallocates its own hover / rename / delete state machines, and the parent
mounts all of them on the first paint. With L1 reducing the route to
~100 ms but the sidebar still rendering 2003 cards, the user feels no
overall speedup. This is the complementary client-side fix.
No new dependencies
package.json/package-lock.jsonreact-window/react-virtual/ similarcomponents/SessionSidebar.tsx(+81 / -21)Audit (self)
origin/main(28bab3c), ahead 0 before this PRnode_modules/.bin/tsc --noEmit)(no e2e/, no lib/, no .github/**)
Stacked plan (each PR base=main, merge-order-free)
perf/bench— independent perf-bench jobperf/l1-scanner— fingerprint memoizationperf/l3-sidebar— windowed listperf/l2-tail— strictly stacked on P2 (depends on the newscanner); will be cut from main once P2 lands
perf/l4-context— strictly stacked on P2; will be cut frommain once P2 lands
Local evidence
On the local 1992-session catalog, before this PR the first paint of
the sidebar mounts 1992 React subtrees; after this PR it mounts roughly
viewport / 54 pxitems (typically 6–20) plus an 8-row overscan.