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:
Hibryda 2026-03-19 06:05:58 +01:00
parent 90c7315336
commit f3d2ca78ba
34 changed files with 17467 additions and 0 deletions

View file

@ -0,0 +1,80 @@
//! ProjectGrid: flex-wrap grid of ProjectBox cards.
//!
//! Lays out projects in a responsive grid that wraps when the window is wide
//! enough for multiple columns.
use gpui::*;
use crate::components::project_box::ProjectBox;
use crate::state::AppState;
use crate::theme;
// ── ProjectGrid View ────────────────────────────────────────────────
pub struct ProjectGrid {
app_state: Entity<AppState>,
/// One ProjectBox entity per project.
project_boxes: Vec<Entity<ProjectBox>>,
}
impl ProjectGrid {
pub fn new(app_state: Entity<AppState>, cx: &mut Context<Self>) -> Self {
// Clone projects out of state to avoid borrowing cx through app_state
let projects: Vec<_> = {
let state = app_state.read(cx);
state.projects.clone()
};
let project_boxes: Vec<Entity<ProjectBox>> = projects
.into_iter()
.map(|proj| {
cx.new(|cx| {
let mut pb = ProjectBox::new(proj);
pb.init_subviews(cx);
pb
})
})
.collect();
Self {
app_state,
project_boxes,
}
}
}
impl Render for ProjectGrid {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let mut grid = div()
.id("project-grid")
.flex_1()
.w_full()
.h_full()
.flex()
.flex_row()
.flex_wrap()
.gap(px(8.0))
.p(px(8.0))
.bg(theme::CRUST)
.overflow_y_scroll();
for pb in &self.project_boxes {
grid = grid.child(pb.clone());
}
if self.project_boxes.is_empty() {
grid = grid.child(
div()
.flex_1()
.flex()
.items_center()
.justify_center()
.text_size(px(16.0))
.text_color(theme::OVERLAY0)
.child("No projects. Press Ctrl+N to add one."),
);
}
grid
}
}