diff --git a/web/Cargo.toml b/web/Cargo.toml index 5494f7e..9e5fc04 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -21,7 +21,12 @@ leptos_router = { version = "0.8", features = ["nightly"] } strum.workspace = true tokio = { version = "1", features = ["rt-multi-thread"], optional = true } wasm-bindgen = { version = "=0.2.104", optional = true } -web-sys = { version = "0.3", features = ["Navigator", "Window", "Clipboard"] } +web-sys = { version = "0.3", features = [ + "Navigator", + "Window", + "Clipboard", + "Storage", +] } [features] hydrate = ["leptos/hydrate", "dep:console_error_panic_hook", "dep:wasm-bindgen"] diff --git a/web/src/app.rs b/web/src/app.rs index 3d56275..bc99423 100644 --- a/web/src/app.rs +++ b/web/src/app.rs @@ -1,7 +1,7 @@ use crate::pages::{ aes::AesPage, des::DesPage, footer::Footer, header::Header, home::Home, not_found::NotFound, }; -use leptos::{prelude::*, svg::view}; +use leptos::prelude::*; use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context}; use leptos_router::{ StaticSegment, diff --git a/web/src/pages/header.rs b/web/src/pages/header.rs index c48a1de..d54ae05 100644 --- a/web/src/pages/header.rs +++ b/web/src/pages/header.rs @@ -4,24 +4,26 @@ use std::fmt::Display; #[component] pub fn Header() -> impl IntoView { - let (theme, set_theme) = signal(Theme::Dark); + let initial_theme = { + if let Ok(Some(storage)) = window().local_storage() + && let Ok(Some(saved)) = storage.get_item("theme") + { + Theme::from_local_storage(&saved) + } else { + Theme::Dark + } + }; + + let (theme, set_theme) = signal(initial_theme); let toggle_theme = move |_| { set_theme.update(|t| *t = t.inverse()); - if let Some(body) = document().body() { - let class_list = body.class_list(); - match theme.get() { - Theme::Light => { - let _ = class_list.remove_1("dark-theme"); - let _ = class_list.add_1("light-theme"); - } - Theme::Dark => { - let _ = class_list.remove_1("light-theme"); - let _ = class_list.add_1("dark-theme"); - } - } + if let Ok(Some(storage)) = window().local_storage() { + let _ = storage.set_item("theme", theme.get().to_local_storage()); } + + apply_theme(theme.get()); }; view! { @@ -57,6 +59,20 @@ impl Theme { Self::Dark => Self::Light, } } + + fn from_local_storage(value: &str) -> Self { + match value.trim().to_lowercase().as_str() { + "light" => Self::Light, + _ => Self::Dark, + } + } + + const fn to_local_storage(self) -> &'static str { + match self { + Self::Light => "light", + Self::Dark => "dark", + } + } } impl Display for Theme { @@ -68,3 +84,19 @@ impl Display for Theme { f.write_str(s) } } + +fn apply_theme(theme: Theme) { + if let Some(body) = document().body() { + let class_list = body.class_list(); + match theme { + Theme::Light => { + let _ = class_list.remove_1("dark-theme"); + let _ = class_list.add_1("light-theme"); + } + Theme::Dark => { + let _ = class_list.remove_1("light-theme"); + let _ = class_list.add_1("dark-theme"); + } + } + } +}