fix: revert sidebar to single-line header (name + badge + ×)

This commit is contained in:
Brian Krabach
2026-04-01 16:36:56 -07:00
parent c5df6511c1
commit 77e2b8476b
3 changed files with 20 additions and 34 deletions
+2 -9
View File
@@ -520,15 +520,12 @@ function buildSidebarHTML(session, currentSession) {
// Edge bar only (left border amber, no glow): applied when actIndicator is 'dot' or 'both' // 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'; 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 = ''; let badgeHtml = '';
if (_serverSettings && _serverSettings.multi_device_enabled && session.deviceName && ds.showDeviceBadges !== false) { if (_serverSettings && _serverSettings.multi_device_enabled && session.deviceName && ds.showDeviceBadges !== false) {
badgeHtml = `<span class="device-badge">${escapeHtml(session.deviceName)}</span>`; badgeHtml = `<span class="device-badge">${escapeHtml(session.deviceName)}</span>`;
} }
// 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, // 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 // 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 // rows 3-40 blank; slice(-20) would return only blank rows, then trim-after-slice
@@ -544,12 +541,8 @@ function buildSidebarHTML(session, currentSession) {
`<article class="${classes}" data-session="${escapedName}" data-remote-id="${escapeHtml(session.remoteId || '')}" tabindex="0" role="listitem">` + `<article class="${classes}" data-session="${escapedName}" data-remote-id="${escapeHtml(session.remoteId || '')}" tabindex="0" role="listitem">` +
`<div class="sidebar-item-header">` + `<div class="sidebar-item-header">` +
`<span class="sidebar-item-name">${escapedName}</span>` + `<span class="sidebar-item-name">${escapedName}</span>` +
`<button class="sidebar-delete" data-session="${escapedName}" aria-label="Kill session">&times;</button>` +
`</div>` +
`<div class="sidebar-item-meta">` +
badgeHtml + badgeHtml +
`<span class="sidebar-meta-sep">\xb7</span>` + `<button class="sidebar-delete" data-session="${escapedName}" aria-label="Kill session">&times;</button>` +
`<span class="sidebar-item-time">${escapeHtml(timeStr)}</span>` +
`</div>` + `</div>` +
`<div class="sidebar-item-body"><pre>${ansiToHtml(lastLines)}</pre></div>` + `<div class="sidebar-item-body"><pre>${ansiToHtml(lastLines)}</pre></div>` +
`</article>` `</article>`
+3 -12
View File
@@ -617,21 +617,12 @@ body {
margin: 0; margin: 0;
} }
/* Sidebar meta line — device badge + separator + timestamp */ .sidebar-item-header .device-badge {
.sidebar-item-meta { margin-left: auto;
display: flex; margin-right: 4px;
align-items: center;
gap: 4px;
padding: 0 8px 4px;
font-size: 10px;
color: var(--text-muted);
flex-shrink: 0; flex-shrink: 0;
} }
.sidebar-meta-sep {
opacity: 0.4;
}
.sidebar-empty { .sidebar-empty {
padding: 16px 12px; padding: 16px 12px;
color: var(--text-muted); color: var(--text-muted);
+15 -13
View File
@@ -3914,22 +3914,24 @@ test('buildTileHTML does NOT add session-tile--edge-bell when activityIndicator
_localStorageStore = {}; _localStorageStore = {};
}); });
test('buildSidebarHTML has sidebar-item-meta line (two-line header)', () => { test('buildSidebarHTML has single-line header with name, badge, and delete button', () => {
const session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null }; 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, ''); 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('</div>', 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 session = { name: 'my-session', snapshot: '', bell: { unseen_count: 0 }, last_activity_at: null };
const html = app.buildSidebarHTML(session, ''); const html = app.buildSidebarHTML(session, '');
assert.ok(html.includes('sidebar-meta-sep'), 'sidebar-meta-sep 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 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');
}); });
test('buildSidebarHTML adds sidebar-item--edge-bell when activityIndicator is dot', () => { 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'); 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'); 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)', () => { test('CSS style.css .tile-meta has opacity transition for crossfade (badge + timestamp together)', () => {