- 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
124 lines
3.9 KiB
Rust
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
|
|
}
|
|
}
|