feat: add Dioxus and GPUI UI prototypes for framework comparison
Dioxus (ui-dioxus/): 2,169 lines, WebView mode (same wry as Tauri), Catppuccin theme, 12 components, agor-core integration, compiles clean. Evolution path — keeps xterm.js, gradual migration from Tauri. GPUI (ui-gpui/): 2,490 lines, GPU-accelerated rendering, alacritty_terminal for native terminal, 17 files, Catppuccin palette, demo data. Revolution path — pure Rust UI, 120fps target, no WebView. Both are standalone (not in workspace), share agor-core backend. Created for side-by-side comparison to inform framework decision.
This commit is contained in:
parent
90c7315336
commit
f3d2ca78ba
34 changed files with 17467 additions and 0 deletions
120
ui-gpui/src/workspace.rs
Normal file
120
ui-gpui/src/workspace.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
//! 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::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)
|
||||
});
|
||||
|
||||
// Observe app_state changes to trigger re-renders
|
||||
cx.observe(&app_state, |_this, _entity, cx| {
|
||||
cx.notify();
|
||||
})
|
||||
.detach();
|
||||
|
||||
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 {
|
||||
let state = self.app_state.read(cx);
|
||||
let sidebar_open = state.sidebar_open;
|
||||
let settings_open = state.settings_open;
|
||||
let palette_open = state.palette_open;
|
||||
|
||||
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)
|
||||
if sidebar_open {
|
||||
main_row = main_row.child(self.sidebar.clone());
|
||||
}
|
||||
|
||||
// Settings drawer (between sidebar and grid)
|
||||
if settings_open {
|
||||
main_row = main_row.child(self.settings_panel.clone());
|
||||
}
|
||||
|
||||
// Project grid (fills remaining space)
|
||||
main_row = main_row.child(
|
||||
div()
|
||||
.flex_1()
|
||||
.h_full()
|
||||
.child(self.project_grid.clone()),
|
||||
);
|
||||
|
||||
root = root.child(main_row);
|
||||
|
||||
// ── Status bar (bottom) ─────────────────────────────
|
||||
root = root.child(self.status_bar.clone());
|
||||
|
||||
// ── Command palette overlay (if open) ───────────────
|
||||
if palette_open {
|
||||
root = root.child(self.command_palette.clone());
|
||||
}
|
||||
|
||||
root
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue