From ef5847f4174cebfbc6e27aa55ef348f3ee3f10b2 Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Tue, 29 Sep 2026 20:31:42 +0200 Subject: [PATCH] feat: improved stats screen (#888) --- packages/oneclient_app/src/theme/colors.rs | 4 - .../src/view/app/analytics/mod.rs | 86 +++++++------------ .../src/view/app/analytics/servers.rs | 12 +-- .../src/view/app/analytics/tiles.rs | 24 +++--- 4 files changed, 49 insertions(+), 77 deletions(-) diff --git a/packages/oneclient_app/src/theme/colors.rs b/packages/oneclient_app/src/theme/colors.rs index 0db8798d..65bd72a5 100644 --- a/packages/oneclient_app/src/theme/colors.rs +++ b/packages/oneclient_app/src/theme/colors.rs @@ -11,10 +11,6 @@ pub fn page_elevated() -> Color { Color::from_rgb(21, 28, 34) } -pub fn page_overlay() -> Color { - Color::from_argb(140, 17, 23, 28) -} - pub fn fg_primary() -> Color { Color::from_rgb(213, 219, 255) } diff --git a/packages/oneclient_app/src/view/app/analytics/mod.rs b/packages/oneclient_app/src/view/app/analytics/mod.rs index 3ffb5255..b1c8c4fd 100644 --- a/packages/oneclient_app/src/view/app/analytics/mod.rs +++ b/packages/oneclient_app/src/view/app/analytics/mod.rs @@ -47,63 +47,35 @@ fn analytics_body_inner(analytics: &Analytics, force_all: bool) -> Element { } pub fn analytics_placeholder(note: &str) -> Element { - AnalyticsPlaceholder { - note: note.to_string(), - } - .into_element() -} - -#[derive(PartialEq)] -struct AnalyticsPlaceholder { - note: String, -} - -impl Component for AnalyticsPlaceholder { - fn render(&self) -> impl IntoElement { - let mut body_height = use_state(|| 0f32); - let scrim_height = *body_height.read(); - - rect() - .width(Size::fill()) - .child( - rect() - .width(Size::fill()) - .on_sized(move |e: Event| { - let height = e.area.height(); - if (*body_height.read() - height).abs() > 0.5 { - body_height.set(height); - } - }) - .child(analytics_body_inner(&empty_analytics(), true)), - ) - .child( - rect() - .position(Position::new_absolute()) - .width(Size::fill()) - .height(Size::px(scrim_height)) - .layer(Layer::Relative(1)) - .center() - .padding(40.) - .background(colors::page_overlay()) - .on_press(|_| {}) - .child( - rect() - .max_width(Size::px(360.)) - .padding(Gaps::new_symmetric(16., 24.)) - .corner_radius(CornerRadius::new_all(12.)) - .background(colors::page_elevated()) - .border(border_all_color(1., colors::component_border())) - .center() - .child( - label() - .text(self.note.clone()) - .font_size(14.) - .text_align(TextAlign::Center) - .color(colors::fg_secondary()), - ), - ), - ) - } + rect() + .vertical() + .width(Size::fill()) + .spacing(24.) + .child( + rect() + .width(Size::fill()) + .padding(Gaps::new_symmetric(16., 24.)) + .corner_radius(CornerRadius::new_all(12.)) + .background(colors::page_elevated()) + .border(border_all_color(1., colors::component_border())) + .center() + .child( + label() + .text(note.to_string()) + .width(Size::fill()) + .font_size(14.) + .text_align(TextAlign::Center) + .color(colors::fg_secondary()), + ), + ) + .child( + rect() + .width(Size::fill()) + .opacity(0.4) + .interactive(false) + .child(analytics_body_inner(&empty_analytics(), true)), + ) + .into_element() } /// A run of zero-second days ending today so the timeline still renders columns for each range diff --git a/packages/oneclient_app/src/view/app/analytics/servers.rs b/packages/oneclient_app/src/view/app/analytics/servers.rs index 71f5ceb6..eb6716d8 100644 --- a/packages/oneclient_app/src/view/app/analytics/servers.rs +++ b/packages/oneclient_app/src/view/app/analytics/servers.rs @@ -122,12 +122,12 @@ impl Component for ServersSection { .unit(m.unit()) .hovered(hovered), ) - .child(rect().width(Size::flex(1.0)).child(legend( - &values, - &labels, - *hovered.read(), - m.unit(), - ))), + .child( + rect() + .width(Size::flex(1.0)) + .max_width(Size::px(420.)) + .child(legend(&values, &labels, *hovered.read(), m.unit())), + ), ) .maybe_child(show_all.read().then(|| { OverlayPopup::new() diff --git a/packages/oneclient_app/src/view/app/analytics/tiles.rs b/packages/oneclient_app/src/view/app/analytics/tiles.rs index 00300039..43234dc2 100644 --- a/packages/oneclient_app/src/view/app/analytics/tiles.rs +++ b/packages/oneclient_app/src/view/app/analytics/tiles.rs @@ -28,7 +28,11 @@ struct TilesRow { impl Component for TilesRow { fn render(&self) -> impl IntoElement { let width = use_state(|| 0f32); - let cols = columns_for(*width.read(), TILE_MIN_W, 4, TILE_GAP); + let w = *width.read(); + let cols = match columns_for(w, TILE_MIN_W, 4, TILE_GAP) { + 3 => 2, + n => n, + }; let stats = &self.analytics.playtime; let avg_session = if stats.session_count > 0 { @@ -81,18 +85,19 @@ impl Component for TilesRow { if cols >= 3 { let alongside: Vec = rest.drain(..(cols - 2).min(rest.len())).collect(); + let col_w = (w - TILE_GAP * (cols - 1) as f32) / cols as f32; + let hero_w = if col_w > 0. { + Size::px(col_w * 2. + TILE_GAP) + } else { + Size::flex(2.0) + }; let mut lead = rect() .horizontal() .content(Content::Flex) .width(Size::fill()) .height(Size::px(TILE_H)) .spacing(TILE_GAP) - .child( - rect() - .width(Size::flex(2.0)) - .height(Size::fill()) - .child(hero), - ); + .child(rect().width(hero_w).height(Size::fill()).child(hero)); for tile in alongside { lead = lead.child( rect() @@ -145,8 +150,7 @@ fn hero_tile(icon: IconType, caption: &str, value: String, note: String) -> Elem card() .width(Size::fill()) .height(Size::fill()) - .padding(Gaps::new_symmetric(16., 20.)) - .spacing(10.) + .main_align(Alignment::SpaceBetween) .background(colors::brand().with_a(18)) .border(border_all_color(1., colors::brand().with_a(90))) .child( @@ -193,7 +197,7 @@ fn stat_tile(icon: IconType, caption: &str, value: String) -> Element { card() .width(Size::fill()) .height(Size::fill()) - .spacing(10.) + .main_align(Alignment::SpaceBetween) .child( rect() .horizontal()