mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-22 16:49:22 -05:00
added use_broadcast_channel
This commit is contained in:
parent
0d546d464a
commit
7fe153e525
21 changed files with 282 additions and 78 deletions
7
.idea/leptos-use.iml
generated
7
.idea/leptos-use.iml
generated
|
@ -63,6 +63,11 @@
|
|||
<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/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$/target" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/docs/book/book" />
|
||||
|
@ -133,4 +138,4 @@
|
|||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Python 3.9 interpreter library" level="application" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
|
@ -61,7 +61,7 @@
|
|||
# Network
|
||||
|
||||
- [use_websocket](network/use_websocket.md)
|
||||
- [use_webtransport](network/use_webtransport.md)
|
||||
<!-- - [use_webtransport](network/use_webtransport.md) -->
|
||||
|
||||
# Animation
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { version = "0.5", features = ["nightly", "csr"] }
|
||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
|
|
|
@ -1,13 +1,56 @@
|
|||
use leptos::*;
|
||||
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]
|
||||
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() {
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { version = "0.5.0-beta2", features = ["nightly", "csr"] }
|
||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { version = "0.5.0-rc1", features = ["nightly", "csr"] }
|
||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -9,21 +9,21 @@ pub mod math;
|
|||
pub mod storage;
|
||||
pub mod utils;
|
||||
|
||||
cfg_if! { if #[cfg(web_sys_unstable_apis)] {
|
||||
mod use_webtransport;
|
||||
pub use use_webtransport::*;
|
||||
}}
|
||||
#[cfg(web_sys_unstable_apis)]
|
||||
mod use_webtransport;
|
||||
#[cfg(web_sys_unstable_apis)]
|
||||
pub use use_webtransport::*;
|
||||
|
||||
mod is_err;
|
||||
mod is_none;
|
||||
mod is_ok;
|
||||
mod is_some;
|
||||
mod on_click_outside;
|
||||
mod use_broadcast_channel;
|
||||
mod signal_debounced;
|
||||
mod signal_throttled;
|
||||
mod use_active_element;
|
||||
mod use_breakpoints;
|
||||
mod use_broadcast_channel;
|
||||
mod use_color_mode;
|
||||
mod use_cookie;
|
||||
mod use_css_var;
|
||||
|
@ -79,11 +79,11 @@ pub use is_none::*;
|
|||
pub use is_ok::*;
|
||||
pub use is_some::*;
|
||||
pub use on_click_outside::*;
|
||||
pub use use_broadcast_channel::*;
|
||||
pub use signal_debounced::*;
|
||||
pub use signal_throttled::*;
|
||||
pub use use_active_element::*;
|
||||
pub use use_breakpoints::*;
|
||||
pub use use_broadcast_channel::*;
|
||||
pub use use_color_mode::*;
|
||||
pub use use_cookie::*;
|
||||
pub use use_css_var::*;
|
||||
|
@ -125,7 +125,6 @@ pub use use_timestamp::*;
|
|||
pub use use_to_string::*;
|
||||
pub use use_web_notification::*;
|
||||
pub use use_websocket::*;
|
||||
pub use use_webtransport::*;
|
||||
pub use use_window::*;
|
||||
pub use use_window_focus::*;
|
||||
pub use use_window_scroll::*;
|
||||
|
|
|
@ -3,11 +3,6 @@ mod use_session_storage;
|
|||
mod use_storage;
|
||||
|
||||
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_session_storage::*;
|
||||
pub use use_storage::*;
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
/// 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)
|
||||
where
|
||||
T: Clone + Default + PartialEq,
|
||||
C: Codec<T> + Default,
|
||||
C: StringCodec<T> + Default,
|
||||
{
|
||||
use_storage_with_options(
|
||||
StorageType::Local,
|
||||
|
@ -30,7 +31,7 @@ pub fn use_local_storage_with_options<T, C>(
|
|||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
T: Clone + PartialEq,
|
||||
C: Codec<T>,
|
||||
C: StringCodec<T>,
|
||||
{
|
||||
use_storage_with_options(StorageType::Local, key, options)
|
||||
}
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
/// 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)
|
||||
where
|
||||
T: Clone + Default + PartialEq,
|
||||
C: Codec<T> + Default,
|
||||
C: StringCodec<T> + Default,
|
||||
{
|
||||
use_storage_with_options(
|
||||
StorageType::Session,
|
||||
|
@ -30,7 +31,7 @@ pub fn use_session_storage_with_options<T, C>(
|
|||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
T: Clone + PartialEq,
|
||||
C: Codec<T>,
|
||||
C: StringCodec<T>,
|
||||
{
|
||||
use_storage_with_options(StorageType::Session, key, options)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::utils::FromToStringCodec;
|
||||
use crate::{
|
||||
core::{MaybeRwSignal, StorageType},
|
||||
utils::{FilterOptions, StringCodec},
|
||||
|
@ -28,18 +29,19 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
|
|||
///
|
||||
/// ```
|
||||
/// # 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 leptos_use::utils::{FromToStringCodec, JsonCodec, ProstCodec};
|
||||
/// #
|
||||
/// # pub fn Demo() -> impl IntoView {
|
||||
/// // Binds a struct:
|
||||
/// let (state, set_state, _) = use_local_storage::<MyState, JsonCodec>("my-state");
|
||||
///
|
||||
/// // 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:
|
||||
/// 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:
|
||||
/// 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,
|
||||
key: impl AsRef<str>,
|
||||
) -> (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`].
|
||||
|
@ -100,7 +106,7 @@ pub fn use_storage_with_options<T, C>(
|
|||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
T: Clone + PartialEq,
|
||||
C: Codec<T>,
|
||||
C: StringCodec<T>,
|
||||
{
|
||||
let UseStorageOptions {
|
||||
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`].
|
||||
pub struct UseStorageOptions<T: 'static, C: Codec<T>> {
|
||||
pub struct UseStorageOptions<T: 'static, C: StringCodec<T>> {
|
||||
// Translates to and from UTF-16 strings
|
||||
codec: C,
|
||||
// Callback for when an error occurs
|
||||
|
@ -344,7 +350,7 @@ fn handle_error<T, 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 {
|
||||
Self {
|
||||
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.
|
||||
pub fn codec(self, codec: impl Into<C>) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
use crate::storage::Codec;
|
||||
use crate::use_supported;
|
||||
use default_struct_builder::DefaultBuilder;
|
||||
use crate::utils::StringCodec;
|
||||
use crate::{
|
||||
use_event_listener, use_event_listener_with_options, use_supported, UseEventListenerOptions,
|
||||
};
|
||||
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
|
||||
///
|
||||
|
@ -11,59 +16,194 @@ use leptos::*;
|
|||
///
|
||||
/// ## 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::use_broadcast_channel;
|
||||
/// # use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
|
||||
/// # use leptos_use::utils::FromToStringCodec;
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # 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! { }
|
||||
/// # }
|
||||
/// ```
|
||||
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
|
||||
C: Codec<T> + Default + Clone,
|
||||
C: StringCodec<T> + Default + Clone,
|
||||
{
|
||||
let is_supported = use_supported(|| JsValue::from("BroadcastChannel").js_in(&window()));
|
||||
|
||||
let (is_closed, set_closed) = create_signal(false);
|
||||
let (channel, set_channel) = create_signal(None::<web_sys::BroadcastChannel>);
|
||||
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| {
|
||||
if let Some(channel) = channel.get_untracked() {
|
||||
channel.post_message().ok();
|
||||
let codec = C::default();
|
||||
|
||||
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`].
|
||||
pub struct UseBroadcastChannelReturn<T, PFn, CFn>
|
||||
pub struct UseBroadcastChannelReturn<T, PFn, CFn, Err>
|
||||
where
|
||||
PFn: Fn(T),
|
||||
CFn: Fn(),
|
||||
T: 'static,
|
||||
PFn: Fn(&T) + Clone,
|
||||
CFn: Fn() + Clone,
|
||||
Err: 'static,
|
||||
{
|
||||
/// `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
|
||||
channel: Signal<Option<web_sys::BroadcastChannel>>,
|
||||
pub channel: Signal<Option<web_sys::BroadcastChannel>>,
|
||||
|
||||
/// Latest message received from the channel
|
||||
message: Signal<Option<T>>,
|
||||
pub message: Signal<Option<T>>,
|
||||
|
||||
/// Sends a message through the channel
|
||||
post: PFn,
|
||||
pub post: PFn,
|
||||
|
||||
/// Closes the channel
|
||||
close: CFn,
|
||||
pub close: CFn,
|
||||
|
||||
/// 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
|
||||
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,
|
||||
}
|
||||
|
|
|
@ -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::{ElementMaybeSignal, MaybeRwSignal};
|
||||
use crate::storage::{use_storage_with_options, UseStorageOptions};
|
||||
use crate::use_preferred_dark;
|
||||
use crate::utils::FromToStringCodec;
|
||||
use default_struct_builder::DefaultBuilder;
|
||||
use leptos::*;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// 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();
|
||||
(store.into(), set_store)
|
||||
} 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_key,
|
||||
UseStorageOptions::default()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use cookie::Cookie;
|
||||
use default_struct_builder::DefaultBuilder;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Get a cookie by name, for both SSR and CSR
|
||||
///
|
||||
|
@ -75,7 +74,7 @@ pub fn use_cookie_with_options(
|
|||
ssr_cookies_header_getter,
|
||||
} = options;
|
||||
|
||||
let cookie = read_cookies_string(ssr_cookies_header_getter);
|
||||
let cookies = read_cookies_string(ssr_cookies_header_getter);
|
||||
|
||||
Cookie::split_parse_encoded(cookies)
|
||||
.filter_map(|cookie| cookie.ok())
|
||||
|
@ -84,7 +83,7 @@ pub fn use_cookie_with_options(
|
|||
}
|
||||
|
||||
/// Options for [`use_cookie_with_options`].
|
||||
#[derive(Clone, DefaultBuilder)]
|
||||
#[derive(DefaultBuilder)]
|
||||
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.
|
||||
|
@ -148,15 +147,23 @@ impl Default for UseCookieOptions {
|
|||
}
|
||||
|
||||
fn read_cookies_string(ssr_cookies_header_getter: Box<dyn Fn() -> String>) -> String {
|
||||
let cookies;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
ssr_cookies_header_getter();
|
||||
{
|
||||
cookies = ssr_cookies_header_getter();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
{
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
let _ = ssr_cookies_header_getter;
|
||||
|
||||
let js_value: wasm_bindgen::JsValue = leptos::document().into();
|
||||
let document: web_sys::HtmlDocument = js_value.unchecked_into();
|
||||
document.cookie().unwrap_or_default()
|
||||
cookies = document.cookie().unwrap_or_default();
|
||||
}
|
||||
|
||||
cookies
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ use web_sys::PointerEvent;
|
|||
///
|
||||
/// ```
|
||||
/// # use leptos::*;
|
||||
/// use leptos::html::Div;
|
||||
/// # use leptos::html::Div;
|
||||
/// # use leptos_use::{use_draggable_with_options, UseDraggableOptions, UseDraggableReturn};
|
||||
/// use leptos_use::core::Position;
|
||||
/// # use leptos_use::core::Position;
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # fn Demo() -> impl IntoView {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use super::BinCodec;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Copy, Clone, Default, PartialEq)]
|
||||
pub struct FromToBytesCodec;
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum FromToBytesCodecError {
|
||||
#[error("failed to convert byte slice to byte array")]
|
||||
InvalidByteSlice(#[from] std::array::TryFromSliceError),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod from_to_bytes;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub use from_to_bytes::*;
|
||||
|
||||
/// A codec for encoding and decoding values to and from strings.
|
||||
|
|
|
@ -8,10 +8,11 @@ use std::str::FromStr;
|
|||
/// ## Example
|
||||
/// ```
|
||||
/// # 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 {
|
||||
/// let (get, set, remove) = use_local_storage::<i32, StringCodec>("my-key");
|
||||
/// let (get, set, remove) = use_local_storage::<i32, FromToStringCodec>("my-key");
|
||||
/// # view! { }
|
||||
/// # }
|
||||
/// ```
|
||||
|
|
|
@ -5,8 +5,9 @@ use super::StringCodec;
|
|||
/// ## Example
|
||||
/// ```
|
||||
/// # 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 leptos_use::utils::JsonCodec;
|
||||
/// #
|
||||
/// # pub fn Demo() -> impl IntoView {
|
||||
/// // Primitive types:
|
||||
|
@ -34,8 +35,9 @@ use super::StringCodec;
|
|||
///
|
||||
/// ```
|
||||
/// # 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 leptos_use::utils::StringCodec;
|
||||
/// #
|
||||
/// # pub fn Demo() -> impl IntoView {
|
||||
/// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
|
||||
|
@ -46,7 +48,7 @@ use super::StringCodec;
|
|||
///
|
||||
/// #[derive(Clone, Default)]
|
||||
/// pub struct MyStateCodec();
|
||||
/// impl Codec<MyState> for MyStateCodec {
|
||||
/// impl StringCodec<MyState> for MyStateCodec {
|
||||
/// type Error = serde_json::Error;
|
||||
///
|
||||
/// fn encode(&self, val: &MyState) -> Result<String, Self::Error> {
|
||||
|
@ -75,9 +77,10 @@ use super::StringCodec;
|
|||
///
|
||||
/// ```
|
||||
/// # 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_json::json;
|
||||
/// # use leptos_use::utils::StringCodec;
|
||||
/// #
|
||||
/// # pub fn Demo() -> impl IntoView {
|
||||
/// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
|
||||
|
@ -88,7 +91,7 @@ use super::StringCodec;
|
|||
///
|
||||
/// #[derive(Clone, Default)]
|
||||
/// pub struct MyStateCodec();
|
||||
/// impl Codec<MyState> for MyStateCodec {
|
||||
/// impl StringCodec<MyState> for MyStateCodec {
|
||||
/// type Error = serde_json::Error;
|
||||
///
|
||||
/// fn encode(&self, val: &MyState) -> Result<String, Self::Error> {
|
||||
|
|
|
@ -11,7 +11,8 @@ use thiserror::Error;
|
|||
/// ## Example
|
||||
/// ```
|
||||
/// # 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 {
|
||||
/// // Primitive types:
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { version = "0.5", features = ["nightly", "csr"] }
|
||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
|
|
Loading…
Add table
Reference in a new issue