From 2c36bf0ff68a59586abcf6f3a4ecd75d21ed1a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Sun, 11 Feb 2024 01:03:12 +0100 Subject: [PATCH 1/2] Add `initial_value_from_url_param` option to `UseColorModeOptions` --- Cargo.toml | 4 ++++ src/core/mod.rs | 1 + src/core/url.rs | 20 ++++++++++++++++++++ src/storage/use_storage.rs | 2 +- src/use_color_mode.rs | 38 +++++++++++++++++++++++++++++++++++--- 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/core/url.rs diff --git a/Cargo.toml b/Cargo.toml index 6d25fa0..53c9a27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ serde_json = { version = "1", optional = true } thiserror = "1" wasm-bindgen = "0.2.88" wasm-bindgen-futures = "0.4" +log = "0.4" [dependencies.web-sys] version = "0.3" @@ -70,6 +71,7 @@ features = [ "IntersectionObserver", "IntersectionObserverInit", "IntersectionObserverEntry", + "Location", "MediaDevices", "MediaQueryList", "MediaStream", @@ -112,6 +114,8 @@ features = [ "Touch", "TouchEvent", "TouchList", + "Url", + "UrlSearchParams", "VisibilityState", "WebSocket", "WebTransport", diff --git a/src/core/mod.rs b/src/core/mod.rs index 9abe354..577cf7f 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -9,6 +9,7 @@ mod position; mod size; mod ssr_safe_method; mod storage; +pub(crate) mod url; pub use connection_ready_state::*; pub(crate) use datetime::*; diff --git a/src/core/url.rs b/src/core/url.rs new file mode 100644 index 0000000..bddd7a9 --- /dev/null +++ b/src/core/url.rs @@ -0,0 +1,20 @@ +use leptos::window; + +fn get() -> web_sys::Url { + web_sys::Url::new( + &window() + .location() + .href() + .expect("Failed to get location.href from the browser"), + ) + .expect("Failed to parse location.href from the browser") +} + +pub mod params { + use super::get as current_url; + + /// Get a URL param value from the URL of the browser + pub fn get(k: &str) -> Option { + current_url().search_params().get(k) + } +} diff --git a/src/storage/use_storage.rs b/src/storage/use_storage.rs index d773e81..c95343f 100644 --- a/src/storage/use_storage.rs +++ b/src/storage/use_storage.rs @@ -67,7 +67,7 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage"; /// pub greeting: String, /// } /// -/// // Default can be used to implement intial or deleted values. +/// // Default can be used to implement initial or deleted values. /// // You can also use a signal via UseStorageOptions::default_value` /// impl Default for MyState { /// fn default() -> Self { diff --git a/src/use_color_mode.rs b/src/use_color_mode.rs index 919efde..550c993 100644 --- a/src/use_color_mode.rs +++ b/src/use_color_mode.rs @@ -1,3 +1,4 @@ +use crate::core::url; use crate::core::StorageType; use crate::core::{ElementMaybeSignal, MaybeRwSignal}; use crate::storage::{use_storage_with_options, UseStorageOptions}; @@ -106,6 +107,7 @@ where target, attribute, initial_value, + initial_value_from_url_param, on_changed, storage_signal, custom_modes, @@ -136,13 +138,26 @@ where } }); + let initial_value_from_url = match initial_value_from_url_param { + Some(param) => match url::params::get(¶m) { + Some(value) => match ColorMode::from_str(&value) { + Ok(mode) => Some(MaybeRwSignal::Static(mode)), + Err(_) => None, + }, + None => None, + }, + None => None, + }; + let update_previous_value = initial_value_from_url.is_some(); + let (store, set_store) = get_store_signal( - initial_value, + initial_value_from_url.unwrap_or(initial_value), storage_signal, &storage_key, storage_enabled, storage, listen_to_storage_changes, + update_previous_value, ); let state = Signal::derive(move || { @@ -255,22 +270,34 @@ fn get_store_signal( storage_enabled: bool, storage: StorageType, listen_to_storage_changes: bool, + update_previous_value: bool, ) -> (Signal, WriteSignal) { - if let Some(storage_signal) = storage_signal { + let initial_value_copy = initial_value.clone(); + + let (store, set_store) = if let Some(storage_signal) = storage_signal { let (store, set_store) = storage_signal.split(); (store.into(), set_store) } else if storage_enabled { - let (store, set_store, _) = use_storage_with_options::( + let (store, set_store, remove) = use_storage_with_options::( storage, storage_key, UseStorageOptions::default() .listen_to_storage_changes(listen_to_storage_changes) .initial_value(initial_value), ); + if update_previous_value { + remove(); + } (store, set_store) } else { initial_value.into_signal() + }; + + if update_previous_value { + set_store.set(initial_value_copy.into_signal().0.get_untracked()); } + + (store, set_store) } impl Display for ColorMode { @@ -330,6 +357,10 @@ where #[builder(into)] initial_value: MaybeRwSignal, + /// Discover the initial value of the color mode from an URL parameter. Defaults to `None`. + #[builder(into)] + initial_value_from_url_param: Option, + /// Custom modes that you plan to use as `ColorMode::Custom(x)`. Defaults to `vec![]`. custom_modes: Vec, @@ -386,6 +417,7 @@ impl Default for UseColorModeOptions<&'static str, web_sys::Element> { target: "html", attribute: "class".into(), initial_value: ColorMode::Auto.into(), + initial_value_from_url_param: None, custom_modes: vec![], on_changed: Rc::new(move |mode, default_handler| (default_handler)(mode)), storage_signal: None, From 3109a54f127e0f0bef85ea165e27960d98e6f8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Thu, 15 Feb 2024 22:45:28 +0100 Subject: [PATCH 2/2] Rewrite implementation --- Cargo.toml | 1 - src/use_color_mode.rs | 51 ++++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 53c9a27..f745f41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ serde_json = { version = "1", optional = true } thiserror = "1" wasm-bindgen = "0.2.88" wasm-bindgen-futures = "0.4" -log = "0.4" [dependencies.web-sys] version = "0.3" diff --git a/src/use_color_mode.rs b/src/use_color_mode.rs index 550c993..aabf8f1 100644 --- a/src/use_color_mode.rs +++ b/src/use_color_mode.rs @@ -108,6 +108,7 @@ where attribute, initial_value, initial_value_from_url_param, + initial_value_from_url_param_to_storage, on_changed, storage_signal, custom_modes, @@ -138,28 +139,31 @@ where } }); - let initial_value_from_url = match initial_value_from_url_param { - Some(param) => match url::params::get(¶m) { - Some(value) => match ColorMode::from_str(&value) { - Ok(mode) => Some(MaybeRwSignal::Static(mode)), - Err(_) => None, - }, - None => None, - }, - None => None, - }; - let update_previous_value = initial_value_from_url.is_some(); + let mut initial_value_from_url = None; + if let Some(param) = initial_value_from_url_param.as_ref() { + if let Some(value) = url::params::get(param) { + initial_value_from_url = ColorMode::from_str(&value).map(MaybeRwSignal::Static).ok() + } + } let (store, set_store) = get_store_signal( - initial_value_from_url.unwrap_or(initial_value), + initial_value_from_url.clone().unwrap_or(initial_value), storage_signal, &storage_key, storage_enabled, storage, listen_to_storage_changes, - update_previous_value, ); + if let Some(initial_value_from_url) = initial_value_from_url { + let value = initial_value_from_url.into_signal().0.get_untracked(); + if initial_value_from_url_param_to_storage { + set_store.set(value); + } else { + set_store.set_untracked(value); + } + } + let state = Signal::derive(move || { let value = store.get(); if value == ColorMode::Auto { @@ -270,34 +274,22 @@ fn get_store_signal( storage_enabled: bool, storage: StorageType, listen_to_storage_changes: bool, - update_previous_value: bool, ) -> (Signal, WriteSignal) { - let initial_value_copy = initial_value.clone(); - - let (store, set_store) = if let Some(storage_signal) = storage_signal { + if let Some(storage_signal) = storage_signal { let (store, set_store) = storage_signal.split(); (store.into(), set_store) } else if storage_enabled { - let (store, set_store, remove) = use_storage_with_options::( + let (store, set_store, _) = use_storage_with_options::( storage, storage_key, UseStorageOptions::default() .listen_to_storage_changes(listen_to_storage_changes) .initial_value(initial_value), ); - if update_previous_value { - remove(); - } (store, set_store) } else { initial_value.into_signal() - }; - - if update_previous_value { - set_store.set(initial_value_copy.into_signal().0.get_untracked()); } - - (store, set_store) } impl Display for ColorMode { @@ -361,6 +353,10 @@ where #[builder(into)] initial_value_from_url_param: Option, + /// Update the initial value of the discovered color mode from URL parameter into storage. + /// Defaults to `false`. + initial_value_from_url_param_to_storage: bool, + /// Custom modes that you plan to use as `ColorMode::Custom(x)`. Defaults to `vec![]`. custom_modes: Vec, @@ -418,6 +414,7 @@ impl Default for UseColorModeOptions<&'static str, web_sys::Element> { attribute: "class".into(), initial_value: ColorMode::Auto.into(), initial_value_from_url_param: None, + initial_value_from_url_param_to_storage: false, custom_modes: vec![], on_changed: Rc::new(move |mode, default_handler| (default_handler)(mode)), storage_signal: None,