mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-02-02 10:54:15 -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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased] -
|
## [0.10.0] - 2024-010-31
|
||||||
|
|
||||||
### New Functions 🚀
|
### New Functions 🚀
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "leptos-use"
|
name = "leptos-use"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Marc-Stefan Cassola"]
|
authors = ["Marc-Stefan Cassola"]
|
||||||
categories = ["gui", "web-programming"]
|
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://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/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/-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>
|
</p>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -92,5 +92,5 @@ This will create the function file in the src directory, scaffold an example dir
|
||||||
| <= 0.3 | 0.3 |
|
| <= 0.3 | 0.3 |
|
||||||
| 0.4, 0.5, 0.6 | 0.4 |
|
| 0.4, 0.5, 0.6 | 0.4 |
|
||||||
| 0.7, 0.8, 0.9 | 0.5 |
|
| 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://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/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="./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>
|
</p>
|
||||||
</div>
|
</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.
|
// Provides context that manages stylesheets, titles, meta tags, etc.
|
||||||
provide_meta_context();
|
provide_meta_context();
|
||||||
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
{
|
|
||||||
expect_context::<http::request::Parts>();
|
|
||||||
}
|
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Stylesheet id="leptos" href="/pkg/start-axum.css"/>
|
<Stylesheet id="leptos" href="/pkg/start-axum.css"/>
|
||||||
|
|
||||||
|
@ -76,11 +71,11 @@ fn HomePage() -> impl IntoView {
|
||||||
|
|
||||||
let is_dark_preferred = use_preferred_dark();
|
let is_dark_preferred = use_preferred_dark();
|
||||||
|
|
||||||
let (session_cookie, _) = use_cookie_with_options::<String, FromToStringCodec>(
|
let (test_cookie, _) = use_cookie_with_options::<String, FromToStringCodec>(
|
||||||
"session",
|
"test-cookie",
|
||||||
UseCookieOptions::<String, _>::default()
|
UseCookieOptions::<String, _>::default()
|
||||||
.max_age(3600)
|
.max_age(3000)
|
||||||
.default_value(Some("Bogus session string".to_owned())),
|
.default_value(Some("Bogus string".to_owned())),
|
||||||
);
|
);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
|
@ -96,7 +91,7 @@ fn HomePage() -> impl IntoView {
|
||||||
<p>{timestamp}</p>
|
<p>{timestamp}</p>
|
||||||
<p>Dark preferred: {is_dark_preferred}</p>
|
<p>Dark preferred: {is_dark_preferred}</p>
|
||||||
<LocalStorageTest/>
|
<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.
|
/// 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
|
/// ## Demo
|
||||||
///
|
///
|
||||||
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_cookie)
|
/// [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(|| {
|
/// .ssr_cookies_header_getter(|| {
|
||||||
/// #[cfg(feature = "ssr")]
|
/// #[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| {
|
/// .ssr_set_cookie(|cookie: &Cookie| {
|
||||||
|
@ -159,7 +166,7 @@ where
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
let delay = if let Some(max_age) = max_age {
|
let delay = if let Some(max_age) = max_age {
|
||||||
Some(max_age * 1000)
|
Some(max_age)
|
||||||
} else {
|
} else {
|
||||||
expires.map(|expires| expires * 1000 - now() as i64)
|
expires.map(|expires| expires * 1000 - now() as i64)
|
||||||
};
|
};
|
||||||
|
@ -179,18 +186,20 @@ where
|
||||||
let ssr_cookies_header_getter = Rc::clone(&ssr_cookies_header_getter);
|
let ssr_cookies_header_getter = Rc::clone(&ssr_cookies_header_getter);
|
||||||
|
|
||||||
jar.update_value(|jar| {
|
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(
|
set_cookie.set(
|
||||||
jar.get(cookie_name)
|
jar.get(cookie_name)
|
||||||
.and_then(|c| {
|
.and_then(|c| {
|
||||||
codec
|
codec
|
||||||
.decode(c.value().to_string())
|
.decode(c.value().to_string())
|
||||||
.map_err(|err| on_error(err))
|
.map_err(|err| on_error(err))
|
||||||
.ok()
|
.ok()
|
||||||
})
|
})
|
||||||
.or(default_value),
|
.or(default_value),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
handle_expiration(delay, set_cookie);
|
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.
|
/// 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.
|
/// 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.
|
/// 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.
|
/// 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;
|
let headers;
|
||||||
#[cfg(feature = "actix")]
|
#[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")]
|
#[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")))]
|
#[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`");
|
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"))]
|
#[cfg(any(feature = "axum", feature = "actix"))]
|
||||||
headers
|
headers.map(|headers| {
|
||||||
.get(COOKIE)
|
headers
|
||||||
.cloned()
|
.get(COOKIE)
|
||||||
.unwrap_or_else(|| HeaderValue::from_static(""))
|
.cloned()
|
||||||
.to_str()
|
.unwrap_or_else(|| HeaderValue::from_static(""))
|
||||||
.unwrap_or_default()
|
.to_str()
|
||||||
.to_owned()
|
.unwrap_or_default()
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "ssr"))]
|
#[cfg(not(feature = "ssr"))]
|
||||||
"".to_owned()
|
None
|
||||||
}),
|
}),
|
||||||
ssr_set_cookie: Rc::new(|cookie: &Cookie| {
|
ssr_set_cookie: Rc::new(|cookie: &Cookie| {
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
|
@ -527,12 +539,12 @@ impl<T, Err> Default for UseCookieOptions<T, Err> {
|
||||||
|
|
||||||
#[cfg(any(feature = "axum", feature = "actix"))]
|
#[cfg(any(feature = "axum", feature = "actix"))]
|
||||||
{
|
{
|
||||||
let response_options = expect_context::<ResponseOptions>();
|
if let Some(response_options) = use_context::<ResponseOptions>() {
|
||||||
|
if let Ok(header_value) =
|
||||||
if let Ok(header_value) =
|
HeaderValue::from_str(&cookie.encoded().to_string())
|
||||||
HeaderValue::from_str(&cookie.encoded().to_string())
|
{
|
||||||
{
|
response_options.insert_header(SET_COOKIE, header_value);
|
||||||
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;
|
let cookies;
|
||||||
|
|
||||||
#[cfg(feature = "ssr")]
|
#[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 js_value: wasm_bindgen::JsValue = leptos::document().into();
|
||||||
let document: web_sys::HtmlDocument = js_value.unchecked_into();
|
let document: web_sys::HtmlDocument = js_value.unchecked_into();
|
||||||
cookies = document.cookie().unwrap_or_default();
|
cookies = Some(document.cookie().unwrap_or_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
cookies
|
cookies
|
||||||
|
@ -657,7 +671,7 @@ fn write_client_cookie(
|
||||||
same_site: Option<SameSite>,
|
same_site: Option<SameSite>,
|
||||||
secure: bool,
|
secure: bool,
|
||||||
http_only: 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;
|
use wasm_bindgen::JsCast;
|
||||||
|
|
||||||
|
@ -693,18 +707,19 @@ fn update_client_cookie_jar(
|
||||||
same_site: Option<SameSite>,
|
same_site: Option<SameSite>,
|
||||||
secure: bool,
|
secure: bool,
|
||||||
http_only: 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 {
|
jar.add_original(cookie);
|
||||||
let cookie = build_cookie_from_options(
|
} else {
|
||||||
name, max_age, expires, http_only, secure, path, same_site, domain, value,
|
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 {
|
fn load_and_parse_cookie_jar(
|
||||||
let mut jar = CookieJar::new();
|
ssr_cookies_header_getter: Rc<dyn Fn() -> Option<String>>,
|
||||||
let cookies = read_cookies_string(ssr_cookies_header_getter);
|
) -> 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
|
||||||
jar.add_original(cookie);
|
})
|
||||||
}
|
|
||||||
|
|
||||||
jar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Copy, Clone)]
|
#[derive(Default, Copy, Clone)]
|
||||||
|
|
|
@ -41,11 +41,11 @@ pub fn use_device_orientation() -> UseDeviceOrientationReturn {
|
||||||
let beta = || None;
|
let beta = || None;
|
||||||
let gamma = || None;
|
let gamma = || None;
|
||||||
} else {
|
} else {
|
||||||
use crate::{use_event_listener_with_options, UseEventListenerOptions};
|
use crate::{use_event_listener_with_options, UseEventListenerOptions, use_supported};
|
||||||
use leptos::ev::deviceorientation;
|
use leptos::ev::deviceorientation;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
let is_supported = Signal::derive(|| js_sys::Reflect::has(
|
let is_supported = use_supported(|| js_sys::Reflect::has(
|
||||||
&window(),
|
&window(),
|
||||||
&JsValue::from_str("DeviceOrientationEvent"),
|
&JsValue::from_str("DeviceOrientationEvent"),
|
||||||
).unwrap_or(false));
|
).unwrap_or(false));
|
||||||
|
@ -54,7 +54,7 @@ pub fn use_device_orientation() -> UseDeviceOrientationReturn {
|
||||||
let (beta, set_beta) = create_signal(None);
|
let (beta, set_beta) = create_signal(None);
|
||||||
let (gamma, set_gamma) = 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(
|
let cleanup = use_event_listener_with_options(
|
||||||
window(),
|
window(),
|
||||||
deviceorientation,
|
deviceorientation,
|
||||||
|
|
Loading…
Add table
Reference in a new issue