mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-22 16:49:22 -05:00
release 0.10.0
This commit is contained in:
parent
7c4d23a359
commit
6c14a8e6be
8 changed files with 82 additions and 73 deletions
|
@ -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 🚀
|
||||
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
||||
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
|
||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-63%20functions-%23EF3939" alt="63 Functions" /></a>
|
||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-69%20functions-%23EF3939" alt="69 Functions" /></a>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
|
@ -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 |
|
||||
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
||||
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
|
||||
<a href="./get_started.html"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
||||
<a href="./functions.html"><img src="https://img.shields.io/badge/-63%20functions-%23EF3939" alt="63 Functions" /></a>
|
||||
<a href="./functions.html"><img src="https://img.shields.io/badge/-69%20functions-%23EF3939" alt="69 Functions" /></a>
|
||||
</p>
|
||||
</div>
|
|
@ -1,3 +0,0 @@
|
|||
# use_webtransport
|
||||
|
||||
<!-- cmdrun python3 ../extract_doc_comment.py use_webtransport -->
|
|
@ -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::<http::request::Parts>();
|
||||
}
|
||||
|
||||
view! {
|
||||
<Stylesheet id="leptos" href="/pkg/start-axum.css"/>
|
||||
|
||||
|
@ -76,11 +71,11 @@ fn HomePage() -> impl IntoView {
|
|||
|
||||
let is_dark_preferred = use_preferred_dark();
|
||||
|
||||
let (session_cookie, _) = use_cookie_with_options::<String, FromToStringCodec>(
|
||||
"session",
|
||||
let (test_cookie, _) = use_cookie_with_options::<String, FromToStringCodec>(
|
||||
"test-cookie",
|
||||
UseCookieOptions::<String, _>::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 {
|
|||
<p>{timestamp}</p>
|
||||
<p>Dark preferred: {is_dark_preferred}</p>
|
||||
<LocalStorageTest/>
|
||||
<p>Session cookie: {session_cookie}</p>
|
||||
<p>Test cookie: {move || test_cookie().unwrap_or("<Expired>".to_string())}</p>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T, Err> {
|
|||
|
||||
/// 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<dyn Fn() -> String>,
|
||||
ssr_cookies_header_getter: Rc<dyn Fn() -> Option<String>>,
|
||||
|
||||
/// 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<T, Err> Default for UseCookieOptions<T, Err> {
|
|||
let headers;
|
||||
#[cfg(feature = "actix")]
|
||||
{
|
||||
headers = expect_context::<actix_web::HttpRequest>().headers().clone();
|
||||
headers = use_context::<actix_web::HttpRequest>()
|
||||
.map(|req| req.headers().clone());
|
||||
}
|
||||
#[cfg(feature = "axum")]
|
||||
{
|
||||
headers = expect_context::<http1::request::Parts>().headers;
|
||||
headers = use_context::<http1::request::Parts>().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<T, Err> Default for UseCookieOptions<T, Err> {
|
|||
|
||||
#[cfg(any(feature = "axum", feature = "actix"))]
|
||||
{
|
||||
let response_options = expect_context::<ResponseOptions>();
|
||||
|
||||
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::<ResponseOptions>() {
|
||||
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<T, Err> Default for UseCookieOptions<T, Err> {
|
|||
}
|
||||
}
|
||||
|
||||
fn read_cookies_string(ssr_cookies_header_getter: Rc<dyn Fn() -> String>) -> String {
|
||||
fn read_cookies_string(
|
||||
ssr_cookies_header_getter: Rc<dyn Fn() -> Option<String>>,
|
||||
) -> Option<String> {
|
||||
let cookies;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
|
@ -562,7 +576,7 @@ fn read_cookies_string(ssr_cookies_header_getter: Rc<dyn Fn() -> 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<SameSite>,
|
||||
secure: bool,
|
||||
http_only: bool,
|
||||
ssr_cookies_header_getter: Rc<dyn Fn() -> String>,
|
||||
ssr_cookies_header_getter: Rc<dyn Fn() -> Option<String>>,
|
||||
) {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
|
@ -693,18 +707,19 @@ fn update_client_cookie_jar(
|
|||
same_site: Option<SameSite>,
|
||||
secure: bool,
|
||||
http_only: bool,
|
||||
ssr_cookies_header_getter: Rc<dyn Fn() -> String>,
|
||||
ssr_cookies_header_getter: Rc<dyn Fn() -> Option<String>>,
|
||||
) {
|
||||
*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<dyn Fn() -> 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<dyn Fn() -> Option<String>>,
|
||||
) -> Option<CookieJar> {
|
||||
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)]
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue