From efed361417cf51c312625675a7b76d0a92ef615a Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:05:42 +0200 Subject: [PATCH] feat: added funfacts changing on background change (#718) Co-authored-by: rozwader --- packages/oneclient_app/src/hooks/actions.rs | 11 ++++++ packages/oneclient_app/src/view/app/debug.rs | 7 ++-- .../view/onboarding/downloading/backdrop.rs | 33 +++++++++++++---- .../src/view/onboarding/downloading/tips.rs | 36 +++++++++++++++++-- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/packages/oneclient_app/src/hooks/actions.rs b/packages/oneclient_app/src/hooks/actions.rs index aee585fc..4cc9062b 100644 --- a/packages/oneclient_app/src/hooks/actions.rs +++ b/packages/oneclient_app/src/hooks/actions.rs @@ -232,6 +232,17 @@ impl Actions { } } + pub fn reset_onboarding(&self) { + if let Some(updated) = self.mutate_settings(|settings| { + settings.seen_onboarding = false; + settings.accepted_tos_version = 0; + settings.accepted_privacy_version = 0; + settings.seen_versions.clear(); + }) { + self.persist(updated); + } + } + pub fn accept_tos(&self, terms_version: u32, privacy_version: u32) { if let Some(updated) = self.mutate_settings(|settings| { settings.accepted_tos_version = terms_version; diff --git a/packages/oneclient_app/src/view/app/debug.rs b/packages/oneclient_app/src/view/app/debug.rs index 030d1063..2d1c8c1e 100644 --- a/packages/oneclient_app/src/view/app/debug.rs +++ b/packages/oneclient_app/src/view/app/debug.rs @@ -6,6 +6,7 @@ use oneclient_auth::preview_samples; use oneclient_core::simulate::Damage; use oneclient_net::status::{self, ServiceStatus}; +use crate::Actions; use crate::components::{Button, Dropdown, Icon, IconType, TextInput, login_dialog, toggle}; use crate::hooks::use_dispatch; use crate::notifications::{ @@ -22,6 +23,7 @@ pub struct Debug; impl Component for Debug { fn render(&self) -> impl IntoElement { + let dispatch = use_dispatch(); let log_debug_info = use_state(|| false); let show_dev_stuff = use_state(|| false); let seen_onboarding = use_state(|| true); @@ -97,7 +99,7 @@ impl Component for Debug { .child(divider()) .child(section( "Other", - vec![action_row(vec![ + vec![action_row(&dispatch, vec![ ("Open Dev Tools", IconType::CodeSnippet02), ("Open Onboarding", IconType::Rocket02), ("Open Launcher Data", IconType::Folder), @@ -1142,7 +1144,7 @@ fn toggle_row(title: &'static str, on: State) -> Element { .into_element() } -fn action_row(buttons: Vec<(&'static str, IconType)>) -> Element { +fn action_row(dispatch: &Actions, buttons: Vec<(&'static str, IconType)>) -> Element { let mut row = rect().horizontal().width(Size::fill()).spacing(12.); for (text, icon) in buttons { @@ -1152,6 +1154,7 @@ fn action_row(buttons: Vec<(&'static str, IconType)>) -> Element { .text(text); if text == "Open Onboarding" { + dispatch.reset_onboarding(); button = button.on_press(|_| { let _ = RouterContext::get().replace(Route::OnboardingWelcome {}); }); diff --git a/packages/oneclient_app/src/view/onboarding/downloading/backdrop.rs b/packages/oneclient_app/src/view/onboarding/downloading/backdrop.rs index b9030aed..c346abe1 100644 --- a/packages/oneclient_app/src/view/onboarding/downloading/backdrop.rs +++ b/packages/oneclient_app/src/view/onboarding/downloading/backdrop.rs @@ -2,7 +2,7 @@ use super::*; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; -use std::time::Duration; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use oneclient_core::clusters::Cluster; @@ -11,7 +11,24 @@ use crate::hooks::use_settings_snapshot; use crate::layout::gradient_overlay_radial; use crate::theme::colors; -const BACKDROP_INTERVAL_SECS: u64 = 12; +pub(super) const BACKDROP_INTERVAL_SECS: u64 = 12; + +const ROTATION_PERIOD: Duration = Duration::from_secs(BACKDROP_INTERVAL_SECS); + +fn since_epoch() -> Duration { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or(Duration::ZERO) +} + +pub(super) fn rotation_tick() -> usize { + (since_epoch().as_secs() / BACKDROP_INTERVAL_SECS) as usize +} + +pub(super) fn next_rotation_delay() -> Duration { + let into_period = since_epoch().as_nanos() % ROTATION_PERIOD.as_nanos(); + ROTATION_PERIOD - Duration::from_nanos(into_period as u64) +} const PARALLAX_SCALE: f32 = 1.10; const PARALLAX_STRENGTH: f32 = 0.008; @@ -28,7 +45,10 @@ impl Component for LoadingBackdrop { fn render(&self) -> impl IntoElement { let clusters = &self.clusters; let count = clusters.len().max(1); - let mut index = use_state(|| 0usize); + // Offset against the shared tick so the first art shown is still the + // first cluster + let start = use_hook(rotation_tick); + let mut tick = use_state(rotation_tick); let stop = use_hook(|| Arc::new(AtomicBool::new(false))); @@ -46,20 +66,19 @@ impl Component for LoadingBackdrop { spawn(async move { loop { - tokio::time::sleep(Duration::from_secs(BACKDROP_INTERVAL_SECS)).await; + tokio::time::sleep(next_rotation_delay()).await; if stop.load(Ordering::Relaxed) { break; } - let next = (*index.peek() + 1) % count; - index.set(next); + tick.set(rotation_tick()); } }); } }); - let current = *index.read() % count; + let current = (*tick.read()).wrapping_sub(start) % count; let parallax_enabled = use_settings_snapshot().settings.dynamic_background_enabled; diff --git a/packages/oneclient_app/src/view/onboarding/downloading/tips.rs b/packages/oneclient_app/src/view/onboarding/downloading/tips.rs index 66485104..1759a38c 100644 --- a/packages/oneclient_app/src/view/onboarding/downloading/tips.rs +++ b/packages/oneclient_app/src/view/onboarding/downloading/tips.rs @@ -1,5 +1,9 @@ use super::*; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, Ordering}; + +use super::backdrop::{next_rotation_delay, rotation_tick}; use crate::theme::colors; const ONBOARDING_TIPS_BACKUP: &[&str] = &[ @@ -35,7 +39,7 @@ fn parse_funfacts(text: &str) -> Vec { .collect() } -/// One stable random tip for the lifetime of the component +/// A random tip that rotates in step with the backdrop art pub(super) fn use_onboarding_tip() -> String { let mut tips = use_state(|| { ONBOARDING_TIPS_BACKUP @@ -78,18 +82,46 @@ pub(super) fn use_onboarding_tip() -> String { }); }); + // Random offset against the shared tick so the run does not always open on + // the same fact let seed = use_hook(|| { std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .map(|d| d.subsec_nanos() as usize) .unwrap_or(0) }); + let mut tick = use_state(rotation_tick); + let stop = use_hook(|| Arc::new(AtomicBool::new(false))); + + use_drop({ + let stop = stop.clone(); + move || stop.store(true, Ordering::Relaxed) + }); + + use_hook({ + let stop = stop.clone(); + move || { + spawn(async move { + loop { + tokio::time::sleep(next_rotation_delay()).await; + + if stop.load(Ordering::Relaxed) { + break; + } + + tick.set(rotation_tick()); + } + }); + } + }); + + // Wrapped at read time the list is swapped out once the remote facts land let list = tips.read(); if list.is_empty() { String::new() } else { - list[seed % list.len()].clone() + list[seed.wrapping_add(*tick.read()) % list.len()].clone() } }