Fix code review issues for phase 2.6 UI polish

Issue 1: Move focusSessionId out of settings to prevent localStorage persistence
- Moved focusSessionId to top-level state property (not in settings)
- Updated all references from state.settings.focusSessionId to state.focusSessionId
- Removed saveSettings() calls from session filter functions

Issue 2: Add active state to wrap toggle button
- Added .active class to wrap-toggle button when wrapText is enabled
- Updated updateSettingsUI() to toggle .active class based on wrapText state

Issue 3: Document auto-scroll ephemeral behavior
- Added comment explaining why auto-scroll is per-session and not persisted
- Clarifies this is intentional design decision

Issue 4: Replace inline styles with CSS class for session filter button
- Added .header-text-btn CSS class with styling
- Removed inline style attribute from sessions-filter-btn
This commit is contained in:
Jared Miller 2026-01-28 15:18:55 -05:00
parent 737948c820
commit 766ee9b67c
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C

View file

@ -697,6 +697,13 @@
font-weight: 600; font-weight: 600;
} }
.header-text-btn {
font-size: 14px;
font-weight: 500;
min-width: auto;
padding: 8px 12px;
}
.popover { .popover {
position: fixed; position: fixed;
top: 60px; top: 60px;
@ -864,7 +871,7 @@
<header> <header>
<h1>claude-remote</h1> <h1>claude-remote</h1>
<div style="display: flex; align-items: center; gap: 16px;"> <div style="display: flex; align-items: center; gap: 16px;">
<button class="settings-btn" id="sessions-filter-btn" onclick="openSessionFilter()" title="Session Filter" style="font-size: 14px; font-weight: 500; min-width: auto; padding: 8px 12px;"> <button class="settings-btn header-text-btn" id="sessions-filter-btn" onclick="openSessionFilter()" title="Session Filter">
<span id="sessions-count-text">0 sessions</span> <span id="sessions-count-text">0 sessions</span>
</button> </button>
<button class="settings-btn" onclick="openStyleModal()" title="Display Settings">⚙️</button> <button class="settings-btn" onclick="openStyleModal()" title="Display Settings">⚙️</button>
@ -968,13 +975,12 @@
eventSource: null, eventSource: null,
reconnectTimeout: null, reconnectTimeout: null,
instructionsModalPromptId: null, instructionsModalPromptId: null,
focusSessionId: null, // session ID for filtering, null = show all (ephemeral, not persisted)
settings: { settings: {
columns: 1, // 1, 2, 3, or 'fit' columns: 1, // 1, 2, 3, or 'fit'
fontSize: 12, // px value fontSize: 12, // px value
terminalHeight: 400, // px value terminalHeight: 400, // px value
wrapText: true, // true = pre-wrap, false = pre (horizontal scroll) wrapText: true, // true = pre-wrap, false = pre (horizontal scroll)
focusSessionId: null, // session ID for filtering, null = show all
autoScroll: true, // true = auto-scroll to bottom on new output
}, },
}; };
@ -1042,6 +1048,9 @@
idle_since: null, idle_since: null,
git_branch: null, git_branch: null,
git_files_json: null, git_files_json: null,
// Auto-scroll state is per-session and ephemeral - not persisted to localStorage.
// This is intentional: users may want different auto-scroll settings for different
// sessions, and persisting would require tracking state by session ID which is complex.
autoScroll: true, autoScroll: true,
}); });
renderSessions(); renderSessions();
@ -1289,14 +1298,13 @@
// Filter sessions if focusSessionId is set // Filter sessions if focusSessionId is set
let sessionsToRender = Array.from(state.sessions.values()); let sessionsToRender = Array.from(state.sessions.values());
if (state.settings.focusSessionId !== null) { if (state.focusSessionId !== null) {
const focusSession = state.sessions.get(state.settings.focusSessionId); const focusSession = state.sessions.get(state.focusSessionId);
if (focusSession) { if (focusSession) {
sessionsToRender = [focusSession]; sessionsToRender = [focusSession];
} else { } else {
// Filtered session no longer exists, clear filter // Filtered session no longer exists, clear filter
state.settings.focusSessionId = null; state.focusSessionId = null;
saveSettings();
updateSessionsCountButton(); updateSessionsCountButton();
} }
} }
@ -1837,7 +1845,13 @@
document.getElementById('terminal-height-display').textContent = `${state.settings.terminalHeight}px`; document.getElementById('terminal-height-display').textContent = `${state.settings.terminalHeight}px`;
// Update wrap toggle // Update wrap toggle
document.getElementById('wrap-toggle').textContent = state.settings.wrapText ? 'On' : 'Off'; const $wrapBtn = document.getElementById('wrap-toggle');
$wrapBtn.textContent = state.settings.wrapText ? 'On' : 'Off';
if (state.settings.wrapText) {
$wrapBtn.classList.add('active');
} else {
$wrapBtn.classList.remove('active');
}
} }
window.openStyleModal = () => { window.openStyleModal = () => {
@ -1893,7 +1907,7 @@
const $countText = document.getElementById('sessions-count-text'); const $countText = document.getElementById('sessions-count-text');
const total = state.sessions.size; const total = state.sessions.size;
if (state.settings.focusSessionId !== null) { if (state.focusSessionId !== null) {
$countText.innerHTML = `Viewing 1 of ${total} <span style="margin-left: 4px;">×</span>`; $countText.innerHTML = `Viewing 1 of ${total} <span style="margin-left: 4px;">×</span>`;
} else { } else {
const label = total === 1 ? 'session' : 'sessions'; const label = total === 1 ? 'session' : 'sessions';
@ -1928,15 +1942,13 @@
} }
window.setSessionFilter = (sessionId) => { window.setSessionFilter = (sessionId) => {
state.settings.focusSessionId = Number(sessionId); state.focusSessionId = Number(sessionId);
saveSettings();
closeSessionFilter(); closeSessionFilter();
renderSessions(); renderSessions();
}; };
window.clearSessionFilter = () => { window.clearSessionFilter = () => {
state.settings.focusSessionId = null; state.focusSessionId = null;
saveSettings();
closeSessionFilter(); closeSessionFilter();
renderSessions(); renderSessions();
}; };
@ -1950,7 +1962,7 @@
} }
$list.innerHTML = Array.from(state.sessions.values()).map(s => { $list.innerHTML = Array.from(state.sessions.values()).map(s => {
const isSelected = state.settings.focusSessionId === s.id; const isSelected = state.focusSessionId === s.id;
return ` return `
<div class="session-filter-item ${isSelected ? 'selected' : ''}" onclick="setSessionFilter(${s.id})"> <div class="session-filter-item ${isSelected ? 'selected' : ''}" onclick="setSessionFilter(${s.id})">
<div class="session-filter-command"> <div class="session-filter-command">