added use_broadcast_channel

This commit is contained in:
Maccesch 2024-01-29 21:29:39 +00:00
parent 0d546d464a
commit 7fe153e525
21 changed files with 282 additions and 78 deletions

5
.idea/leptos-use.iml generated
View file

@ -63,6 +63,11 @@
<sourceFolder url="file://$MODULE_DIR$/examples/use_web_notification/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/examples/use_web_notification/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_webtransport_with_server/client/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/examples/use_webtransport_with_server/client/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_webtransport_with_server/server/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/examples/use_webtransport_with_server/server/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_broadcast_channel/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_cookie/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_device_pixel_ratio/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_element_bounding/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/examples/use_mouse_in_element/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/examples/use_event_listener/target" /> <excludeFolder url="file://$MODULE_DIR$/examples/use_event_listener/target" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/docs/book/book" /> <excludeFolder url="file://$MODULE_DIR$/docs/book/book" />

View file

@ -61,7 +61,7 @@
# Network # Network
- [use_websocket](network/use_websocket.md) - [use_websocket](network/use_websocket.md)
- [use_webtransport](network/use_webtransport.md) <!-- - [use_webtransport](network/use_webtransport.md) -->
# Animation # Animation

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] } leptos = { version = "0.6", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
console_log = "1" console_log = "1"
log = "0.4" log = "0.4"

View file

@ -1,13 +1,56 @@
use leptos::*; use leptos::*;
use leptos_use::docs::demo_or_body; use leptos_use::docs::demo_or_body;
use leptos_use::use_broadcast_channel; use leptos_use::utils::FromToStringCodec;
use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
#[component] #[component]
fn Demo() -> impl IntoView { fn Demo() -> impl IntoView {
let UseBroadcastChannelReturn {
is_supported,
message,
post,
error,
..
} = use_broadcast_channel::<String, FromToStringCodec>("leptos-use-demo-channel");
use_broadcast_channel(); let (input_value, set_input_value) = create_signal(String::new());
view! { } view! {
<p>Please open this page in at least two tabs</p>
<Show
when=move || is_supported()
fallback=move || view! { <p>"BroadcastChannel not supported"</p> }
>
<form on:submit={
let post = post.clone();
move |ev: web_sys::SubmitEvent| {
ev.prevent_default();
let value = input_value();
post(&value);
}
}>
<input
value=input_value
on:input=move |event| {
set_input_value(event_target_value(&event));
}
type="text"
/>
<button type="submit">Send Message</button>
</form>
<Show when=move || message().is_some()>
<p>"Received message: " {move || message().as_ref().unwrap().to_string()}</p>
</Show>
<Show when=move || error().is_some()>
<p>"Error: " {move || format!("{:?}", error().as_ref().unwrap())}</p>
</Show>
</Show>
}
} }
fn main() { fn main() {

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
leptos = { version = "0.5.0-beta2", features = ["nightly", "csr"] } leptos = { version = "0.6", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
console_log = "1" console_log = "1"
log = "0.4" log = "0.4"

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
leptos = { version = "0.5.0-rc1", features = ["nightly", "csr"] } leptos = { version = "0.6", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
console_log = "1" console_log = "1"
log = "0.4" log = "0.4"

View file

@ -9,21 +9,21 @@ pub mod math;
pub mod storage; pub mod storage;
pub mod utils; pub mod utils;
cfg_if! { if #[cfg(web_sys_unstable_apis)] { #[cfg(web_sys_unstable_apis)]
mod use_webtransport; mod use_webtransport;
pub use use_webtransport::*; #[cfg(web_sys_unstable_apis)]
}} pub use use_webtransport::*;
mod is_err; mod is_err;
mod is_none; mod is_none;
mod is_ok; mod is_ok;
mod is_some; mod is_some;
mod on_click_outside; mod on_click_outside;
mod use_broadcast_channel;
mod signal_debounced; mod signal_debounced;
mod signal_throttled; mod signal_throttled;
mod use_active_element; mod use_active_element;
mod use_breakpoints; mod use_breakpoints;
mod use_broadcast_channel;
mod use_color_mode; mod use_color_mode;
mod use_cookie; mod use_cookie;
mod use_css_var; mod use_css_var;
@ -79,11 +79,11 @@ pub use is_none::*;
pub use is_ok::*; pub use is_ok::*;
pub use is_some::*; pub use is_some::*;
pub use on_click_outside::*; pub use on_click_outside::*;
pub use use_broadcast_channel::*;
pub use signal_debounced::*; pub use signal_debounced::*;
pub use signal_throttled::*; pub use signal_throttled::*;
pub use use_active_element::*; pub use use_active_element::*;
pub use use_breakpoints::*; pub use use_breakpoints::*;
pub use use_broadcast_channel::*;
pub use use_color_mode::*; pub use use_color_mode::*;
pub use use_cookie::*; pub use use_cookie::*;
pub use use_css_var::*; pub use use_css_var::*;
@ -125,7 +125,6 @@ pub use use_timestamp::*;
pub use use_to_string::*; pub use use_to_string::*;
pub use use_web_notification::*; pub use use_web_notification::*;
pub use use_websocket::*; pub use use_websocket::*;
pub use use_webtransport::*;
pub use use_window::*; pub use use_window::*;
pub use use_window_focus::*; pub use use_window_focus::*;
pub use use_window_scroll::*; pub use use_window_scroll::*;

View file

@ -3,11 +3,6 @@ mod use_session_storage;
mod use_storage; mod use_storage;
pub use crate::core::StorageType; pub use crate::core::StorageType;
#[cfg(feature = "serde")]
pub use codec_json::*;
#[cfg(feature = "prost")]
pub use codec_prost::*;
pub use codec_string::*;
pub use use_local_storage::*; pub use use_local_storage::*;
pub use use_session_storage::*; pub use use_session_storage::*;
pub use use_storage::*; pub use use_storage::*;

View file

@ -1,4 +1,5 @@
use super::{use_storage_with_options, Codec, StorageType, UseStorageOptions}; use super::{use_storage_with_options, StorageType, UseStorageOptions};
use crate::utils::StringCodec;
use leptos::signal_prelude::*; use leptos::signal_prelude::*;
/// Reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). /// Reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
@ -14,7 +15,7 @@ pub fn use_local_storage<T, C>(
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + Default + PartialEq, T: Clone + Default + PartialEq,
C: Codec<T> + Default, C: StringCodec<T> + Default,
{ {
use_storage_with_options( use_storage_with_options(
StorageType::Local, StorageType::Local,
@ -30,7 +31,7 @@ pub fn use_local_storage_with_options<T, C>(
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + PartialEq, T: Clone + PartialEq,
C: Codec<T>, C: StringCodec<T>,
{ {
use_storage_with_options(StorageType::Local, key, options) use_storage_with_options(StorageType::Local, key, options)
} }

View file

@ -1,4 +1,5 @@
use super::{use_storage_with_options, Codec, StorageType, UseStorageOptions}; use super::{use_storage_with_options, StorageType, UseStorageOptions};
use crate::utils::StringCodec;
use leptos::signal_prelude::*; use leptos::signal_prelude::*;
/// Reactive [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage). /// Reactive [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage).
@ -14,7 +15,7 @@ pub fn use_session_storage<T, C>(
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + Default + PartialEq, T: Clone + Default + PartialEq,
C: Codec<T> + Default, C: StringCodec<T> + Default,
{ {
use_storage_with_options( use_storage_with_options(
StorageType::Session, StorageType::Session,
@ -30,7 +31,7 @@ pub fn use_session_storage_with_options<T, C>(
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + PartialEq, T: Clone + PartialEq,
C: Codec<T>, C: StringCodec<T>,
{ {
use_storage_with_options(StorageType::Session, key, options) use_storage_with_options(StorageType::Session, key, options)
} }

View file

@ -1,3 +1,4 @@
use crate::utils::FromToStringCodec;
use crate::{ use crate::{
core::{MaybeRwSignal, StorageType}, core::{MaybeRwSignal, StorageType},
utils::{FilterOptions, StringCodec}, utils::{FilterOptions, StringCodec},
@ -28,18 +29,19 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
/// ///
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage_with_options, UseStorageOptions, StringCodec, JsonCodec, ProstCodec}; /// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage_with_options, UseStorageOptions};
/// # use serde::{Deserialize, Serialize}; /// # use serde::{Deserialize, Serialize};
/// # use leptos_use::utils::{FromToStringCodec, JsonCodec, ProstCodec};
/// # /// #
/// # pub fn Demo() -> impl IntoView { /// # pub fn Demo() -> impl IntoView {
/// // Binds a struct: /// // Binds a struct:
/// let (state, set_state, _) = use_local_storage::<MyState, JsonCodec>("my-state"); /// let (state, set_state, _) = use_local_storage::<MyState, JsonCodec>("my-state");
/// ///
/// // Binds a bool, stored as a string: /// // Binds a bool, stored as a string:
/// let (flag, set_flag, remove_flag) = use_session_storage::<bool, StringCodec>("my-flag"); /// let (flag, set_flag, remove_flag) = use_session_storage::<bool, FromToStringCodec>("my-flag");
/// ///
/// // Binds a number, stored as a string: /// // Binds a number, stored as a string:
/// let (count, set_count, _) = use_session_storage::<i32, StringCodec>("my-count"); /// let (count, set_count, _) = use_session_storage::<i32, FromToStringCodec>("my-count");
/// // Binds a number, stored in JSON: /// // Binds a number, stored in JSON:
/// let (count, set_count, _) = use_session_storage::<i32, JsonCodec>("my-count-kept-in-js"); /// let (count, set_count, _) = use_session_storage::<i32, JsonCodec>("my-count-kept-in-js");
/// ///
@ -89,7 +91,11 @@ pub fn use_storage(
storage_type: StorageType, storage_type: StorageType,
key: impl AsRef<str>, key: impl AsRef<str>,
) -> (Signal<String>, WriteSignal<String>, impl Fn() + Clone) { ) -> (Signal<String>, WriteSignal<String>, impl Fn() + Clone) {
use_storage_with_options::<String, StringCodec>(storage_type, key, UseStorageOptions::default()) use_storage_with_options::<String, FromToStringCodec>(
storage_type,
key,
UseStorageOptions::default(),
)
} }
/// Version of [`use_storage`] that accepts [`UseStorageOptions`]. /// Version of [`use_storage`] that accepts [`UseStorageOptions`].
@ -100,7 +106,7 @@ pub fn use_storage_with_options<T, C>(
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + PartialEq, T: Clone + PartialEq,
C: Codec<T>, C: StringCodec<T>,
{ {
let UseStorageOptions { let UseStorageOptions {
codec, codec,
@ -322,7 +328,7 @@ pub enum UseStorageError<Err> {
} }
/// Options for use with [`use_local_storage_with_options`], [`use_session_storage_with_options`] and [`use_storage_with_options`]. /// Options for use with [`use_local_storage_with_options`], [`use_session_storage_with_options`] and [`use_storage_with_options`].
pub struct UseStorageOptions<T: 'static, C: Codec<T>> { pub struct UseStorageOptions<T: 'static, C: StringCodec<T>> {
// Translates to and from UTF-16 strings // Translates to and from UTF-16 strings
codec: C, codec: C,
// Callback for when an error occurs // Callback for when an error occurs
@ -344,7 +350,7 @@ fn handle_error<T, Err>(
result.map_err(|err| (on_error)(err)) result.map_err(|err| (on_error)(err))
} }
impl<T: Default, C: Codec<T> + Default> Default for UseStorageOptions<T, C> { impl<T: Default, C: StringCodec<T> + Default> Default for UseStorageOptions<T, C> {
fn default() -> Self { fn default() -> Self {
Self { Self {
codec: C::default(), codec: C::default(),
@ -356,7 +362,7 @@ impl<T: Default, C: Codec<T> + Default> Default for UseStorageOptions<T, C> {
} }
} }
impl<T: Default, C: Codec<T>> UseStorageOptions<T, C> { impl<T: Default, C: StringCodec<T>> UseStorageOptions<T, C> {
/// Sets the codec to use for encoding and decoding values to and from UTF-16 strings. /// Sets the codec to use for encoding and decoding values to and from UTF-16 strings.
pub fn codec(self, codec: impl Into<C>) -> Self { pub fn codec(self, codec: impl Into<C>) -> Self {
Self { Self {

View file

@ -1,9 +1,14 @@
use crate::storage::Codec; use crate::utils::StringCodec;
use crate::use_supported; use crate::{
use default_struct_builder::DefaultBuilder; use_event_listener, use_event_listener_with_options, use_supported, UseEventListenerOptions,
};
use leptos::*; use leptos::*;
use thiserror::Error;
use wasm_bindgen::JsValue;
/// Reactive [BroadcastChannel API](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel).
/// ///
/// Closes a broadcast channel automatically when the component is cleaned up.
/// ///
/// ## Demo /// ## Demo
/// ///
@ -11,59 +16,194 @@ use leptos::*;
/// ///
/// ## Usage /// ## Usage
/// ///
/// The BroadcastChannel interface represents a named channel that any browsing context of a given origin can subscribe to. It allows communication between different documents (in different windows, tabs, frames, or iframes) of the same origin.
///
/// Messages are broadcasted via a message event fired at all BroadcastChannel objects listening to the channel.
///
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::use_broadcast_channel; /// # use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
/// # use leptos_use::utils::FromToStringCodec;
/// # /// #
/// # #[component] /// # #[component]
/// # fn Demo() -> impl IntoView { /// # fn Demo() -> impl IntoView {
/// use_broadcast_channel(); /// let UseBroadcastChannelReturn {
/// is_supported,
/// message,
/// post,
/// error,
/// close,
/// ..
/// } = use_broadcast_channel::<bool, FromToStringCodec>("some-channel-name");
///
/// post(&true);
///
/// close();
/// # /// #
/// # view! { } /// # view! { }
/// # } /// # }
/// ``` /// ```
pub fn use_broadcast_channel<T, C>(name: &str) -> UseBroadcastChannelReturn ///
/// Just like with [`use_storage`] you can use different codecs for encoding and decoding.
///
/// ```
/// # use leptos::*;
/// # use serde::{Deserialize, Serialize};
/// # use leptos_use::use_broadcast_channel;
/// # use leptos_use::utils::JsonCodec;
/// #
/// // Data sent in JSON must implement Serialize, Deserialize:
/// #[derive(Serialize, Deserialize, Clone, PartialEq)]
/// pub struct MyState {
/// pub playing_lego: bool,
/// pub everything_is_awesome: String,
/// }
///
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// use_broadcast_channel::<MyState, JsonCodec>("everyting-is-awesome");
/// # view! { }
/// # }
/// ```
pub fn use_broadcast_channel<T, C>(
name: &str,
) -> UseBroadcastChannelReturn<T, impl Fn(&T) + Clone, impl Fn() + Clone, C::Error>
where where
C: Codec<T> + Default + Clone, C: StringCodec<T> + Default + Clone,
{ {
let is_supported = use_supported(|| JsValue::from("BroadcastChannel").js_in(&window())); let is_supported = use_supported(|| JsValue::from("BroadcastChannel").js_in(&window()));
let (is_closed, set_closed) = create_signal(false); let (is_closed, set_closed) = create_signal(false);
let (channel, set_channel) = create_signal(None::<web_sys::BroadcastChannel>); let (channel, set_channel) = create_signal(None::<web_sys::BroadcastChannel>);
let (message, set_message) = create_signal(None::<T>); let (message, set_message) = create_signal(None::<T>);
let (error, set_error) = create_signal(None::<web_sys::MessageEvent>); let (error, set_error) = create_signal(None::<UseBroadcastChannelError<C::Error>>);
let post = move |data: T| { let codec = C::default();
if let Some(channel) = channel.get_untracked() {
channel.post_message().ok(); let post = {
let codec = codec.clone();
move |data: &T| {
if let Some(channel) = channel.get_untracked() {
match codec.encode(data) {
Ok(msg) => {
channel
.post_message(&msg.into())
.map_err(|err| {
set_error.set(Some(UseBroadcastChannelError::PostMessage(err)))
})
.ok();
}
Err(err) => {
set_error.set(Some(UseBroadcastChannelError::Encode(err)));
}
}
}
} }
}; };
let close = {
let channel = channel.clone();
move || {
if let Some(channel) = channel.get_untracked() {
channel.close();
}
set_closed.set(true);
}
};
if is_supported.get_untracked() {
let channel_val = web_sys::BroadcastChannel::new(name).ok();
set_channel.set(channel_val.clone());
if let Some(channel) = channel_val {
let _ = use_event_listener_with_options(
channel.clone(),
ev::message,
move |event| {
if let Some(data) = event.data().as_string() {
match codec.decode(data) {
Ok(msg) => {
set_message.set(Some(msg));
}
Err(err) => set_error.set(Some(UseBroadcastChannelError::Decode(err))),
}
} else {
set_error.set(Some(UseBroadcastChannelError::ValueNotString));
}
},
UseEventListenerOptions::default().passive(true),
);
let _ = use_event_listener_with_options(
channel.clone(),
ev::messageerror,
move |event| {
set_error.set(Some(UseBroadcastChannelError::MessageEvent(event)));
},
UseEventListenerOptions::default().passive(true),
);
let _ = use_event_listener(channel, ev::close, move |_| set_closed.set(true));
}
}
on_cleanup(move || {
close();
});
return UseBroadcastChannelReturn {
is_supported,
channel: channel.into(),
message: message.into(),
post,
close,
error: error.into(),
is_closed: is_closed.into(),
};
} }
/// Return type of [`use_broadcast_channel`]. /// Return type of [`use_broadcast_channel`].
pub struct UseBroadcastChannelReturn<T, PFn, CFn> pub struct UseBroadcastChannelReturn<T, PFn, CFn, Err>
where where
PFn: Fn(T), T: 'static,
CFn: Fn(), PFn: Fn(&T) + Clone,
CFn: Fn() + Clone,
Err: 'static,
{ {
/// `true` if this browser supports `BroadcastChannel`s. /// `true` if this browser supports `BroadcastChannel`s.
is_supported: Signal<bool>, pub is_supported: Signal<bool>,
/// The broadcast channel that is wrapped by this function /// The broadcast channel that is wrapped by this function
channel: Signal<Option<web_sys::BroadcastChannel>>, pub channel: Signal<Option<web_sys::BroadcastChannel>>,
/// Latest message received from the channel /// Latest message received from the channel
message: Signal<Option<T>>, pub message: Signal<Option<T>>,
/// Sends a message through the channel /// Sends a message through the channel
post: PFn, pub post: PFn,
/// Closes the channel /// Closes the channel
close: CFn, pub close: CFn,
/// Latest error as reported by the `messageerror` event. /// Latest error as reported by the `messageerror` event.
error: Signal<Option<web_sys::MessageEvent>>, pub error: Signal<Option<UseBroadcastChannelError<Err>>>,
/// Wether the channel is closed /// Wether the channel is closed
is_closed: Signal<bool>, pub is_closed: Signal<bool>,
}
#[derive(Debug, Error, Clone)]
pub enum UseBroadcastChannelError<Err> {
#[error("failed to post message")]
PostMessage(JsValue),
#[error("channel message error")]
MessageEvent(web_sys::MessageEvent),
#[error("failed to encode value")]
Encode(Err),
#[error("failed to decode value")]
Decode(Err),
#[error("received value is not a string")]
ValueNotString,
} }

View file

@ -1,14 +1,14 @@
use crate::core::{ElementMaybeSignal, MaybeRwSignal};
use crate::storage::{use_storage_with_options, StringCodec, UseStorageOptions};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
use crate::core::StorageType; use crate::core::StorageType;
use crate::core::{ElementMaybeSignal, MaybeRwSignal};
use crate::storage::{use_storage_with_options, UseStorageOptions};
use crate::use_preferred_dark; use crate::use_preferred_dark;
use crate::utils::FromToStringCodec;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::*; use leptos::*;
use std::fmt::{Display, Formatter};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
/// Reactive color mode (dark / light / customs) with auto data persistence. /// Reactive color mode (dark / light / customs) with auto data persistence.
@ -261,7 +261,7 @@ fn get_store_signal(
let (store, set_store) = storage_signal.split(); let (store, set_store) = storage_signal.split();
(store.into(), set_store) (store.into(), set_store)
} else if storage_enabled { } else if storage_enabled {
let (store, set_store, _) = use_storage_with_options::<ColorMode, StringCodec>( let (store, set_store, _) = use_storage_with_options::<ColorMode, FromToStringCodec>(
storage, storage,
storage_key, storage_key,
UseStorageOptions::default() UseStorageOptions::default()

View file

@ -1,6 +1,5 @@
use cookie::Cookie; use cookie::Cookie;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use std::rc::Rc;
/// Get a cookie by name, for both SSR and CSR /// Get a cookie by name, for both SSR and CSR
/// ///
@ -75,7 +74,7 @@ pub fn use_cookie_with_options(
ssr_cookies_header_getter, ssr_cookies_header_getter,
} = options; } = options;
let cookie = read_cookies_string(ssr_cookies_header_getter); let cookies = read_cookies_string(ssr_cookies_header_getter);
Cookie::split_parse_encoded(cookies) Cookie::split_parse_encoded(cookies)
.filter_map(|cookie| cookie.ok()) .filter_map(|cookie| cookie.ok())
@ -84,7 +83,7 @@ pub fn use_cookie_with_options(
} }
/// Options for [`use_cookie_with_options`]. /// Options for [`use_cookie_with_options`].
#[derive(Clone, DefaultBuilder)] #[derive(DefaultBuilder)]
pub struct UseCookieOptions { pub struct UseCookieOptions {
/// 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.
@ -148,15 +147,23 @@ impl Default for UseCookieOptions {
} }
fn read_cookies_string(ssr_cookies_header_getter: Box<dyn Fn() -> String>) -> String { fn read_cookies_string(ssr_cookies_header_getter: Box<dyn Fn() -> String>) -> String {
let cookies;
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
ssr_cookies_header_getter(); {
cookies = ssr_cookies_header_getter();
}
#[cfg(not(feature = "ssr"))] #[cfg(not(feature = "ssr"))]
{ {
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
let _ = ssr_cookies_header_getter;
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();
document.cookie().unwrap_or_default() cookies = document.cookie().unwrap_or_default();
} }
cookies
} }

View file

@ -18,9 +18,9 @@ use web_sys::PointerEvent;
/// ///
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// use leptos::html::Div; /// # use leptos::html::Div;
/// # use leptos_use::{use_draggable_with_options, UseDraggableOptions, UseDraggableReturn}; /// # use leptos_use::{use_draggable_with_options, UseDraggableOptions, UseDraggableReturn};
/// use leptos_use::core::Position; /// # use leptos_use::core::Position;
/// # /// #
/// # #[component] /// # #[component]
/// # fn Demo() -> impl IntoView { /// # fn Demo() -> impl IntoView {

View file

@ -1,9 +1,10 @@
use super::BinCodec; use super::BinCodec;
use thiserror::Error;
#[derive(Copy, Clone, Default, PartialEq)] #[derive(Copy, Clone, Default, PartialEq)]
pub struct FromToBytesCodec; pub struct FromToBytesCodec;
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug)]
pub enum FromToBytesCodecError { pub enum FromToBytesCodecError {
#[error("failed to convert byte slice to byte array")] #[error("failed to convert byte slice to byte array")]
InvalidByteSlice(#[from] std::array::TryFromSliceError), InvalidByteSlice(#[from] std::array::TryFromSliceError),

View file

@ -1,5 +1,6 @@
mod from_to_bytes; mod from_to_bytes;
#[allow(unused_imports)]
pub use from_to_bytes::*; pub use from_to_bytes::*;
/// A codec for encoding and decoding values to and from strings. /// A codec for encoding and decoding values to and from strings.

View file

@ -8,10 +8,11 @@ use std::str::FromStr;
/// ## Example /// ## Example
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions, StringCodec}; /// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
/// # use leptos_use::utils::FromToStringCodec;
/// # /// #
/// # pub fn Demo() -> impl IntoView { /// # pub fn Demo() -> impl IntoView {
/// let (get, set, remove) = use_local_storage::<i32, StringCodec>("my-key"); /// let (get, set, remove) = use_local_storage::<i32, FromToStringCodec>("my-key");
/// # view! { } /// # view! { }
/// # } /// # }
/// ``` /// ```

View file

@ -5,8 +5,9 @@ use super::StringCodec;
/// ## Example /// ## Example
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions, JsonCodec}; /// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
/// # use serde::{Deserialize, Serialize}; /// # use serde::{Deserialize, Serialize};
/// # use leptos_use::utils::JsonCodec;
/// # /// #
/// # pub fn Demo() -> impl IntoView { /// # pub fn Demo() -> impl IntoView {
/// // Primitive types: /// // Primitive types:
@ -34,8 +35,9 @@ use super::StringCodec;
/// ///
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions, Codec, JsonCodec}; /// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
/// # use serde::{Deserialize, Serialize}; /// # use serde::{Deserialize, Serialize};
/// # use leptos_use::utils::StringCodec;
/// # /// #
/// # pub fn Demo() -> impl IntoView { /// # pub fn Demo() -> impl IntoView {
/// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)] /// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
@ -46,7 +48,7 @@ use super::StringCodec;
/// ///
/// #[derive(Clone, Default)] /// #[derive(Clone, Default)]
/// pub struct MyStateCodec(); /// pub struct MyStateCodec();
/// impl Codec<MyState> for MyStateCodec { /// impl StringCodec<MyState> for MyStateCodec {
/// type Error = serde_json::Error; /// type Error = serde_json::Error;
/// ///
/// fn encode(&self, val: &MyState) -> Result<String, Self::Error> { /// fn encode(&self, val: &MyState) -> Result<String, Self::Error> {
@ -75,9 +77,10 @@ use super::StringCodec;
/// ///
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions, Codec, JsonCodec}; /// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
/// # use serde::{Deserialize, Serialize}; /// # use serde::{Deserialize, Serialize};
/// # use serde_json::json; /// # use serde_json::json;
/// # use leptos_use::utils::StringCodec;
/// # /// #
/// # pub fn Demo() -> impl IntoView { /// # pub fn Demo() -> impl IntoView {
/// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)] /// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
@ -88,7 +91,7 @@ use super::StringCodec;
/// ///
/// #[derive(Clone, Default)] /// #[derive(Clone, Default)]
/// pub struct MyStateCodec(); /// pub struct MyStateCodec();
/// impl Codec<MyState> for MyStateCodec { /// impl StringCodec<MyState> for MyStateCodec {
/// type Error = serde_json::Error; /// type Error = serde_json::Error;
/// ///
/// fn encode(&self, val: &MyState) -> Result<String, Self::Error> { /// fn encode(&self, val: &MyState) -> Result<String, Self::Error> {

View file

@ -11,7 +11,8 @@ use thiserror::Error;
/// ## Example /// ## Example
/// ``` /// ```
/// # use leptos::*; /// # use leptos::*;
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions, ProstCodec}; /// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
/// # use leptos_use::utils::ProstCodec;
/// # /// #
/// # pub fn Demo() -> impl IntoView { /// # pub fn Demo() -> impl IntoView {
/// // Primitive types: /// // Primitive types:

View file

@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
leptos = { version = "0.5", features = ["nightly", "csr"] } leptos = { version = "0.6", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1" console_error_panic_hook = "0.1"
console_log = "1" console_log = "1"
log = "0.4" log = "0.4"