1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2024-11-22 12:01:08 +00:00

Better dark mode storage using cookie

This commit is contained in:
Felix Ableitner 2024-11-07 15:38:10 +01:00
parent 519a6c4848
commit 6cd87cf790
6 changed files with 52 additions and 32 deletions

14
Cargo.lock generated
View file

@ -1780,6 +1780,7 @@ dependencies = [
"axum-macros", "axum-macros",
"bcrypt", "bcrypt",
"chrono", "chrono",
"codee",
"config", "config",
"console_error_panic_hook", "console_error_panic_hook",
"diesel", "diesel",
@ -1796,7 +1797,6 @@ dependencies = [
"leptos", "leptos",
"leptos-use", "leptos-use",
"leptos_axum", "leptos_axum",
"leptos_darkmode",
"leptos_meta", "leptos_meta",
"leptos_router", "leptos_router",
"log", "log",
@ -2022,9 +2022,11 @@ dependencies = [
"default-struct-builder", "default-struct-builder",
"futures-util", "futures-util",
"gloo-timers", "gloo-timers",
"http",
"js-sys", "js-sys",
"lazy_static", "lazy_static",
"leptos", "leptos",
"leptos_axum",
"paste", "paste",
"thiserror", "thiserror",
"unic-langid", "unic-langid",
@ -2070,16 +2072,6 @@ dependencies = [
"typed-builder", "typed-builder",
] ]
[[package]]
name = "leptos_darkmode"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ec7c7c56b312da0a739680cc2cb70d641eb82adbc1f83a565c2e9562a96253"
dependencies = [
"leptos",
"web-sys",
]
[[package]] [[package]]
name = "leptos_dom" name = "leptos_dom"
version = "0.6.15" version = "0.6.15"

View file

@ -20,6 +20,7 @@ ssr = [
"katex/duktape", "katex/duktape",
"leptos/ssr", "leptos/ssr",
"leptos-use/ssr", "leptos-use/ssr",
"leptos-use/axum"
] ]
hydrate = [ hydrate = [
"leptos/hydrate", "leptos/hydrate",
@ -108,7 +109,7 @@ markdown-it-footnote = "0.2.0"
markdown-it-sub = "1.0.0" markdown-it-sub = "1.0.0"
markdown-it-sup = "1.0.0" markdown-it-sup = "1.0.0"
leptos-use = "0.13.6" leptos-use = "0.13.6"
leptos_darkmode = "0.2.0" codee = "0.2.0"
[dev-dependencies] [dev-dependencies]
pretty_assertions = "1.4.1" pretty_assertions = "1.4.1"

View file

@ -3,6 +3,7 @@ use crate::{
frontend::{ frontend::{
api::ApiClient, api::ApiClient,
components::nav::Nav, components::nav::Nav,
dark_mode::DarkMode,
pages::{ pages::{
article::{ article::{
actions::ArticleActions, actions::ArticleActions,
@ -37,7 +38,6 @@ use leptos::{
SignalGetUntracked, SignalGetUntracked,
SignalUpdate, SignalUpdate,
}; };
use leptos_darkmode::Darkmode;
use leptos_meta::{provide_meta_context, *}; use leptos_meta::{provide_meta_context, *};
use leptos_router::{Route, Router, Routes}; use leptos_router::{Route, Router, Routes};
use reqwest::Client; use reqwest::Client;
@ -91,18 +91,11 @@ pub fn App() -> impl IntoView {
GlobalState::update_my_profile(); GlobalState::update_my_profile();
provide_context(create_rw_signal(global_state)); provide_context(create_rw_signal(global_state));
let darkmode = Darkmode::init(); let darkmode = DarkMode::init();
provide_context(darkmode.clone()); provide_context(darkmode.clone());
let theme = move || {
if darkmode.is_light() {
"emerald"
} else {
"dim"
}
};
view! { view! {
<Html attr:data-theme=theme class="h-full" /> <Html attr:data-theme=darkmode.theme class="h-full" />
<Body class="min-h-full flex max-sm:flex-col md:divide-x divide-slate-400 divide-solid" /> <Body class="min-h-full flex max-sm:flex-col md:divide-x divide-slate-400 divide-solid" />
<> <>
<Stylesheet id="ibis" href="/pkg/ibis.css" /> <Stylesheet id="ibis" href="/pkg/ibis.css" />

View file

@ -1,6 +1,5 @@
use crate::frontend::app::GlobalState; use crate::frontend::{app::GlobalState, dark_mode::DarkMode};
use leptos::{component, use_context, view, IntoView, RwSignal, SignalWith, *}; use leptos::{component, use_context, view, IntoView, RwSignal, SignalWith, *};
use leptos_darkmode::Darkmode;
use leptos_router::*; use leptos_router::*;
#[component] #[component]
@ -22,6 +21,7 @@ pub fn Nav() -> impl IntoView {
); );
let (search_query, set_search_query) = create_signal(String::new()); let (search_query, set_search_query) = create_signal(String::new());
let mut dark_mode = expect_context::<DarkMode>();
view! { view! {
<nav class="max-sm:navbar p-2.5"> <nav class="max-sm:navbar p-2.5">
<div <div
@ -126,14 +126,8 @@ pub fn Nav() -> impl IntoView {
<input <input
type="checkbox" type="checkbox"
class="toggle" class="toggle"
checked=move || { prop:checked=dark_mode.is_dark
if expect_context::<Darkmode>().is_light() { on:click=move |_| { dark_mode.toggle() }
"checked"
} else {
""
}
}
on:click=move |_| { expect_context::<Darkmode>().toggle() }
/> />
<span class="label-text">Dark</span> <span class="label-text">Dark</span>
</label> </label>

39
src/frontend/dark_mode.rs Normal file
View file

@ -0,0 +1,39 @@
use chrono::{Duration, Local};
use codee::string::FromToStringCodec;
use leptos::{Signal, SignalGet, SignalGetUntracked, SignalSet, WriteSignal};
use leptos_use::{use_cookie_with_options, use_preferred_dark, SameSite, UseCookieOptions};
#[derive(Debug, Clone)]
pub struct DarkMode {
cookie: WriteSignal<Option<bool>>,
pub is_dark: Signal<bool>,
pub theme: Signal<&'static str>,
}
impl DarkMode {
pub fn init() -> Self {
let expires = (Local::now() + Duration::days(356)).timestamp();
let cookie_options = UseCookieOptions::default()
.path("/")
.expires(expires)
.same_site(SameSite::Strict);
let cookie =
use_cookie_with_options::<bool, FromToStringCodec>("dark_mode", cookie_options);
let is_dark = Signal::derive(move || {
let default = || use_preferred_dark().get_untracked();
cookie.0.get().unwrap_or_else(default)
});
let theme = Signal::derive(move || if is_dark.get() { "dim" } else { "emerald" });
Self {
cookie: cookie.1,
is_dark,
theme,
}
}
pub fn toggle(&mut self) {
let new = !self.is_dark.get_untracked();
self.cookie.set(Some(new));
}
}

View file

@ -5,6 +5,7 @@ use leptos::*;
pub mod api; pub mod api;
pub mod app; pub mod app;
mod components; mod components;
pub mod dark_mode;
pub mod error; pub mod error;
pub mod markdown; pub mod markdown;
pub mod pages; pub mod pages;