From 618417c14b0257a8543cd7057200b9e88219cc88 Mon Sep 17 00:00:00 2001 From: Edwin Date: Thu, 28 May 2026 17:20:27 -0700 Subject: [PATCH] Preserve web session list visibility on resize --- crates/daemon/assets/index.html | 12 ++++---- crates/e2e/tests/web_smoke.rs | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/crates/daemon/assets/index.html b/crates/daemon/assets/index.html index d5d7c9b9..1668f965 100644 --- a/crates/daemon/assets/index.html +++ b/crates/daemon/assets/index.html @@ -1630,6 +1630,10 @@ // prompts (codex with tool-heavy turns) don't lose any. approvalQueue: [], approvalShown: null, + // Logical session-list visibility. Keep this separate from the + // responsive CSS classes because narrow-screen auto-hide after + // selecting a session is intentionally not persisted to storage. + sessionListVisible: true, }; const LARGE_TEXT_PASTE_CHARS = 16 * 1024; @@ -3287,6 +3291,7 @@ } function setSessionListVisible(visible, persist = true) { + state.sessionListVisible = !!visible; if (isNarrowLayout()) { sessionListEl.classList.toggle("collapsed", !visible); } else { @@ -3301,9 +3306,7 @@ } function isSessionListVisible() { - return isNarrowLayout() - ? !sessionListEl.classList.contains("collapsed") - : !mainEl.classList.contains("session-list-hidden"); + return state.sessionListVisible; } function currentSessionListWidth() { @@ -3353,8 +3356,7 @@ window.addEventListener("resize", () => { setSessionListWidth(currentSessionListWidth(), false); - const storedVisible = localStorage.getItem(SESSION_LIST_VISIBLE_KEY); - setSessionListVisible(storedVisible !== "0", false); + setSessionListVisible(state.sessionListVisible, false); }); // --- Transcript rendering ------------------------------------------------- diff --git a/crates/e2e/tests/web_smoke.rs b/crates/e2e/tests/web_smoke.rs index 44af8941..8e8d7061 100644 --- a/crates/e2e/tests/web_smoke.rs +++ b/crates/e2e/tests/web_smoke.rs @@ -339,6 +339,59 @@ async fn web_client_loads_and_websocket_connects() { "visible keyboard switch should preserve terminal focus: {switch_focus:?}" ); + // Mobile regression: selecting a session auto-hides the narrow session + // list without changing the stored preference. Keyboard/viewport resizes + // must preserve that current hidden state instead of re-reading the older + // stored "visible" preference and expanding the list from the top. + let list_resize: serde_json::Value = page + .evaluate( + r#" + (() => { + const saved = { + isNarrowLayout, + sessionListVisible: state.sessionListVisible, + storage: localStorage.getItem(SESSION_LIST_VISIBLE_KEY), + mode: state.mode, + }; + try { + isNarrowLayout = () => true; + state.mode = 'chat'; + localStorage.setItem(SESSION_LIST_VISIBLE_KEY, '1'); + setSessionListVisible(false, false); + const before = { + visible: isSessionListVisible(), + collapsed: document.getElementById('sessionList').classList.contains('collapsed'), + stored: localStorage.getItem(SESSION_LIST_VISIBLE_KEY), + }; + window.dispatchEvent(new Event('resize')); + const after = { + visible: isSessionListVisible(), + collapsed: document.getElementById('sessionList').classList.contains('collapsed'), + stored: localStorage.getItem(SESSION_LIST_VISIBLE_KEY), + }; + return { before, after }; + } finally { + isNarrowLayout = saved.isNarrowLayout; + state.sessionListVisible = saved.sessionListVisible; + state.mode = saved.mode; + if (saved.storage === null) localStorage.removeItem(SESSION_LIST_VISIBLE_KEY); + else localStorage.setItem(SESSION_LIST_VISIBLE_KEY, saved.storage); + setSessionListVisible(saved.sessionListVisible, false); + } + })() + "#, + ) + .await + .expect("evaluate session list resize") + .into_value::() + .expect("json object"); + assert_eq!(list_resize["before"]["visible"], false); + assert_eq!(list_resize["before"]["collapsed"], true); + assert_eq!(list_resize["before"]["stored"], "1"); + assert_eq!(list_resize["after"]["visible"], false); + assert_eq!(list_resize["after"]["collapsed"], true); + assert_eq!(list_resize["after"]["stored"], "1"); + // Issue #132: the web session list exposes pin/unpin in the // selected-session toolbar and marks pinned rows visibly. let pin_ui: serde_json::Value = page