diff --git a/src/ui/components/mod.rs b/src/ui/components/mod.rs index e16f8da..85270b0 100644 --- a/src/ui/components/mod.rs +++ b/src/ui/components/mod.rs @@ -1 +1,2 @@ +pub mod page_view; pub mod sidebar; diff --git a/src/ui/components/page_view.rs b/src/ui/components/page_view.rs new file mode 100644 index 0000000..5e29bfb --- /dev/null +++ b/src/ui/components/page_view.rs @@ -0,0 +1,43 @@ +use gpui::*; +use gpui_component::{StyledExt, Theme, v_flex}; + +pub struct PageView; + +impl PageView { + pub fn build( + title: impl Into, + subtitle: impl Into, + 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), + ), + ) + } +} diff --git a/src/ui/views/about.rs b/src/ui/views/about.rs index cc82fea..c325b4e 100644 --- a/src/ui/views/about.rs +++ b/src/ui/views/about.rs @@ -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, + ) } } diff --git a/src/ui/views/home.rs b/src/ui/views/home.rs index e15c0a3..48a346f 100644 --- a/src/ui/views/home.rs +++ b/src/ui/views/home.rs @@ -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,