chore: abstract pages into a pageview component

This commit is contained in:
Suyog Tandel
2026-01-29 12:07:50 +05:30
parent 7e58d58d55
commit 49ff0dc515
4 changed files with 167 additions and 175 deletions
+1
View File
@@ -1 +1,2 @@
pub mod page_view;
pub mod sidebar;
+43
View File
@@ -0,0 +1,43 @@
use gpui::*;
use gpui_component::{StyledExt, Theme, v_flex};
pub struct PageView;
impl PageView {
pub fn build(
title: impl Into<SharedString>,
subtitle: impl Into<SharedString>,
content: impl IntoElement,
theme: &Theme,
) -> impl IntoElement {
div()
.size_full()
.bg(theme.background)
.flex()
.flex_col()
.items_center()
.child(
div().w_full().max_w(px(1200.0)).px_10().py_5().child(
v_flex()
.gap_8()
.child(
v_flex()
.child(
div()
.text_3xl()
.font_extrabold()
.text_color(theme.foreground)
.child(title.into()),
)
.child(
div()
.text_sm()
.text_color(theme.muted_foreground)
.child(subtitle.into()),
),
)
.child(content),
),
)
}
}
+88 -118
View File
@@ -1,4 +1,5 @@
// src/views/about.rs
use crate::ui::components::page_view::PageView;
use gpui::*;
use gpui_component::{Icon, StyledExt, Theme, badge::Badge, button::Button, h_flex, v_flex};
@@ -6,143 +7,112 @@ pub struct AboutView;
impl AboutView {
pub fn build(theme: &Theme) -> impl IntoElement {
div()
.size_full()
.bg(theme.background)
.flex()
.flex_col()
.items_center()
.child(
div().w_full().max_w(px(1200.0)).px_10().py_5().child(
v_flex()
.gap_8()
PageView::build(
"About",
"Information about the application and its development.",
div()
.w_full()
.flex()
.justify_center()
.child(
div()
.max_w(px(1200.0))
.w_full()
.bg(rgb(0x18181b))
.border_1()
.border_color(theme.border)
.rounded_xl()
.p_6()
.child(
v_flex()
.items_center()
.justify_center()
.gap_4()
.py_8()
.text_center()
.child(
div()
.text_3xl()
.font_extrabold()
.text_color(theme.foreground)
.child("About"),
img("appIcons/in.suyogtandel.picoforge.svg")
.w(px(256.0))
.h(px(256.0)),
)
.child(
div().text_sm().text_color(theme.muted_foreground).child(
"Information about the application and its development.",
),
),
)
.child(
div()
.w_full()
.flex()
.justify_center()
div()
.text_2xl()
.font_bold()
.text_color(theme.foreground)
.child("PicoForge"),
)
.child(Badge::new().child("v0.4.0").color(theme.secondary))
.child(
div()
.max_w(px(1200.0))
.w_full()
.bg(rgb(0x18181b))
.border_1()
.border_color(theme.border)
.rounded_xl()
.p_6()
.text_color(theme.muted_foreground)
.max_w(px(450.0))
.child(
v_flex()
.items_center()
.justify_center()
.gap_4()
.py_8()
.text_center()
.child(
img("appIcons/in.suyogtandel.picoforge.svg")
.w(px(256.0))
.h(px(256.0))
)
"An open source commissioning tool for Pico FIDO security keys. Developed with Rust and GPUI.",
),
)
.child(
div()
.text_sm()
.text_color(theme.muted_foreground)
.gap_1()
.pt_4()
.border_t_1()
.border_color(theme.border)
.border_t_1()
.border_color(theme.border)
.w(px(320.0))
.child(
h_flex()
.justify_between()
.child("Code By:")
.child(
div()
.text_2xl()
.font_bold()
.font_medium()
.text_color(theme.foreground)
.child("PicoForge"),
)
.child(
Badge::new()
.child("v0.4.0")
.color(theme.secondary),
)
.child("Suyog Tandel"),
),
)
.child(
h_flex()
.justify_between()
.items_center()
.pt_2()
.mt_2()
.child(h_flex().items_center().gap_1().child("Copyright:"))
.child(
div()
.text_color(theme.muted_foreground)
.max_w(px(450.0))
.child(
"An open source commissioning tool for Pico FIDO security keys. Developed with Rust and GPUI.",
),
)
.child(
div()
.text_sm()
.text_color(theme.muted_foreground)
.gap_1()
.pt_4()
.border_t_1()
.border_color(theme.border)
.border_t_1()
.border_color(theme.border)
.w(px(320.0))
.child(
h_flex()
.justify_between()
.child("Code By:")
.child(
div()
.font_medium()
.text_color(theme.foreground)
.child("Suyog Tandel"),
),
)
.child(
h_flex()
.justify_between()
.items_center()
.pt_2()
.mt_2()
.child(
h_flex()
.items_center()
.gap_1()
.child("Copyright:"),
)
.child(
div()
.font_medium()
.text_color(theme.foreground)
.child("© 2026 Suyog Tandel"),
),
),
)
.font_medium()
.text_color(theme.foreground)
.child("© 2026 Suyog Tandel"),
),
),
)
.child(
h_flex()
.gap_4()
.pt_6()
.child(
Button::new("github_btn")
.outline()
.child(
h_flex()
.gap_4()
.pt_6()
.gap_2()
.child(
Button::new("github_btn")
.outline()
.child(
h_flex()
.gap_2()
.child(
Icon::default().path("icons/github.svg").size_4()
)
.child("GitHub")
)
.on_click(|_, _, cx| {
cx.open_url("https://github.com/librekeys/picoforge")
}),
),
),
Icon::default()
.path("icons/github.svg")
.size_4(),
)
.child("GitHub"),
)
.on_click(|_, _, cx| {
cx.open_url("https://github.com/librekeys/picoforge")
}),
),
),
),
),
)
theme,
)
}
}
+35 -57
View File
@@ -1,4 +1,5 @@
// use crate::device::types::*;
use crate::ui::components::page_view::PageView;
use gpui::*;
use gpui_component::StyledExt;
use gpui_component::{Icon, IconName, Theme, badge::Badge, h_flex, progress::Progress, v_flex};
@@ -83,62 +84,39 @@ impl HomeView {
},
};
div()
.size_full()
.bg(theme.background)
.flex()
.flex_col()
.items_center()
.child(
div().w_full().max_w(px(1200.0)).px_10().py_5().child(
v_flex()
.gap_8()
.child(
v_flex()
.child(
div()
.text_3xl()
.font_extrabold()
.text_color(theme.foreground)
.child("Device Overview"),
)
.child(
div().text_sm().text_color(theme.muted_foreground).child(
"Quick view of your device status and specifications.",
),
),
)
// Content Section
.child(if !device.connected {
// No Device Status Placeholder
div()
.flex()
.items_center()
.justify_center()
.h_64()
.border_1()
.border_color(theme.border)
.rounded_xl()
.child(
div()
.text_color(theme.muted_foreground)
.child("No Device Connected"),
)
.into_any_element()
} else {
// 4 Card Grid
div()
.grid()
.grid_cols(2)
.gap_6()
.child(Self::render_device_info(&device, theme))
.child(Self::render_fido_info(&device, theme))
.child(Self::render_led_config(&device, theme))
.child(Self::render_security_status(&device, theme))
.into_any_element()
}),
),
)
PageView::build(
"Device Overview",
"Quick view of your device status and specifications.",
if !device.connected {
// No Device Status Placeholder
div()
.flex()
.items_center()
.justify_center()
.h_64()
.border_1()
.border_color(theme.border)
.rounded_xl()
.child(
div()
.text_color(theme.muted_foreground)
.child("No Device Connected"),
)
.into_any_element()
} else {
// 4 Card Grid
div()
.grid()
.grid_cols(2)
.gap_6()
.child(Self::render_device_info(&device, theme))
.child(Self::render_fido_info(&device, theme))
.child(Self::render_led_config(&device, theme))
.child(Self::render_security_status(&device, theme))
.into_any_element()
},
theme,
)
}
fn home_card(
@@ -174,7 +152,7 @@ impl HomeView {
)
}
// --- Helper for Key-Value pairs ---
// Helper for Key-Value pairs
fn render_kv(
label: &str,
value: impl IntoElement,