From 77e2b8476b1e91b8683d6b0de0d61b6d17bc845d Mon Sep 17 00:00:00 2001 From: Brian Krabach Date: Wed, 1 Apr 2026 16:36:56 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20revert=20sidebar=20to=20single-line=20he?= =?UTF-8?q?ader=20(name=20+=20badge=20+=20=C3=97)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- muxplex/frontend/app.js | 11 ++--------- muxplex/frontend/style.css | 15 +++------------ muxplex/frontend/tests/test_app.mjs | 28 +++++++++++++++------------- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/muxplex/frontend/app.js b/muxplex/frontend/app.js index 5ea7e99..9f01d2f 100644 --- a/muxplex/frontend/app.js +++ b/muxplex/frontend/app.js @@ -520,15 +520,12 @@ function buildSidebarHTML(session, currentSession) { // Edge bar only (left border amber, no glow): applied when actIndicator is 'dot' or 'both' if (isBell && (actIndicator === 'dot' || actIndicator === 'both')) classes += ' sidebar-item--edge-bell'; - // Device badge — shown in meta line when multi_device_enabled + // Device badge — shown in header line when multi_device_enabled let badgeHtml = ''; if (_serverSettings && _serverSettings.multi_device_enabled && session.deviceName && ds.showDeviceBadges !== false) { badgeHtml = `${escapeHtml(session.deviceName)}`; } - // Timestamp for meta line - const timeStr = formatTimestamp(session.last_activity_at || null); - // Last 20 lines of snapshot — trim trailing blanks from the FULL snapshot FIRST, // then slice. Sessions with the cursor near the top have content at rows 1-2 and // rows 3-40 blank; slice(-20) would return only blank rows, then trim-after-slice @@ -544,12 +541,8 @@ function buildSidebarHTML(session, currentSession) { `
` + `` + - `` + `` + `
` diff --git a/muxplex/frontend/style.css b/muxplex/frontend/style.css index 746d789..dca90e7 100644 --- a/muxplex/frontend/style.css +++ b/muxplex/frontend/style.css @@ -617,21 +617,12 @@ body { margin: 0; } -/* Sidebar meta line — device badge + separator + timestamp */ -.sidebar-item-meta { - display: flex; - align-items: center; - gap: 4px; - padding: 0 8px 4px; - font-size: 10px; - color: var(--text-muted); +.sidebar-item-header .device-badge { + margin-left: auto; + margin-right: 4px; flex-shrink: 0; } -.sidebar-meta-sep { - opacity: 0.4; -} - .sidebar-empty { padding: 16px 12px; color: var(--text-muted); diff --git a/muxplex/frontend/tests/test_app.mjs b/muxplex/frontend/tests/test_app.mjs index f481293..d5ca39e 100644 --- a/muxplex/frontend/tests/test_app.mjs +++ b/muxplex/frontend/tests/test_app.mjs @@ -3914,22 +3914,24 @@ test('buildTileHTML does NOT add session-tile--edge-bell when activityIndicator _localStorageStore = {}; }); -test('buildSidebarHTML has sidebar-item-meta line (two-line header)', () => { - const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null }; +test('buildSidebarHTML has single-line header with name, badge, and delete button', () => { + app._setServerSettings({ multi_device_enabled: true }); + const session = { name: 'my-session', deviceName: 'Laptop', remoteId: 'fed-abc', snapshot: '', bell: { unseen_count: 0 } }; const html = app.buildSidebarHTML(session, ''); - assert.ok(html.includes('sidebar-item-meta'), 'sidebar-item-meta element must exist in sidebar HTML'); + const headerStart = html.indexOf('sidebar-item-header'); + const headerEnd = html.indexOf('', headerStart); + const headerContent = html.substring(headerStart, headerEnd); + assert.ok(headerContent.includes('device-badge'), 'device-badge must be inside sidebar-item-header'); + assert.ok(headerContent.includes('sidebar-delete'), 'sidebar-delete must be inside sidebar-item-header'); + app._setServerSettings(null); }); -test('buildSidebarHTML sidebar-item-meta contains sidebar-meta-sep dot separator', () => { +test('buildSidebarHTML does not have sidebar-item-meta element', () => { const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null }; const html = app.buildSidebarHTML(session, ''); - assert.ok(html.includes('sidebar-meta-sep'), 'sidebar-meta-sep must be present in sidebar HTML'); -}); - -test('buildSidebarHTML sidebar-item-meta contains sidebar-item-time', () => { - const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null }; - const html = app.buildSidebarHTML(session, ''); - assert.ok(html.includes('sidebar-item-time'), 'sidebar-item-time must be present in sidebar HTML'); + assert.ok(!html.includes('sidebar-item-meta'), 'sidebar-item-meta must NOT exist in sidebar HTML'); + assert.ok(!html.includes('sidebar-meta-sep'), 'sidebar-meta-sep must NOT exist in sidebar HTML'); + assert.ok(!html.includes('sidebar-item-time'), 'sidebar-item-time must NOT exist in sidebar HTML'); }); test('buildSidebarHTML adds sidebar-item--edge-bell when activityIndicator is dot', () => { @@ -3983,9 +3985,9 @@ test('CSS style.css .session-tile has border-left for edge bar', () => { assert.ok(tileBody.includes('border-left'), '.session-tile must have border-left for edge bar'); }); -test('CSS style.css has .sidebar-item-meta rule', () => { +test('CSS style.css has .sidebar-item-header .device-badge rule for badge right-alignment', () => { const source = fs.readFileSync(new URL('../style.css', import.meta.url), 'utf8'); - assert.ok(source.includes('.sidebar-item-meta'), 'style.css must have .sidebar-item-meta rule'); + assert.ok(source.includes('.sidebar-item-header .device-badge'), 'style.css must have .sidebar-item-header .device-badge rule for badge alignment in single-line header'); }); test('CSS style.css .tile-meta has opacity transition for crossfade (badge + timestamp together)', () => {