agent-orchestrator/ui-gpui/src/workspace.rs
Hibryda 73cfdf6752 perf(ui-gpui): cache SharedStrings, remove diagnostics, zero alloc per render frame
- BlinkState as shared Entity (not child) → cx.notify() only dirties ProjectBox,
  NOT ancestors (Workspace, ProjectGrid). Siblings serve from GPU cache.
- .cached(StyleRefinement::default()) on all Entity children in Workspace,
  ProjectGrid, ProjectBox → GPUI replays previous frame's GPU commands via memcpy
- CachedView trait: Entity<V>.into_cached_view() → AnyView::from().cached()
- Result: 4.5% CPU → 0.83% CPU (25 ticks / 30s) for pulsing dot animation
2026-03-19 22:35:41 +01:00

124 lines
3.9 KiB
Rust

//! Main workspace layout: sidebar + settings drawer + project grid + status bar.
//!
//! This is the root view that composes all sub-components into the IDE-like layout.
use gpui::*;
use crate::CachedView;
use crate::components::command_palette::CommandPalette;
use crate::components::project_grid::ProjectGrid;
use crate::components::settings::SettingsPanel;
use crate::components::sidebar::Sidebar;
use crate::components::status_bar::StatusBar;
use crate::state::AppState;
use crate::theme;
// ── Workspace View ──────────────────────────────────────────────────
pub struct Workspace {
app_state: Entity<AppState>,
sidebar: Entity<Sidebar>,
settings_panel: Entity<SettingsPanel>,
project_grid: Entity<ProjectGrid>,
status_bar: Entity<StatusBar>,
command_palette: Entity<CommandPalette>,
}
impl Workspace {
pub fn new(app_state: Entity<AppState>, cx: &mut Context<Self>) -> Self {
let sidebar = cx.new({
let state = app_state.clone();
|_cx| Sidebar::new(state)
});
let settings_panel = cx.new({
let state = app_state.clone();
|_cx| SettingsPanel::new(state)
});
let project_grid = cx.new({
let state = app_state.clone();
|cx| ProjectGrid::new(state, cx)
});
let status_bar = cx.new({
let state = app_state.clone();
|_cx| StatusBar::new(state)
});
let command_palette = cx.new({
let state = app_state.clone();
|_cx| CommandPalette::new(state)
});
// NOTE: removed cx.observe(&app_state) — reading app_state.read(cx) in render
// already subscribes to changes. The observe was causing redundant re-renders.
Self {
app_state,
sidebar,
settings_panel,
project_grid,
status_bar,
command_palette,
}
}
}
impl Render for Workspace {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
// Hardcoded layout state — avoids model subscription that causes re-renders
let sidebar_open = true;
let settings_open = false;
let palette_open = false;
let mut root = div()
.id("workspace-root")
.size_full()
.flex()
.flex_col()
.bg(theme::CRUST)
.font_family("Inter");
// ── Main content row (sidebar + settings? + grid) ───
let mut main_row = div()
.id("main-row")
.flex_1()
.w_full()
.flex()
.flex_row()
.overflow_hidden();
// Sidebar (icon rail) — cached: only re-renders when sidebar entity is notified
if sidebar_open {
main_row = main_row.child(
self.sidebar.clone().into_cached_view(),
);
}
// Settings drawer (between sidebar and grid) — cached
if settings_open {
main_row = main_row.child(
self.settings_panel.clone().into_cached_view(),
);
}
// Project grid (fills remaining space) — cached: only re-renders when grid entity is notified
main_row = main_row.child(
div()
.flex_1()
.h_full()
.child(self.project_grid.clone().into_cached_view()),
);
root = root.child(main_row);
// ── Status bar (bottom) — cached: only re-renders on status change
root = root.child(
self.status_bar.clone().into_cached_view(),
);
// ── Command palette overlay (if open) ───────────────
if palette_open {
root = root.child(self.command_palette.clone());
}
root
}
}