mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-03 05:59:43 +02:00
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:
@@ -85,6 +85,7 @@ The Quick Start button will:
|
||||
| `Ctrl+K` | Kill all sessions |
|
||||
| `Ctrl+L` | Clear terminal |
|
||||
| `Ctrl+1/2/3` | Switch tabs (Run/Cases/Settings) |
|
||||
| `Ctrl++/-` | Increase/decrease font size |
|
||||
| `Escape` | Close modals |
|
||||
|
||||
### CLI Usage
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user