mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-23 00:59: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
5
.idea/leptos-use.iml
generated
5
.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_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" />
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -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::*;
|
||||||
|
|
|
@ -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::*;
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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! { }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Add table
Reference in a new issue