From 6c14a8e6be002756e030bb42090ec3d99e55b4bf Mon Sep 17 00:00:00 2001 From: Maccesch Date: Wed, 31 Jan 2024 19:55:30 +0000 Subject: [PATCH] release 0.10.0 --- CHANGELOG.md | 2 +- Cargo.toml | 2 +- README.md | 4 +- docs/book/src/introduction.md | 2 +- docs/book/src/network/use_webtransport.md | 3 - examples/ssr/src/app.rs | 15 +-- src/use_cookie.rs | 121 ++++++++++++---------- src/use_device_orientation.rs | 6 +- 8 files changed, 82 insertions(+), 73 deletions(-) delete mode 100644 docs/book/src/network/use_webtransport.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f98ec89..c1d9aa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] - +## [0.10.0] - 2024-010-31 ### New Functions 🚀 diff --git a/Cargo.toml b/Cargo.toml index 96570e4..c8188d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leptos-use" -version = "0.9.0" +version = "0.10.0" edition = "2021" authors = ["Marc-Stefan Cassola"] categories = ["gui", "web-programming"] diff --git a/README.md b/README.md index b28c69a..4bfe646 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Crates.io SSR Docs & Demos - 63 Functions + 69 Functions


@@ -92,5 +92,5 @@ This will create the function file in the src directory, scaffold an example dir | <= 0.3 | 0.3 | | 0.4, 0.5, 0.6 | 0.4 | | 0.7, 0.8, 0.9 | 0.5 | -| main | 0.6.0-beta | +| 0.10 | 0.6 | diff --git a/docs/book/src/introduction.md b/docs/book/src/introduction.md index a8c07ae..3e0ce5b 100644 --- a/docs/book/src/introduction.md +++ b/docs/book/src/introduction.md @@ -12,6 +12,6 @@ Crates.io SSR Docs & Demos - 63 Functions + 69 Functions

\ No newline at end of file diff --git a/docs/book/src/network/use_webtransport.md b/docs/book/src/network/use_webtransport.md deleted file mode 100644 index 7bf8da0..0000000 --- a/docs/book/src/network/use_webtransport.md +++ /dev/null @@ -1,3 +0,0 @@ -# use_webtransport - - diff --git a/examples/ssr/src/app.rs b/examples/ssr/src/app.rs index 0cc7768..fa44443 100644 --- a/examples/ssr/src/app.rs +++ b/examples/ssr/src/app.rs @@ -16,11 +16,6 @@ pub fn App() -> impl IntoView { // Provides context that manages stylesheets, titles, meta tags, etc. provide_meta_context(); - #[cfg(feature = "ssr")] - { - expect_context::(); - } - view! { @@ -76,11 +71,11 @@ fn HomePage() -> impl IntoView { let is_dark_preferred = use_preferred_dark(); - let (session_cookie, _) = use_cookie_with_options::( - "session", + let (test_cookie, _) = use_cookie_with_options::( + "test-cookie", UseCookieOptions::::default() - .max_age(3600) - .default_value(Some("Bogus session string".to_owned())), + .max_age(3000) + .default_value(Some("Bogus string".to_owned())), ); view! { @@ -96,7 +91,7 @@ fn HomePage() -> impl IntoView {

{timestamp}

Dark preferred: {is_dark_preferred}

-

Session cookie: {session_cookie}

+

