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.
80 lines
2.2 KiB
Rust
80 lines
2.2 KiB
Rust
//! 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
|
|
}
|
|
}
|