mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 08:59:40 +02:00
perf: optimize WebUI rendering and CSS performance
Frontend JS: - Add render debouncing for renderInnerStatePanel (50ms) - Add render debouncing for renderTaskPanel (100ms) - Add render debouncing for renderScreenSessions (100ms) - Store timeout references for cleanup CSS Performance: - Add CSS containment to terminal container (strict) - Add containment to session tabs (layout) - Add containment to ralph panel (layout style paint) - Add containment to task panel (layout style) - Add containment to modal content (layout style paint) - Add will-change for animated elements - Use GPU-accelerated transitions where appropriate These optimizations reduce layout thrashing and isolate paint operations for smoother 60fps rendering. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,9 @@ class ClaudemanApp {
|
|||||||
|
|
||||||
// Render debouncing
|
// Render debouncing
|
||||||
this.renderSessionTabsTimeout = null;
|
this.renderSessionTabsTimeout = null;
|
||||||
|
this.renderInnerStatePanelTimeout = null;
|
||||||
|
this.renderTaskPanelTimeout = null;
|
||||||
|
this.renderScreenSessionsTimeout = null;
|
||||||
|
|
||||||
// System stats polling
|
// System stats polling
|
||||||
this.systemStatsInterval = null;
|
this.systemStatsInterval = null;
|
||||||
@@ -1912,6 +1915,16 @@ class ClaudemanApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderTaskPanel() {
|
renderTaskPanel() {
|
||||||
|
// Debounce renders at 100ms to prevent excessive DOM updates
|
||||||
|
if (this.renderTaskPanelTimeout) {
|
||||||
|
clearTimeout(this.renderTaskPanelTimeout);
|
||||||
|
}
|
||||||
|
this.renderTaskPanelTimeout = setTimeout(() => {
|
||||||
|
this._renderTaskPanelImmediate();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderTaskPanelImmediate() {
|
||||||
const session = this.sessions.get(this.activeSessionId);
|
const session = this.sessions.get(this.activeSessionId);
|
||||||
const body = document.getElementById('backgroundTasksBody');
|
const body = document.getElementById('backgroundTasksBody');
|
||||||
const stats = document.getElementById('taskPanelStats');
|
const stats = document.getElementById('taskPanelStats');
|
||||||
@@ -2128,6 +2141,16 @@ class ClaudemanApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderInnerStatePanel() {
|
renderInnerStatePanel() {
|
||||||
|
// Debounce renders at 50ms to prevent excessive DOM updates
|
||||||
|
if (this.renderInnerStatePanelTimeout) {
|
||||||
|
clearTimeout(this.renderInnerStatePanelTimeout);
|
||||||
|
}
|
||||||
|
this.renderInnerStatePanelTimeout = setTimeout(() => {
|
||||||
|
this._renderInnerStatePanelImmediate();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderInnerStatePanelImmediate() {
|
||||||
const panel = this.$('innerStatePanel');
|
const panel = this.$('innerStatePanel');
|
||||||
const toggle = this.$('ralphToggle');
|
const toggle = this.$('ralphToggle');
|
||||||
|
|
||||||
@@ -2462,6 +2485,16 @@ class ClaudemanApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderScreenSessions() {
|
renderScreenSessions() {
|
||||||
|
// Debounce renders at 100ms to prevent excessive DOM updates
|
||||||
|
if (this.renderScreenSessionsTimeout) {
|
||||||
|
clearTimeout(this.renderScreenSessionsTimeout);
|
||||||
|
}
|
||||||
|
this.renderScreenSessionsTimeout = setTimeout(() => {
|
||||||
|
this._renderScreenSessionsImmediate();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderScreenSessionsImmediate() {
|
||||||
const body = document.getElementById('screenSessionsBody');
|
const body = document.getElementById('screenSessionsBody');
|
||||||
|
|
||||||
if (!this.screenSessions || this.screenSessions.length === 0) {
|
if (!this.screenSessions || this.screenSessions.length === 0) {
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ body {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: 120px;
|
max-height: 120px;
|
||||||
padding: 0.15rem 0.25rem;
|
padding: 0.15rem 0.25rem;
|
||||||
|
/* Performance: isolate layout recalculations */
|
||||||
|
contain: layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-tabs::-webkit-scrollbar {
|
.session-tabs::-webkit-scrollbar {
|
||||||
@@ -134,7 +136,12 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.session-tab .tab-status.idle { background: var(--green); }
|
.session-tab .tab-status.idle { background: var(--green); }
|
||||||
.session-tab .tab-status.busy { background: var(--green); animation: pulse 1.5s infinite; }
|
.session-tab .tab-status.busy {
|
||||||
|
background: var(--green);
|
||||||
|
animation: pulse 1.5s infinite;
|
||||||
|
/* Performance: GPU acceleration for animation */
|
||||||
|
will-change: opacity;
|
||||||
|
}
|
||||||
.session-tab .tab-status.error { background: var(--red); }
|
.session-tab .tab-status.error { background: var(--red); }
|
||||||
|
|
||||||
.session-tab .tab-name {
|
.session-tab .tab-name {
|
||||||
@@ -150,7 +157,8 @@ body {
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: opacity 0.15s, width 0.15s, padding 0.15s;
|
/* Performance: use transform for GPU acceleration */
|
||||||
|
transition: opacity 0.15s ease-out, width 0.15s ease-out, padding 0.15s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-tab:hover .tab-close {
|
.session-tab:hover .tab-close {
|
||||||
@@ -491,6 +499,8 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow-anchor: none; /* Prevent scroll anchoring when expanding/collapsing */
|
overflow-anchor: none; /* Prevent scroll anchoring when expanding/collapsing */
|
||||||
|
/* Performance: isolate paint and layout operations */
|
||||||
|
contain: layout style paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mini Progress Ring (in summary) */
|
/* Mini Progress Ring (in summary) */
|
||||||
@@ -1066,6 +1076,9 @@ body {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
background: #0d0d0d;
|
background: #0d0d0d;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
/* Performance: isolate layout and paint operations */
|
||||||
|
contain: strict;
|
||||||
|
will-change: contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-container .xterm {
|
.terminal-container .xterm {
|
||||||
@@ -1707,6 +1720,8 @@ body {
|
|||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
||||||
|
/* Performance: isolate modal paint operations */
|
||||||
|
contain: layout style paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content.modal-sm {
|
.modal-content.modal-sm {
|
||||||
@@ -2145,6 +2160,9 @@ kbd {
|
|||||||
right: 0.5rem;
|
right: 0.5rem;
|
||||||
width: 350px;
|
width: 350px;
|
||||||
max-width: calc(100vw - 1rem);
|
max-width: calc(100vw - 1rem);
|
||||||
|
/* Performance: GPU-accelerated transforms and isolated paint */
|
||||||
|
contain: layout style;
|
||||||
|
will-change: transform;
|
||||||
max-height: 50vh;
|
max-height: 50vh;
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
|||||||
Reference in New Issue
Block a user