Test cookie: {move || test_cookie().unwrap_or("".to_string())}

} } diff --git a/src/use_cookie.rs b/src/use_cookie.rs index 758031b..575e2ae 100644 --- a/src/use_cookie.rs +++ b/src/use_cookie.rs @@ -10,6 +10,13 @@ use std::rc::Rc; /// SSR-friendly and reactive cookie access. /// +/// You can use this function multiple times in your for the same cookie and they're signals will synchronize +/// (even across windows/tabs). But there is no way to listen to changes to `document.cookie` directly so in case +/// something outside of this function changes the cookie, the signal will **not** be updated. +/// +/// When the options `max_age` or `expire` is given then the returned signal will +/// automatically turn to `None` after that time. +/// /// ## Demo /// /// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_cookie) @@ -109,7 +116,7 @@ use std::rc::Rc; /// .ssr_cookies_header_getter(|| { /// #[cfg(feature = "ssr")] /// { -/// "Somehow get the value of the cookie header as a string".to_owned() +/// Some("Somehow get the value of the cookie header as a string".to_owned()) /// } /// }) /// .ssr_set_cookie(|cookie: &Cookie| { @@ -159,7 +166,7 @@ where } = options; let delay = if let Some(max_age) = max_age { - Some(max_age * 1000) + Some(max_age) } else { expires.map(|expires| expires * 1000 - now() as i64) }; @@ -179,18 +186,20 @@ where let ssr_cookies_header_getter = Rc::clone(&ssr_cookies_header_getter); jar.update_value(|jar| { - *jar = load_and_parse_cookie_jar(ssr_cookies_header_getter); + if let Some(new_jar) = load_and_parse_cookie_jar(ssr_cookies_header_getter) { + *jar = new_jar; - set_cookie.set( - jar.get(cookie_name) - .and_then(|c| { - codec - .decode(c.value().to_string()) - .map_err(|err| on_error(err)) - .ok() - }) - .or(default_value), - ); + set_cookie.set( + jar.get(cookie_name) + .and_then(|c| { + codec + .decode(c.value().to_string()) + .map_err(|err| on_error(err)) + .ok() + }) + .or(default_value), + ); + } }); handle_expiration(delay, set_cookie); @@ -433,7 +442,7 @@ pub struct UseCookieOptions { /// Getter function to return the string value of the cookie header. /// When you use one of the features "axum" or "actix" there's a valid default implementation provided. - ssr_cookies_header_getter: Rc String>, + ssr_cookies_header_getter: Rc Option>, /// Function to add a set cookie header to the response on the server. /// When you use one of the features "axum" or "actix" there's a valid default implementation provided. @@ -476,30 +485,33 @@ impl Default for UseCookieOptions { let headers; #[cfg(feature = "actix")] { - headers = expect_context::().headers().clone(); + headers = use_context::() + .map(|req| req.headers().clone()); } #[cfg(feature = "axum")] { - headers = expect_context::().headers; + headers = use_context::().map(|parts| parts.headers); } #[cfg(all(not(feature = "axum"), not(feature = "actix")))] { leptos::logging::warn!("If you're using use_cookie without the feature `axum` or `actix` enabled, you should provide the option `ssr_cookies_header_getter`"); - "".to_owned() + None } #[cfg(any(feature = "axum", feature = "actix"))] - headers - .get(COOKIE) - .cloned() - .unwrap_or_else(|| HeaderValue::from_static("")) - .to_str() - .unwrap_or_default() - .to_owned() + headers.map(|headers| { + headers + .get(COOKIE) + .cloned() + .unwrap_or_else(|| HeaderValue::from_static("")) + .to_str() + .unwrap_or_default() + .to_owned() + }) } #[cfg(not(feature = "ssr"))] - "".to_owned() + None }), ssr_set_cookie: Rc::new(|cookie: &Cookie| { #[cfg(feature = "ssr")] @@ -527,12 +539,12 @@ impl Default for UseCookieOptions { #[cfg(any(feature = "axum", feature = "actix"))] { - let response_options = expect_context::(); - - if let Ok(header_value) = - HeaderValue::from_str(&cookie.encoded().to_string()) - { - response_options.insert_header(SET_COOKIE, header_value); + if let Some(response_options) = use_context::() { + if let Ok(header_value) = + HeaderValue::from_str(&cookie.encoded().to_string()) + { + response_options.insert_header(SET_COOKIE, header_value); + } } } } @@ -546,7 +558,9 @@ impl Default for UseCookieOptions { } } -fn read_cookies_string(ssr_cookies_header_getter: Rc String>) -> String { +fn read_cookies_string( + ssr_cookies_header_getter: Rc Option>, +) -> Option { let cookies; #[cfg(feature = "ssr")] @@ -562,7 +576,7 @@ fn read_cookies_string(ssr_cookies_header_getter: Rc String>) -> Str let js_value: wasm_bindgen::JsValue = leptos::document().into(); let document: web_sys::HtmlDocument = js_value.unchecked_into(); - cookies = document.cookie().unwrap_or_default(); + cookies = Some(document.cookie().unwrap_or_default()); } cookies @@ -657,7 +671,7 @@ fn write_client_cookie( same_site: Option, secure: bool, http_only: bool, - ssr_cookies_header_getter: Rc String>, + ssr_cookies_header_getter: Rc Option>, ) { use wasm_bindgen::JsCast; @@ -693,18 +707,19 @@ fn update_client_cookie_jar( same_site: Option, secure: bool, http_only: bool, - ssr_cookies_header_getter: Rc String>, + ssr_cookies_header_getter: Rc Option>, ) { - *jar = load_and_parse_cookie_jar(ssr_cookies_header_getter); + if let Some(new_jar) = load_and_parse_cookie_jar(ssr_cookies_header_getter) { + *jar = new_jar; + if let Some(value) = value { + let cookie = build_cookie_from_options( + name, max_age, expires, http_only, secure, path, same_site, domain, value, + ); - if let Some(value) = value { - let cookie = build_cookie_from_options( - name, max_age, expires, http_only, secure, path, same_site, domain, value, - ); - - jar.add_original(cookie); - } else { - jar.force_remove(name); + jar.add_original(cookie); + } else { + jar.force_remove(name); + } } } @@ -791,15 +806,17 @@ fn write_server_cookie( } } -fn load_and_parse_cookie_jar(ssr_cookies_header_getter: Rc String>) -> CookieJar { - let mut jar = CookieJar::new(); - let cookies = read_cookies_string(ssr_cookies_header_getter); +fn load_and_parse_cookie_jar( + ssr_cookies_header_getter: Rc Option>, +) -> Option { + read_cookies_string(ssr_cookies_header_getter).map(|cookies| { + let mut jar = CookieJar::new(); + for cookie in Cookie::split_parse_encoded(cookies).flatten() { + jar.add_original(cookie); + } - for cookie in Cookie::split_parse_encoded(cookies).flatten() { - jar.add_original(cookie); - } - - jar + jar + }) } #[derive(Default, Copy, Clone)] diff --git a/src/use_device_orientation.rs b/src/use_device_orientation.rs index 97a3d0e..9674220 100644 --- a/src/use_device_orientation.rs +++ b/src/use_device_orientation.rs @@ -41,11 +41,11 @@ pub fn use_device_orientation() -> UseDeviceOrientationReturn { let beta = || None; let gamma = || None; } else { - use crate::{use_event_listener_with_options, UseEventListenerOptions}; + use crate::{use_event_listener_with_options, UseEventListenerOptions, use_supported}; use leptos::ev::deviceorientation; use wasm_bindgen::JsValue; - let is_supported = Signal::derive(|| js_sys::Reflect::has( + let is_supported = use_supported(|| js_sys::Reflect::has( &window(), &JsValue::from_str("DeviceOrientationEvent"), ).unwrap_or(false)); @@ -54,7 +54,7 @@ pub fn use_device_orientation() -> UseDeviceOrientationReturn { let (beta, set_beta) = create_signal(None); let (gamma, set_gamma) = create_signal(None); - if is_supported.get() { + if is_supported.get_untracked() { let cleanup = use_event_listener_with_options( window(), deviceorientation,