Skip to content

emrg: GUI per-session chat-view containers — P3 slice 2 (GUI multi-session rant P3) - #634

Merged
argszero merged 1 commit into
masterfrom
feature/gui-p3-session-containers
Aug 10, 2026
Merged

emrg: GUI per-session chat-view containers — P3 slice 2 (GUI multi-session rant P3)#634
argszero merged 1 commit into
masterfrom
feature/gui-p3-session-containers

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

P3 slice 2 of the GUI multi-session rant (2026-08-10T15:07:19): per-session chat-view containers with display switching, building on P3 slice 0 (#630, per-session chat state isolation) and P3 slice 1 (#632, sessionsBySid state table).

Each open session now gets its own .session-view container under the #chat-view wrapper. Switching sessions toggles display (browser-tab effect) — scroll position, draft state, tool cards, and in-flight stream are fully preserved.

Changes

renderer/chat.jschatContainer(sid) fallback chain: registered container → active session's container (unsid'd events land in the active session, P4 transition) → legacy #chat-view.

renderer/app.js

  • ensureSessionView(sid) / activateSessionView(sid): get-or-create .session-view under #chat-view, toggle .active (only the active view is display:flex), register container (idempotent). Exported for tests.
  • switchSession / newSession: activate the session view instead of Chat.clear() — switching away no longer destroys the other session's rendered state.
  • deleteSession: unregister + remove the deleted session's container (if open).
  • /clear and /rewind: Chat.clear(state.sessionId) — target the active session's container only.
  • updateEmptyState: evaluate the active session's container (the wrapper always holds .session-view children, so counting the wrapper would break the welcome screen).

renderer/css/layout.css#chat-view becomes a positioning wrapper (position:relative; overflow:hidden); .session-view = absolute inset:0 scroll container, display:none unless .active. Excluded .session-view from the legacy #chat-view > * centering rule so the scroll container stays full-width (scrollbar at window edge); media-query padding moved to .session-view.

test/renderer.smoke.test.js — +3 tests (container creation + display switching + unsid'd-node routing; targeted Chat.clear isolation; unregistered-sid fallback with per-sid state buckets). Test mock: innerHTML setter now faithfully clears children on "" (Chat.clear depends on it).

Verification

  • GUI: 153 tests pass (43 daemon_client + 17 conn-manager + 22 app-commands + 43 renderer smoke + 15 i18n + 7 integration + 3 commands + 3 build-config); README/README.cn/Agent.md counts synced
  • Python: 680 pytest pass
  • node --check clean on all touched JS

Part of the staged P3 plan (remaining: P3 finalize/event-routing cleanup, then P4 open-sessions sidebar).

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260810-172123 (author). P3 slice 2: per-session .session-view containers with display switching; 153 GUI + 680 pytest green.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260810-173337

Verified locally on the PR head: GUI suite 153/153 (43 renderer smoke — activateSessionView creates distinct per-session .session-view containers under #chat-view and toggles .active (only the active view display:flex); unsid'd nodes route to the active session's container (fallback chain registered → active → legacy); Chat.clear targets only the active container (inactive view retained — switch-back shows original messages); targeted clear(sid); unregistered-sid events render into active view while state buckets stay keyed by own sid; test mock innerHTML setter now faithfully clears children), 680 pytest green, doc-count guard passes (153 = 43 dc + 17 cm + 43 renderer smoke + 22 + 15 + 7 + 3 + 3 synced in Agent.md/README/README.cn), node --check clean.

Code review: #chat-view becomes a positioning wrapper with .session-view absolute inset:0 scroll containers (display:none unless .active) — browser-tab effect preserves scroll/draft/tool cards/in-flight stream across switches; switchSession/newSession activate instead of Chat.clear(); deleteSession unregisters + removes the container; /clear and /rewind target the active session's container; updateEmptyState correctly counts the active view (not the wrapper). Exported activateSessionView for tests. Builds cleanly on #630/#632; matches the rant P3 plan (remaining: P3 finalize/event-routing cleanup, P4 open-sessions sidebar).

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle 20260810-173604

Re-verified on head 8e573ec: GUI suite 153/153 (43 renderer smoke incl. new P3 s2 tests — per-session .session-view containers created/toggled under #chat-view, unsid'd events route to the active container, targeted clear(sid) isolation, unregistered-sid fallback with per-sid state buckets), 680 pytest green, CLI import OK, node --check clean. Doc-count guard synced (153 = 43+17+22+43+15+7+3+3).

@pm25coder

Copy link
Copy Markdown
Collaborator

Tested this PR end-to-end on Windows — P3 slice 2 (per-session chat-view containers) verified.

@argszero
argszero merged commit 606f14e into masterAug 10, 2026
1 check passed
argszero added a commit that referenced this pull request Aug 10, 2026
…at-view containers entry (#635)
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
@argszero
argszero deleted the feature/gui-p3-session-containers branch August 10, 2026 12:38
argszero added a commit that referenced this pull request Aug 13, 2026
…to session-view scrolls (#764)
Regression from #634 (per-session .session-view scroll containers): #workspace
is overflow:hidden and never scrolls itself, but both scroll listeners were
attached to it in bubble phase. Native scroll events do NOT bubble, so:
- back-to-bottom button never appeared in the real GUI (tests dispatched
scroll directly on the wrapper, masking the bug)
- scroll-to-top older-history load never fired (same cause)
- returning from a panel view (v0.2 #762) always jumped to bottom, violating
the rant acceptance "scroll position preserved" (browser-tab semantics)
Fix:
- attach both #workspace scroll listeners with capture: true so child
.session-view scrolls reach them
- updateBackToBottomState/activeScrollEl helpers read metrics from the
active .session-view (not the non-scrolling #workspace)
- back-to-bottom click scrolls the active .session-view
- activateSessionView only scrolls to bottom for newly-created containers;
existing containers preserve their scroll position (panel round-trip / session
switch no longer jump)
- setWorkspaceChrome hides back-to-bottom in panel views, restores per
position when returning to session view
Tests: +1 renderer.smoke (back-to-bottom follows session-view scroll via
capture, panel-view hide + position restore on return) — GUI 236→237;
Agent.md count synced; pytest 801 green.
Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@argszero@pm25coder