feat(ui): add terminal font controls and session duration

- Add font size controls (A+/A-) with keyboard shortcuts (Ctrl++/-)
- Add session duration display in session cards
- Persist font size preference in localStorage
- Add periodic session re-render to update durations
- Update terminal welcome message with new shortcuts
- Update README keyboard shortcuts documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-18 22:11:43 +01:00
co-authored by Claude Opus 4.5
parent f8b84a9465
commit c60f416d4b
4 changed files with 100 additions and 0 deletions
+71
View File
@@ -39,6 +39,7 @@ class ClaudemanApp {
init() {
this.initTerminal();
this.loadFontSize();
this.connectSSE();
this.loadState();
this.loadCases();
@@ -98,6 +99,7 @@ class ClaudemanApp {
this.terminal.writeln('╠═══════════════════════════════════════════════════════════════╣');
this.terminal.writeln('║ \x1b[0;90mCtrl+Enter\x1b[1;36m Quick Start \x1b[0;90mCtrl+K\x1b[1;36m Kill All Sessions ║');
this.terminal.writeln('║ \x1b[0;90mCtrl+L\x1b[1;36m Clear Terminal \x1b[0;90mCtrl+1/2/3\x1b[1;36m Switch Tabs ║');
this.terminal.writeln('║ \x1b[0;90mCtrl++/-\x1b[1;36m Font Size \x1b[0;90mEscape\x1b[1;36m Close Modals ║');
this.terminal.writeln('╚═══════════════════════════════════════════════════════════════╝\x1b[0m');
this.terminal.writeln('');
@@ -189,6 +191,16 @@ class ClaudemanApp {
e.preventDefault();
this.switchTab('settings');
}
// Ctrl/Cmd + +/- for font size
if ((e.ctrlKey || e.metaKey) && (e.key === '=' || e.key === '+')) {
e.preventDefault();
this.increaseFontSize();
}
if ((e.ctrlKey || e.metaKey) && e.key === '-') {
e.preventDefault();
this.decreaseFontSize();
}
});
}
@@ -959,6 +971,39 @@ class ClaudemanApp {
this.terminal.writeln('\x1b[90mTerminal cleared\x1b[0m');
}
// Font size controls
increaseFontSize() {
const current = this.terminal.options.fontSize || 14;
const newSize = Math.min(current + 2, 24);
this.setFontSize(newSize);
}
decreaseFontSize() {
const current = this.terminal.options.fontSize || 14;
const newSize = Math.max(current - 2, 10);
this.setFontSize(newSize);
}
setFontSize(size) {
this.terminal.options.fontSize = size;
document.getElementById('fontSizeDisplay').textContent = `${size}px`;
this.fitAddon.fit();
// Save preference
localStorage.setItem('claudeman-font-size', size);
}
loadFontSize() {
const saved = localStorage.getItem('claudeman-font-size');
if (saved) {
const size = parseInt(saved, 10);
if (size >= 10 && size <= 24) {
this.terminal.options.fontSize = size;
document.getElementById('fontSizeDisplay').textContent = `${size}px`;
}
}
}
// Timer
showTimer() {
document.getElementById('timerBanner').style.display = 'block';
@@ -1010,6 +1055,8 @@ class ClaudemanApp {
startTimerUpdates() {
setInterval(() => this.updateTimer(), 1000);
// Also update session durations every 30 seconds
setInterval(() => this.renderSessions(), 30000);
}
formatTime(ms) {
@@ -1078,8 +1125,15 @@ class ClaudemanApp {
(terminalSize / bufferStats.maxTerminalBuffer * 100) : 0;
const memoryClass = memoryPercent > 80 ? 'high' : memoryPercent > 50 ? 'medium' : 'low';
// Session duration
const duration = this.formatDuration(Date.now() - s.createdAt);
const resourceHtml = `
<div class="session-resources">
<div class="resource-item">
<span class="resource-label">⏱</span>
<span class="resource-value">${duration}</span>
</div>
<div class="resource-item">
<span class="resource-label">Memory:</span>
<span class="resource-value ${memoryClass}">${this.formatBytes(totalMemory)}</span>
@@ -1218,6 +1272,23 @@ class ClaudemanApp {
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
// Format duration in human-readable format
formatDuration(ms) {
const seconds = Math.floor(ms / 1000);
if (seconds < 60) return `${seconds}s`;
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes}m`;
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
if (hours < 24) return `${hours}h ${remainingMinutes}m`;
const days = Math.floor(hours / 24);
const remainingHours = hours % 24;
return `${days}d ${remainingHours}h`;
}
updateSessionOutput(sessionId, text) {
// Sessions list shows brief info, main terminal shows full output
}
+5
View File
@@ -235,6 +235,11 @@
<div class="output-header">
<h2>Terminal</h2>
<div class="output-actions">
<div class="font-controls">
<button class="btn btn-xs" onclick="app.decreaseFontSize()" title="Decrease font size (Ctrl+-)">A-</button>
<span class="font-size-display" id="fontSizeDisplay">14px</span>
<button class="btn btn-xs" onclick="app.increaseFontSize()" title="Increase font size (Ctrl+=)">A+</button>
</div>
<button class="btn btn-sm" onclick="app.clearTerminal()">Clear</button>
</div>
</div>
+23
View File
@@ -1671,3 +1671,26 @@ input[type="checkbox"] {
height: 1px;
background: var(--border);
}
/* Font Controls */
.font-controls {
display: flex;
align-items: center;
gap: 0.25rem;
margin-right: 0.5rem;
}
.font-size-display {
font-size: 0.7rem;
color: var(--text-muted);
min-width: 32px;
text-align: center;
font-family: 'SF Mono', Monaco, monospace;
}
/* Output Actions */
.output-actions {
display: flex;
align-items: center;
gap: 0.5rem;
}