Removed all trivial SendWrappers

This commit is contained in:
CorvusPrudens 2024-08-03 23:28:09 -06:00
parent c414022b23
commit feb585362e
33 changed files with 488 additions and 405 deletions

View file

@ -18,8 +18,8 @@ pub enum ElementMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
Static(Option<SendWrapper<T>>), Static(SendWrapper<Option<T>>),
Dynamic(Signal<Option<SendWrapper<T>>>), Dynamic(Signal<Option<T>, LocalStorage>),
_Phantom(PhantomData<fn() -> E>), _Phantom(PhantomData<fn() -> E>),
} }
@ -28,7 +28,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn default() -> Self { fn default() -> Self {
Self::Static(None) Self::Static(SendWrapper::new(None))
} }
} }
@ -62,28 +62,19 @@ where
fn with<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> O { fn with<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> O {
match self { match self {
Self::Static(t) => { Self::Static(t) => f(&t),
let value = t.as_ref().map(|t| t.clone().take()); Self::Dynamic(s) => {
let value = s.get();
f(&value) f(&value)
} }
Self::Dynamic(s) => s.with(|s| {
let value = s.as_ref().map(|s| s.clone().take());
f(&value)
}),
_ => unreachable!(), _ => unreachable!(),
} }
} }
fn try_with<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> Option<O> { fn try_with<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> Option<O> {
match self { match self {
Self::Static(t) => { Self::Static(t) => Some(f(&t)),
let value = t.as_ref().map(|t| t.clone().take()); Self::Dynamic(s) => s.try_with(f),
Some(f(&value))
}
Self::Dynamic(s) => s.try_with(|s| {
let value = s.as_ref().map(|s| s.clone().take());
f(&value)
}),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -97,28 +88,16 @@ where
fn with_untracked<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> O { fn with_untracked<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> O {
match self { match self {
Self::Static(t) => { Self::Static(t) => f(&t),
let value = t.as_ref().map(|t| t.clone().take()); Self::Dynamic(s) => s.with_untracked(f),
f(&value)
}
Self::Dynamic(s) => s.with_untracked(|s| {
let value = s.as_ref().map(|s| s.clone().take());
f(&value)
}),
_ => unreachable!(), _ => unreachable!(),
} }
} }
fn try_with_untracked<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> Option<O> { fn try_with_untracked<O>(&self, f: impl FnOnce(&Option<T>) -> O) -> Option<O> {
match self { match self {
Self::Static(t) => { Self::Static(t) => Some(f(&t)),
let value = t.as_ref().map(|t| t.clone().take()); Self::Dynamic(s) => s.try_with_untracked(f),
Some(f(&value))
}
Self::Dynamic(s) => s.try_with_untracked(|s| {
let value = s.as_ref().map(|s| s.clone().take());
f(&value)
}),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -131,7 +110,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(value: T) -> Self { fn from(value: T) -> Self {
ElementMaybeSignal::Static(Some(SendWrapper::new(value))) ElementMaybeSignal::Static(SendWrapper::new(Some(value)))
} }
} }
@ -140,7 +119,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: Option<T>) -> Self { fn from(target: Option<T>) -> Self {
ElementMaybeSignal::Static(target.map(SendWrapper::new)) ElementMaybeSignal::Static(SendWrapper::new(target))
} }
} }
@ -151,7 +130,7 @@ macro_rules! impl_from_deref_option {
E: From<$ty2> + 'static, E: From<$ty2> + 'static,
{ {
fn from(value: $ty) -> Self { fn from(value: $ty) -> Self {
Self::Static((*value).clone().map(SendWrapper::new)) Self::Static(SendWrapper::new((*value).clone()))
} }
} }
}; };
@ -169,9 +148,9 @@ where
fn from(target: &'a str) -> Self { fn from(target: &'a str) -> Self {
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
let _ = target; let _ = target;
Self::Static(None) Self::Static(SendWrapper::new(None))
} else { } else {
Self::Static(document().query_selector(target).unwrap_or_default().map(SendWrapper::new)) Self::Static(SendWrapper::new(document().query_selector(target).unwrap_or_default()))
}} }}
} }
} }
@ -194,10 +173,10 @@ macro_rules! impl_from_signal_string {
fn from(signal: $ty) -> Self { fn from(signal: $ty) -> Self {
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
let _ = signal; let _ = signal;
Self::Dynamic(Signal::derive(|| None)) Self::Dynamic(Signal::derive_local(|| None))
} else { } else {
Self::Dynamic( Self::Dynamic(
Signal::derive(move || document().query_selector(&signal.get()).unwrap_or_default().map(SendWrapper::new)), Signal::derive_local(move || document().query_selector(&signal.get()).unwrap_or_default()),
) )
}} }}
} }
@ -210,8 +189,8 @@ impl_from_signal_string!(ReadSignal<String>);
impl_from_signal_string!(RwSignal<String>); impl_from_signal_string!(RwSignal<String>);
impl_from_signal_string!(Memo<String>); impl_from_signal_string!(Memo<String>);
impl_from_signal_string!(Signal<&str>); impl_from_signal_string!(Signal<&'static str>);
impl_from_signal_string!(ReadSignal<&str>); impl_from_signal_string!(ReadSignal<&'static str>);
impl_from_signal_string!(RwSignal<&'static str>); impl_from_signal_string!(RwSignal<&'static str>);
impl_from_signal_string!(Memo<&'static str>); impl_from_signal_string!(Memo<&'static str>);
@ -230,10 +209,10 @@ macro_rules! impl_from_signal_option {
}; };
} }
impl_from_signal_option!(Signal<Option<SendWrapper<T>>>); impl_from_signal_option!(Signal<Option<T>, LocalStorage>);
impl_from_signal_option!(ReadSignal<Option<SendWrapper<T>>>); impl_from_signal_option!(ReadSignal<Option<T>, LocalStorage>);
impl_from_signal_option!(RwSignal<Option<SendWrapper<T>>>); impl_from_signal_option!(RwSignal<Option<T>, LocalStorage>);
impl_from_signal_option!(Memo<Option<SendWrapper<T>>>); impl_from_signal_option!(Memo<Option<T>, LocalStorage>);
macro_rules! impl_from_signal { macro_rules! impl_from_signal {
($ty:ty) => { ($ty:ty) => {
@ -242,16 +221,16 @@ macro_rules! impl_from_signal {
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(signal: $ty) -> Self { fn from(signal: $ty) -> Self {
Self::Dynamic(Signal::derive(move || Some(signal.get()))) Self::Dynamic(Signal::derive_local(move || Some(signal.get())))
} }
} }
}; };
} }
impl_from_signal!(Signal<SendWrapper<T>>); impl_from_signal!(Signal<T, LocalStorage>);
impl_from_signal!(ReadSignal<SendWrapper<T>>); impl_from_signal!(ReadSignal<T, LocalStorage>);
impl_from_signal!(RwSignal<SendWrapper<T>>); impl_from_signal!(RwSignal<T, LocalStorage>);
impl_from_signal!(Memo<SendWrapper<T>>); impl_from_signal!(Memo<T, LocalStorage>);
// From NodeRef ////////////////////////////////////////////////////////////// // From NodeRef //////////////////////////////////////////////////////////////
@ -263,10 +242,10 @@ macro_rules! impl_from_node_ref {
R::Output: JsCast + Into<$ty> + Clone + 'static, R::Output: JsCast + Into<$ty> + Clone + 'static,
{ {
fn from(node_ref: NodeRef<R>) -> Self { fn from(node_ref: NodeRef<R>) -> Self {
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
node_ref.get().map(move |el| { node_ref.get().map(move |el| {
let el: $ty = el.clone().into(); let el: $ty = el.clone().into();
SendWrapper::new(el) el
}) })
})) }))
} }

View file

@ -1,12 +1,11 @@
use crate::core::ElementMaybeSignal; use crate::core::ElementMaybeSignal;
use crate::{UseDocument, UseWindow}; use crate::{UseDocument, UseWindow};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use leptos::html::{ElementType, HtmlElement}; use leptos::html::ElementType;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper; use send_wrapper::SendWrapper;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::Deref;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
/// Used as an argument type to make it easily possible to pass either /// Used as an argument type to make it easily possible to pass either
@ -20,8 +19,8 @@ pub enum ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
Static(Vec<Option<SendWrapper<T>>>), Static(SendWrapper<Vec<Option<T>>>),
Dynamic(Signal<Vec<Option<SendWrapper<T>>>>), Dynamic(Signal<Vec<Option<T>>, LocalStorage>),
_Phantom(PhantomData<fn() -> E>), _Phantom(PhantomData<fn() -> E>),
} }
@ -30,7 +29,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn default() -> Self { fn default() -> Self {
Self::Static(vec![]) Self::Static(SendWrapper::new(vec![]))
} }
} }
@ -60,9 +59,9 @@ impl<T, E> With for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
type Value = Vec<Option<SendWrapper<T>>>; type Value = Vec<Option<T>>;
fn with<O>(&self, f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O) -> O { fn with<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> O {
match self { match self {
Self::Static(v) => f(v), Self::Static(v) => f(v),
Self::Dynamic(s) => s.with(f), Self::Dynamic(s) => s.with(f),
@ -70,7 +69,7 @@ where
} }
} }
fn try_with<O>(&self, f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O) -> Option<O> { fn try_with<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> Option<O> {
match self { match self {
Self::Static(v) => Some(f(v)), Self::Static(v) => Some(f(v)),
Self::Dynamic(s) => s.try_with(f), Self::Dynamic(s) => s.try_with(f),
@ -83,9 +82,9 @@ impl<T, E> WithUntracked for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
type Value = Vec<Option<SendWrapper<T>>>; type Value = Vec<Option<T>>;
fn with_untracked<O>(&self, f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O) -> O { fn with_untracked<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> O {
match self { match self {
Self::Static(t) => f(t), Self::Static(t) => f(t),
Self::Dynamic(s) => s.with_untracked(f), Self::Dynamic(s) => s.with_untracked(f),
@ -93,10 +92,7 @@ where
} }
} }
fn try_with_untracked<O>( fn try_with_untracked<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> Option<O> {
&self,
f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O,
) -> Option<O> {
match self { match self {
Self::Static(t) => Some(f(t)), Self::Static(t) => Some(f(t)),
Self::Dynamic(s) => s.try_with_untracked(f), Self::Dynamic(s) => s.try_with_untracked(f),
@ -112,7 +108,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(value: T) -> Self { fn from(value: T) -> Self {
ElementsMaybeSignal::Static(vec![Some(SendWrapper::new(value))]) ElementsMaybeSignal::Static(SendWrapper::new(vec![Some(value)]))
} }
} }
@ -121,7 +117,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: Option<T>) -> Self { fn from(target: Option<T>) -> Self {
ElementsMaybeSignal::Static(vec![target.map(SendWrapper::new)]) ElementsMaybeSignal::Static(SendWrapper::new(vec![target]))
} }
} }
@ -132,7 +128,7 @@ macro_rules! impl_from_deref_option {
E: From<$ty2> + 'static, E: From<$ty2> + 'static,
{ {
fn from(value: $ty) -> Self { fn from(value: $ty) -> Self {
Self::Static(vec![(*value).clone().map(SendWrapper::new)]) Self::Static(SendWrapper::new(vec![(*value).clone()]))
} }
} }
}; };
@ -150,18 +146,18 @@ where
fn from(target: &'a str) -> Self { fn from(target: &'a str) -> Self {
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
let _ = target; let _ = target;
Self::Static(vec![]) Self::Static(SendWrapper::new(vec![]))
} else { } else {
if let Ok(node_list) = document().query_selector_all(target) { if let Ok(node_list) = document().query_selector_all(target) {
let mut list = Vec::with_capacity(node_list.length() as usize); let mut list = Vec::with_capacity(node_list.length() as usize);
for i in 0..node_list.length() { for i in 0..node_list.length() {
let node = node_list.get(i).expect("checked the range"); let node = node_list.get(i).expect("checked the range");
list.push(Some(SendWrapper::new(node))); list.push(Some(node));
} }
Self::Static(list) Self::Static(SendWrapper::new(list))
} else { } else {
Self::Static(vec![]) Self::Static(SendWrapper::new(vec![]))
} }
}} }}
} }
@ -185,12 +181,12 @@ macro_rules! impl_from_signal_string {
fn from(signal: $ty) -> Self { fn from(signal: $ty) -> Self {
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
Self::Dynamic( Self::Dynamic(
Signal::derive(move || { Signal::derive_local(move || {
if let Ok(node_list) = document().query_selector_all(&signal.get()) { if let Ok(node_list) = document().query_selector_all(&signal.get()) {
let mut list = Vec::with_capacity(node_list.length() as usize); let mut list = Vec::with_capacity(node_list.length() as usize);
for i in 0..node_list.length() { for i in 0..node_list.length() {
let node = node_list.get(i).expect("checked the range"); let node = node_list.get(i).expect("checked the range");
list.push(Some(SendWrapper::new(node))); list.push(Some(node));
} }
list list
} else { } else {
@ -200,7 +196,7 @@ macro_rules! impl_from_signal_string {
) )
} else { } else {
let _ = signal; let _ = signal;
Self::Dynamic(Signal::derive(Vec::new)) Self::Dynamic(Signal::derive_local(Vec::new))
}} }}
} }
} }
@ -212,8 +208,8 @@ impl_from_signal_string!(ReadSignal<String>);
impl_from_signal_string!(RwSignal<String>); impl_from_signal_string!(RwSignal<String>);
impl_from_signal_string!(Memo<String>); impl_from_signal_string!(Memo<String>);
impl_from_signal_string!(Signal<&str>); impl_from_signal_string!(Signal<&'static str>);
impl_from_signal_string!(ReadSignal<&str>); impl_from_signal_string!(ReadSignal<&'static str>);
impl_from_signal_string!(RwSignal<&'static str>); impl_from_signal_string!(RwSignal<&'static str>);
impl_from_signal_string!(Memo<&'static str>); impl_from_signal_string!(Memo<&'static str>);
@ -226,16 +222,16 @@ macro_rules! impl_from_signal_option {
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(signal: $ty) -> Self { fn from(signal: $ty) -> Self {
Self::Dynamic(Signal::derive(move || vec![signal.get()])) Self::Dynamic(Signal::derive_local(move || vec![signal.get()]))
} }
} }
}; };
} }
impl_from_signal_option!(Signal<Option<SendWrapper<T>>>); impl_from_signal_option!(Signal<Option<T>, LocalStorage>);
impl_from_signal_option!(ReadSignal<Option<SendWrapper<T>>>); impl_from_signal_option!(ReadSignal<Option<T>, LocalStorage>);
impl_from_signal_option!(RwSignal<Option<SendWrapper<T>>>); impl_from_signal_option!(RwSignal<Option<T>, LocalStorage>);
impl_from_signal_option!(Memo<Option<SendWrapper<T>>>); impl_from_signal_option!(Memo<Option<T>, LocalStorage>);
macro_rules! impl_from_signal { macro_rules! impl_from_signal {
($ty:ty) => { ($ty:ty) => {
@ -244,16 +240,16 @@ macro_rules! impl_from_signal {
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(signal: $ty) -> Self { fn from(signal: $ty) -> Self {
Self::Dynamic(Signal::derive(move || vec![Some(signal.get())])) Self::Dynamic(Signal::derive_local(move || vec![Some(signal.get())]))
} }
} }
}; };
} }
impl_from_signal!(Signal<SendWrapper<T>>); impl_from_signal!(Signal<T, LocalStorage>);
impl_from_signal!(ReadSignal<SendWrapper<T>>); impl_from_signal!(ReadSignal<T, LocalStorage>);
impl_from_signal!(RwSignal<SendWrapper<T>>); impl_from_signal!(RwSignal<T, LocalStorage>);
impl_from_signal!(Memo<SendWrapper<T>>); impl_from_signal!(Memo<T, LocalStorage>);
// From single NodeRef ////////////////////////////////////////////////////////////// // From single NodeRef //////////////////////////////////////////////////////////////
@ -265,10 +261,10 @@ macro_rules! impl_from_node_ref {
R::Output: JsCast + Into<$ty> + Clone + 'static, R::Output: JsCast + Into<$ty> + Clone + 'static,
{ {
fn from(node_ref: NodeRef<R>) -> Self { fn from(node_ref: NodeRef<R>) -> Self {
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
vec![node_ref.get().map(move |el| { vec![node_ref.get().map(move |el| {
let el: $ty = el.clone().into(); let el: $ty = el.clone().into();
SendWrapper::new(el) el
})] })]
})) }))
} }
@ -306,12 +302,9 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: &[T]) -> Self { fn from(target: &[T]) -> Self {
Self::Static( Self::Static(SendWrapper::new(
target target.iter().map(|t| Some(t.clone())).collect(),
.iter() ))
.map(|t| Some(SendWrapper::new(t.clone())))
.collect(),
)
} }
} }
@ -320,12 +313,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: &[Option<T>]) -> Self { fn from(target: &[Option<T>]) -> Self {
Self::Static( Self::Static(SendWrapper::new(target.iter().map(|t| t.clone()).collect()))
target
.iter()
.map(|t| t.clone().map(SendWrapper::new))
.collect(),
)
} }
} }
@ -334,12 +322,9 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: Vec<T>) -> Self { fn from(target: Vec<T>) -> Self {
Self::Static( Self::Static(SendWrapper::new(
target target.iter().map(|t| Some(t.clone())).collect(),
.iter() ))
.map(|t| Some(SendWrapper::new(t.clone())))
.collect(),
)
} }
} }
@ -348,12 +333,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: Vec<Option<T>>) -> Self { fn from(target: Vec<Option<T>>) -> Self {
Self::Static( Self::Static(SendWrapper::new(target.into_iter().map(|t| t).collect()))
target
.into_iter()
.map(|t| t.map(SendWrapper::new))
.collect(),
)
} }
} }
@ -362,12 +342,9 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: [T; C]) -> Self { fn from(target: [T; C]) -> Self {
Self::Static( Self::Static(SendWrapper::new(
target target.into_iter().map(|t| Some(t)).collect(),
.into_iter() ))
.map(|t| Some(SendWrapper::new(t)))
.collect(),
)
} }
} }
@ -376,12 +353,7 @@ where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: [Option<T>; C]) -> Self { fn from(target: [Option<T>; C]) -> Self {
Self::Static( Self::Static(SendWrapper::new(target.into_iter().collect()))
target
.into_iter()
.map(|t| t.map(SendWrapper::new))
.collect(),
)
} }
} }
@ -390,30 +362,32 @@ where
macro_rules! impl_from_strings_inner { macro_rules! impl_from_strings_inner {
($el_ty:ty, $str_ty:ty, $target:ident) => { ($el_ty:ty, $str_ty:ty, $target:ident) => {
Self::Static( Self::Static(
$target SendWrapper::new(
.iter() $target
.filter_map(|sel: &$str_ty| -> Option<Vec<Option<SendWrapper<$el_ty>>>> { .iter()
cfg_if! { if #[cfg(feature = "ssr")] { .filter_map(|sel: &$str_ty| -> Option<Vec<Option<$el_ty>>> {
let _ = sel; cfg_if! { if #[cfg(feature = "ssr")] {
None let _ = sel;
} else {
use wasm_bindgen::JsCast;
if let Ok(node_list) = document().query_selector_all(sel) {
let mut list = Vec::with_capacity(node_list.length() as usize);
for i in 0..node_list.length() {
let node: $el_ty = node_list.get(i).expect("checked the range").unchecked_into();
list.push(Some(SendWrapper::new(node)));
}
Some(list)
} else {
None None
} } else {
}} use wasm_bindgen::JsCast;
})
.flatten() if let Ok(node_list) = document().query_selector_all(sel) {
.collect(), let mut list = Vec::with_capacity(node_list.length() as usize);
for i in 0..node_list.length() {
let node: $el_ty = node_list.get(i).expect("checked the range").unchecked_into();
list.push(Some(node));
}
Some(list)
} else {
None
}
}}
})
.flatten()
.collect(),
)
) )
}; };
} }
@ -452,101 +426,101 @@ impl_from_strings!(web_sys::EventTarget, String);
// From signal of vec //////////////////////////////////////////////////////////////// // From signal of vec ////////////////////////////////////////////////////////////////
impl<T, E> From<Signal<Vec<SendWrapper<T>>>> for ElementsMaybeSignal<T, E> impl<T, E> From<Signal<Vec<T>, LocalStorage>> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(signal: Signal<Vec<SendWrapper<T>>>) -> Self { fn from(signal: Signal<Vec<T>, LocalStorage>) -> Self {
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
signal.get().into_iter().map(|t| Some(t)).collect() signal.get().into_iter().map(|t| Some(t)).collect()
})) }))
} }
} }
impl<T, E> From<Signal<Vec<Option<SendWrapper<T>>>>> for ElementsMaybeSignal<T, E> impl<T, E> From<Signal<Vec<Option<T>>, LocalStorage>> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(target: Signal<Vec<Option<SendWrapper<T>>>>) -> Self { fn from(target: Signal<Vec<Option<T>>, LocalStorage>) -> Self {
Self::Dynamic(target) Self::Dynamic(target)
} }
} }
// From multiple signals ////////////////////////////////////////////////////////////// // From multiple signals //////////////////////////////////////////////////////////////
impl<T, E> From<&[Signal<SendWrapper<T>>]> for ElementsMaybeSignal<T, E> impl<T, E> From<&[Signal<T, LocalStorage>]> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(list: &[Signal<SendWrapper<T>>]) -> Self { fn from(list: &[Signal<T, LocalStorage>]) -> Self {
let list = list.to_vec(); let list = list.to_vec();
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
list.iter().map(|t| Some(t.get())).collect() list.iter().map(|t| Some(t.get())).collect()
})) }))
} }
} }
impl<T, E> From<&[Signal<Option<SendWrapper<T>>>]> for ElementsMaybeSignal<T, E> impl<T, E> From<&[Signal<Option<T>, LocalStorage>]> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(list: &[Signal<Option<SendWrapper<T>>>]) -> Self { fn from(list: &[Signal<Option<T>, LocalStorage>]) -> Self {
let list = list.to_vec(); let list = list.to_vec();
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
list.iter().map(|t| t.get()).collect() list.iter().map(|t| t.get()).collect()
})) }))
} }
} }
impl<T, E> From<Vec<Signal<SendWrapper<T>>>> for ElementsMaybeSignal<T, E> impl<T, E> From<Vec<Signal<T, LocalStorage>>> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(list: Vec<Signal<SendWrapper<T>>>) -> Self { fn from(list: Vec<Signal<T, LocalStorage>>) -> Self {
let list = list.clone(); let list = list.clone();
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
list.iter().map(|t| Some(t.get())).collect() list.iter().map(|t| Some(t.get())).collect()
})) }))
} }
} }
impl<T, E> From<Vec<Signal<Option<SendWrapper<T>>>>> for ElementsMaybeSignal<T, E> impl<T, E> From<Vec<Signal<Option<T>, LocalStorage>>> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(list: Vec<Signal<Option<SendWrapper<T>>>>) -> Self { fn from(list: Vec<Signal<Option<T>, LocalStorage>>) -> Self {
let list = list.clone(); let list = list.clone();
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
list.iter().map(|t| t.get()).collect() list.iter().map(|t| t.get()).collect()
})) }))
} }
} }
impl<T, E, const C: usize> From<[Signal<SendWrapper<T>>; C]> for ElementsMaybeSignal<T, E> impl<T, E, const C: usize> From<[Signal<T, LocalStorage>; C]> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(list: [Signal<SendWrapper<T>>; C]) -> Self { fn from(list: [Signal<T, LocalStorage>; C]) -> Self {
let list = list.to_vec(); let list = list.to_vec();
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
list.iter().map(|t| Some(t.get())).collect() list.iter().map(|t| Some(t.get())).collect()
})) }))
} }
} }
impl<T, E, const C: usize> From<[Signal<Option<SendWrapper<T>>>; C]> for ElementsMaybeSignal<T, E> impl<T, E, const C: usize> From<[Signal<Option<T>, LocalStorage>; C]> for ElementsMaybeSignal<T, E>
where where
T: Into<E> + Clone + 'static, T: Into<E> + Clone + 'static,
{ {
fn from(list: [Signal<Option<SendWrapper<T>>>; C]) -> Self { fn from(list: [Signal<Option<T>, LocalStorage>; C]) -> Self {
let list = list.to_vec(); let list = list.to_vec();
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
list.iter().map(|t| t.get()).collect() list.iter().map(|t| t.get()).collect()
})) }))
} }
@ -556,13 +530,13 @@ where
macro_rules! impl_from_multi_node_ref_inner { macro_rules! impl_from_multi_node_ref_inner {
($ty:ty, $node_refs:ident) => { ($ty:ty, $node_refs:ident) => {
Self::Dynamic(Signal::derive(move || { Self::Dynamic(Signal::derive_local(move || {
$node_refs $node_refs
.iter() .iter()
.map(|node_ref| { .map(|node_ref| {
node_ref.get().map(move |el| { node_ref.get().map(move |el| {
let el: $ty = el.clone().into(); let el: $ty = el.clone().into();
SendWrapper::new(el) el
}) })
}) })
.collect() .collect()
@ -685,9 +659,11 @@ where
fn from(signal: ElementMaybeSignal<T, E>) -> Self { fn from(signal: ElementMaybeSignal<T, E>) -> Self {
match signal { match signal {
ElementMaybeSignal::Dynamic(signal) => { ElementMaybeSignal::Dynamic(signal) => {
Self::Dynamic(Signal::derive(move || vec![signal.get()])) Self::Dynamic(Signal::derive_local(move || vec![signal.get()]))
}
ElementMaybeSignal::Static(el) => {
Self::Static(SendWrapper::new(vec![SendWrapper::take(el)]))
} }
ElementMaybeSignal::Static(el) => Self::Static(vec![el]),
ElementMaybeSignal::_Phantom(_) => unreachable!(), ElementMaybeSignal::_Phantom(_) => unreachable!(),
} }
} }

View file

@ -1,16 +1,20 @@
use leptos::prelude::*; use leptos::prelude::*;
use std::fmt::Debug; use std::fmt::Debug;
pub enum MaybeRwSignal<T> pub enum MaybeRwSignal<T, S = SyncStorage>
where where
T: 'static, T: 'static,
S: Storage<T>,
{ {
Static(T), Static(T),
DynamicRw(Signal<T>, WriteSignal<T>), DynamicRw(Signal<T, S>, WriteSignal<T, S>),
DynamicRead(Signal<T>), DynamicRead(Signal<T, S>),
} }
impl<T: Clone> Clone for MaybeRwSignal<T> { impl<T: Clone, S> Clone for MaybeRwSignal<T, S>
where
S: Storage<T>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
match self { match self {
Self::Static(t) => Self::Static(t.clone()), Self::Static(t) => Self::Static(t.clone()),
@ -20,21 +24,21 @@ impl<T: Clone> Clone for MaybeRwSignal<T> {
} }
} }
impl<T: Copy> Copy for MaybeRwSignal<T> {} impl<T: Copy, S> Copy for MaybeRwSignal<T, S> where S: Storage<T> {}
impl<T> From<T> for MaybeRwSignal<T> { impl<T: Default, S> Default for MaybeRwSignal<T, S>
fn from(t: T) -> Self { where
Self::Static(t) S: Storage<T>,
} {
}
impl<T: Default> Default for MaybeRwSignal<T> {
fn default() -> Self { fn default() -> Self {
Self::Static(T::default()) Self::Static(T::default())
} }
} }
impl<T: Debug> Debug for MaybeRwSignal<T> { impl<T: Debug, S> Debug for MaybeRwSignal<T, S>
where
S: Storage<T> + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::Static(t) => f.debug_tuple("Static").field(t).finish(), Self::Static(t) => f.debug_tuple("Static").field(t).finish(),
@ -44,12 +48,42 @@ impl<T: Debug> Debug for MaybeRwSignal<T> {
} }
} }
impl<T> From<Signal<T>> for MaybeRwSignal<T> { impl<T> From<T> for MaybeRwSignal<T, SyncStorage>
where
SyncStorage: Storage<T>,
{
fn from(t: T) -> Self {
Self::Static(t)
}
}
impl<T> FromLocal<T> for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(value: T) -> Self {
Self::Static(value)
}
}
impl<T> From<Signal<T>> for MaybeRwSignal<T>
where
SyncStorage: Storage<T>,
{
fn from(s: Signal<T>) -> Self { fn from(s: Signal<T>) -> Self {
Self::DynamicRead(s) Self::DynamicRead(s)
} }
} }
impl<T> FromLocal<Signal<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(s: Signal<T, LocalStorage>) -> Self {
Self::DynamicRead(s)
}
}
impl<T> From<ReadSignal<T>> for MaybeRwSignal<T> impl<T> From<ReadSignal<T>> for MaybeRwSignal<T>
where where
T: Send + Sync, T: Send + Sync,
@ -59,6 +93,15 @@ where
} }
} }
impl<T> FromLocal<ReadSignal<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(s: ReadSignal<T, LocalStorage>) -> Self {
Self::DynamicRead(s.into())
}
}
impl<T> From<Memo<T>> for MaybeRwSignal<T> impl<T> From<Memo<T>> for MaybeRwSignal<T>
where where
T: Send + Sync, T: Send + Sync,
@ -68,6 +111,15 @@ where
} }
} }
impl<T> FromLocal<Memo<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(s: Memo<T, LocalStorage>) -> Self {
Self::DynamicRead(s.into())
}
}
impl<T> From<RwSignal<T>> for MaybeRwSignal<T> impl<T> From<RwSignal<T>> for MaybeRwSignal<T>
where where
T: Send + Sync, T: Send + Sync,
@ -78,6 +130,16 @@ where
} }
} }
impl<T> FromLocal<RwSignal<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(s: RwSignal<T, LocalStorage>) -> Self {
let (r, w) = s.split();
Self::DynamicRw(r.into(), w)
}
}
impl<T> From<(ReadSignal<T>, WriteSignal<T>)> for MaybeRwSignal<T> impl<T> From<(ReadSignal<T>, WriteSignal<T>)> for MaybeRwSignal<T>
where where
T: Send + Sync, T: Send + Sync,
@ -87,18 +149,67 @@ where
} }
} }
impl<T> From<(Signal<T>, WriteSignal<T>)> for MaybeRwSignal<T> { impl<T> FromLocal<(ReadSignal<T, LocalStorage>, WriteSignal<T, LocalStorage>)>
for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(s: (ReadSignal<T, LocalStorage>, WriteSignal<T, LocalStorage>)) -> Self {
Self::DynamicRw(s.0.into(), s.1)
}
}
impl<T> From<(Signal<T>, WriteSignal<T>)> for MaybeRwSignal<T>
where
T: Send + Sync,
{
fn from(s: (Signal<T>, WriteSignal<T>)) -> Self { fn from(s: (Signal<T>, WriteSignal<T>)) -> Self {
Self::DynamicRw(s.0, s.1) Self::DynamicRw(s.0, s.1)
} }
} }
impl From<&str> for MaybeRwSignal<String> { impl<T> FromLocal<(Signal<T, LocalStorage>, WriteSignal<T, LocalStorage>)>
for MaybeRwSignal<T, LocalStorage>
where
LocalStorage: Storage<T>,
{
fn from_local(s: (Signal<T, LocalStorage>, WriteSignal<T, LocalStorage>)) -> Self {
Self::DynamicRw(s.0, s.1)
}
}
impl<S> From<&str> for MaybeRwSignal<String, S>
where
S: Storage<String>,
{
fn from(s: &str) -> Self { fn from(s: &str) -> Self {
Self::Static(s.to_string()) Self::Static(s.to_string())
} }
} }
impl<T: Clone> MaybeRwSignal<T, LocalStorage> {
pub fn into_signal(self) -> (Signal<T, LocalStorage>, WriteSignal<T, LocalStorage>) {
match self {
Self::DynamicRead(s) => {
let (r, w) = signal_local(s.get_untracked());
Effect::<LocalStorage>::new(move |_| {
w.update(move |w| {
*w = s.get();
});
});
(r.into(), w)
}
Self::DynamicRw(r, w) => (r, w),
Self::Static(v) => {
let (r, w) = signal_local(v.clone());
(Signal::from(r), w)
}
}
}
}
impl<T: Clone> MaybeRwSignal<T> impl<T: Clone> MaybeRwSignal<T>
where where
T: Send + Sync, T: Send + Sync,

View file

@ -1,21 +1,28 @@
use leptos::prelude::*; use leptos::prelude::*;
pub enum UseRwSignal<T: 'static> { pub enum UseRwSignal<T: 'static, S = SyncStorage>
Separate(Signal<T>, WriteSignal<T>), where
Combined(RwSignal<T>), S: Storage<T>,
{
Separate(Signal<T, S>, WriteSignal<T, S>),
Combined(RwSignal<T, S>),
} }
impl<T> From<RwSignal<T>> for UseRwSignal<T> { impl<T, S> From<RwSignal<T, S>> for UseRwSignal<T, S>
fn from(s: RwSignal<T>) -> Self { where
S: Storage<T>,
{
fn from(s: RwSignal<T, S>) -> Self {
Self::Combined(s) Self::Combined(s)
} }
} }
impl<T, RS> From<(RS, WriteSignal<T>)> for UseRwSignal<T> impl<T, S, RS> From<(RS, WriteSignal<T, S>)> for UseRwSignal<T, S>
where where
RS: Into<Signal<T>>, RS: Into<Signal<T, S>>,
S: Storage<T>,
{ {
fn from(s: (RS, WriteSignal<T>)) -> Self { fn from(s: (RS, WriteSignal<T, S>)) -> Self {
Self::Separate(s.0.into(), s.1) Self::Separate(s.0.into(), s.1)
} }
} }
@ -29,15 +36,30 @@ where
} }
} }
impl<T> Clone for UseRwSignal<T> { impl<T> Default for UseRwSignal<T, LocalStorage>
where
T: Default,
{
fn default() -> Self {
Self::Combined(Default::default())
}
}
impl<T, S> Clone for UseRwSignal<T, S>
where
S: Storage<T>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<T> Copy for UseRwSignal<T> {} impl<T, S> Copy for UseRwSignal<T, S> where S: Storage<T> {}
impl<T> DefinedAt for UseRwSignal<T> { impl<T, S> DefinedAt for UseRwSignal<T, S>
where
S: Storage<T>,
{
fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> { fn defined_at(&self) -> Option<&'static std::panic::Location<'static>> {
match self { match self {
Self::Combined(s) => s.defined_at(), Self::Combined(s) => s.defined_at(),
@ -47,9 +69,12 @@ impl<T> DefinedAt for UseRwSignal<T> {
} }
} }
impl<T> With for UseRwSignal<T> impl<T, S> With for UseRwSignal<T, S>
where where
T: Send + Sync, RwSignal<T, S>: With<Value = T>,
Signal<T, S>: With<Value = T>,
ReadSignal<T, S>: With<Value = T>,
S: Storage<T>,
{ {
type Value = T; type Value = T;
@ -68,9 +93,12 @@ where
} }
} }
impl<T> WithUntracked for UseRwSignal<T> impl<T, S> WithUntracked for UseRwSignal<T, S>
where where
T: Send + Sync, RwSignal<T, S>: WithUntracked<Value = T>,
Signal<T, S>: WithUntracked<Value = T>,
ReadSignal<T, S>: WithUntracked<Value = T>,
S: Storage<T>,
{ {
type Value = T; type Value = T;
@ -89,7 +117,12 @@ where
} }
} }
impl<T> Set for UseRwSignal<T> { impl<T, S> Set for UseRwSignal<T, S>
where
RwSignal<T, S>: Set<Value = T>,
WriteSignal<T, S>: Set<Value = T>,
S: Storage<T>,
{
type Value = T; type Value = T;
fn set(&self, new_value: T) { fn set(&self, new_value: T) {
@ -107,7 +140,12 @@ impl<T> Set for UseRwSignal<T> {
} }
} }
impl<T> Update for UseRwSignal<T> { impl<T, S> Update for UseRwSignal<T, S>
where
RwSignal<T, S>: Update<Value = T>,
WriteSignal<T, S>: Update<Value = T>,
S: Storage<T>,
{
type Value = T; type Value = T;
fn update(&self, f: impl FnOnce(&mut T)) { fn update(&self, f: impl FnOnce(&mut T)) {

View file

@ -68,7 +68,7 @@ mod use_preferred_dark;
mod use_raf_fn; mod use_raf_fn;
mod use_resize_observer; mod use_resize_observer;
mod use_scroll; mod use_scroll;
// mod use_service_worker; mod use_service_worker;
mod use_sorted; mod use_sorted;
mod use_supported; mod use_supported;
mod use_throttle_fn; mod use_throttle_fn;
@ -134,7 +134,7 @@ pub use use_preferred_dark::*;
pub use use_raf_fn::*; pub use use_raf_fn::*;
pub use use_resize_observer::*; pub use use_resize_observer::*;
pub use use_scroll::*; pub use use_scroll::*;
// pub use use_service_worker::*; pub use use_service_worker::*;
pub use use_sorted::*; pub use use_sorted::*;
pub use use_supported::*; pub use use_supported::*;
pub use use_throttle_fn::*; pub use use_throttle_fn::*;

View file

@ -149,7 +149,7 @@ where
let ignore = ignore.get_untracked(); let ignore = ignore.get_untracked();
ignore.into_iter().flatten().any(|element| { ignore.into_iter().flatten().any(|element| {
let element: web_sys::EventTarget = element.take().into(); let element: web_sys::EventTarget = element.into();
event_target::<web_sys::EventTarget>(event) == element event_target::<web_sys::EventTarget>(event) == element
|| event.composed_path().includes(element.as_ref(), 0) || event.composed_path().includes(element.as_ref(), 0)

View file

@ -15,7 +15,7 @@ pub fn use_local_storage<T, C>(
key: impl AsRef<str>, key: impl AsRef<str>,
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + Default + PartialEq + Send + Sync, T: Clone + Default + PartialEq + Send + Sync + 'static,
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>, C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
{ {
use_storage_with_options::<T, C>( use_storage_with_options::<T, C>(

View file

@ -14,7 +14,7 @@ pub fn use_session_storage<T, C>(
key: impl AsRef<str>, key: impl AsRef<str>,
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Clone + Default + PartialEq + Send + Sync, T: Clone + Default + PartialEq + Send + Sync + 'static,
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>, C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
{ {
use_storage_with_options::<T, C>( use_storage_with_options::<T, C>(

View file

@ -152,7 +152,7 @@ pub fn use_storage<T, C>(
key: impl AsRef<str>, key: impl AsRef<str>,
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone) ) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
where where
T: Default + Clone + PartialEq + Send + Sync, T: Default + Clone + PartialEq + Send + Sync + 'static,
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>, C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
{ {
use_storage_with_options::<T, C>(storage_type, key, UseStorageOptions::default()) use_storage_with_options::<T, C>(storage_type, key, UseStorageOptions::default())
@ -203,7 +203,7 @@ where
// Get storage API // Get storage API
let storage = storage_type let storage = storage_type
.into_storage() .into_storage()
.map_err(|e| UseStorageError::StorageNotAvailable(SendWrapper::new(e))) .map_err(UseStorageError::StorageNotAvailable)
.and_then(|s| s.ok_or(UseStorageError::StorageReturnedNone)); .and_then(|s| s.ok_or(UseStorageError::StorageReturnedNone));
let storage = handle_error(&on_error, storage); let storage = handle_error(&on_error, storage);
@ -227,7 +227,7 @@ where
) )
.expect("failed to create custom storage event"), .expect("failed to create custom storage event"),
) )
.map_err(|e| UseStorageError::NotifyItemChangedFailed(SendWrapper::new(e))); .map_err(UseStorageError::NotifyItemChangedFailed);
let _ = handle_error(&on_error, result); let _ = handle_error(&on_error, result);
}) })
} }
@ -246,7 +246,7 @@ where
// Get directly from storage // Get directly from storage
let result = storage let result = storage
.get_item(&key) .get_item(&key)
.map_err(|e| UseStorageError::GetItemFailed(SendWrapper::new(e))); .map_err(UseStorageError::GetItemFailed);
handle_error(&on_error, result) handle_error(&on_error, result)
}) })
.unwrap_or_default() // Drop handled Err(()) .unwrap_or_default() // Drop handled Err(())
@ -314,9 +314,9 @@ where
.map_err(|e| UseStorageError::ItemCodecError(CodecError::Encode(e))) .map_err(|e| UseStorageError::ItemCodecError(CodecError::Encode(e)))
.and_then(|enc_value| { .and_then(|enc_value| {
// Set storage -- sends a global event // Set storage -- sends a global event
storage.set_item(&key, &enc_value).map_err(|e| { storage
UseStorageError::SetItemFailed(SendWrapper::new(e)) .set_item(&key, &enc_value)
}) .map_err(UseStorageError::SetItemFailed)
}); });
let result = handle_error(&on_error, result); let result = handle_error(&on_error, result);
// Send internal storage event // Send internal storage event
@ -329,18 +329,19 @@ where
); );
} }
// TODO: solve for 0.7 if delay_during_hydration
// // Fetch initial value && Owner::current_shared_context()
// if delay_during_hydration && leptos::leptos_dom::HydrationCtx::is_hydrating() { .map(|sc| sc.during_hydration())
// request_animation_frame(fetch_from_storage.clone()); .unwrap_or_default()
// } else { {
// fetch_from_storage(); request_animation_frame({
// } let fetch_from_storage = fetch_from_storage.clone();
request_animation_frame({ #[allow(clippy::redundant_closure)]
let fetch_from_storage = fetch_from_storage.clone(); move || fetch_from_storage()
#[allow(clippy::redundant_closure)] });
move || fetch_from_storage() } else {
}); fetch_from_storage();
}
if listen_to_storage_changes { if listen_to_storage_changes {
let check_key = key.as_ref().to_owned(); let check_key = key.as_ref().to_owned();
@ -378,7 +379,7 @@ where
// Delete directly from storage // Delete directly from storage
let result = storage let result = storage
.remove_item(&key) .remove_item(&key)
.map_err(|e| UseStorageError::RemoveItemFailed(SendWrapper::new(e))); .map_err(|e| UseStorageError::RemoveItemFailed(e));
let _ = handle_error(&on_error, result); let _ = handle_error(&on_error, result);
notify.trigger(); notify.trigger();
dispatch_storage_event(); dispatch_storage_event();
@ -394,17 +395,17 @@ where
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum UseStorageError<E, D> { pub enum UseStorageError<E, D> {
#[error("storage not available")] #[error("storage not available")]
StorageNotAvailable(SendWrapper<JsValue>), StorageNotAvailable(JsValue),
#[error("storage not returned from window")] #[error("storage not returned from window")]
StorageReturnedNone, StorageReturnedNone,
#[error("failed to get item")] #[error("failed to get item")]
GetItemFailed(SendWrapper<JsValue>), GetItemFailed(JsValue),
#[error("failed to set item")] #[error("failed to set item")]
SetItemFailed(SendWrapper<JsValue>), SetItemFailed(JsValue),
#[error("failed to delete item")] #[error("failed to delete item")]
RemoveItemFailed(SendWrapper<JsValue>), RemoveItemFailed(JsValue),
#[error("failed to notify item changed")] #[error("failed to notify item changed")]
NotifyItemChangedFailed(SendWrapper<JsValue>), NotifyItemChangedFailed(JsValue),
#[error("failed to encode / decode item value")] #[error("failed to encode / decode item value")]
ItemCodecError(CodecError<E, D>), ItemCodecError(CodecError<E, D>),
} }
@ -413,7 +414,7 @@ pub enum UseStorageError<E, D> {
#[derive(DefaultBuilder)] #[derive(DefaultBuilder)]
pub struct UseStorageOptions<T, E, D> pub struct UseStorageOptions<T, E, D>
where where
T: 'static, T: Send + Sync + 'static,
{ {
// Callback for when an error occurs // Callback for when an error occurs
#[builder(skip)] #[builder(skip)]
@ -441,7 +442,10 @@ fn handle_error<T, E, D>(
result.map_err(|err| (on_error)(err)) result.map_err(|err| (on_error)(err))
} }
impl<T: Default, E, D> Default for UseStorageOptions<T, E, D> { impl<T: Default, E, D> Default for UseStorageOptions<T, E, D>
where
T: Send + Sync + 'static,
{
fn default() -> Self { fn default() -> Self {
Self { Self {
on_error: Arc::new(|_err| ()), on_error: Arc::new(|_err| ()),
@ -453,7 +457,10 @@ impl<T: Default, E, D> Default for UseStorageOptions<T, E, D> {
} }
} }
impl<T: Default, E, D> UseStorageOptions<T, E, D> { impl<T: Default, E, D> UseStorageOptions<T, E, D>
where
T: Send + Sync + 'static,
{
/// Optional callback whenever an error occurs. /// Optional callback whenever an error occurs.
pub fn on_error( pub fn on_error(
self, self,

View file

@ -184,7 +184,10 @@ macro_rules! impl_cmp_reactively {
}; };
} }
impl<K: Eq + Hash + Debug + Clone + Send + Sync> UseBreakpointsReturn<K> { impl<K> UseBreakpointsReturn<K>
where
K: Eq + Hash + Debug + Clone + Send + Sync + 'static,
{
fn match_(query: &str) -> bool { fn match_(query: &str) -> bool {
if let Ok(Some(query_list)) = use_window().match_media(query) { if let Ok(Some(query_list)) = use_window().match_media(query) {
return query_list.matches(); return query_list.matches();

View file

@ -4,7 +4,6 @@ use crate::{
use codee::{CodecError, Decoder, Encoder}; use codee::{CodecError, Decoder, Encoder};
use leptos::ev::messageerror; use leptos::ev::messageerror;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use thiserror::Error; use thiserror::Error;
use wasm_bindgen::JsValue; use wasm_bindgen::JsValue;
@ -89,9 +88,9 @@ where
let is_supported = use_supported(|| js!("BroadcastChannel" in &window())); let is_supported = use_supported(|| js!("BroadcastChannel" in &window()));
let (is_closed, set_closed) = signal(false); let (is_closed, set_closed) = signal(false);
let (channel, set_channel) = signal(None::<SendWrapper<web_sys::BroadcastChannel>>); let (channel, set_channel) = signal_local(None::<web_sys::BroadcastChannel>);
let (message, set_message) = signal(None::<T>); let (message, set_message) = signal(None::<T>);
let (error, set_error) = signal( let (error, set_error) = signal_local(
None::<UseBroadcastChannelError<<C as Encoder<T>>::Error, <C as Decoder<T>>::Error>>, None::<UseBroadcastChannelError<<C as Encoder<T>>::Error, <C as Decoder<T>>::Error>>,
); );
@ -103,9 +102,7 @@ where
channel channel
.post_message(&msg.into()) .post_message(&msg.into())
.map_err(|err| { .map_err(|err| {
set_error.set(Some(UseBroadcastChannelError::PostMessage( set_error.set(Some(UseBroadcastChannelError::PostMessage(err)))
SendWrapper::new(err),
)))
}) })
.ok(); .ok();
} }
@ -130,7 +127,7 @@ where
if is_supported.get_untracked() { if is_supported.get_untracked() {
let channel_val = web_sys::BroadcastChannel::new(name).ok(); let channel_val = web_sys::BroadcastChannel::new(name).ok();
set_channel.set(channel_val.clone().map(SendWrapper::new)); set_channel.set(channel_val.clone());
if let Some(channel) = channel_val { if let Some(channel) = channel_val {
let _ = use_event_listener_with_options( let _ = use_event_listener_with_options(
@ -157,9 +154,7 @@ where
channel.clone(), channel.clone(),
messageerror, messageerror,
move |event| { move |event| {
set_error.set(Some(UseBroadcastChannelError::MessageEvent( set_error.set(Some(UseBroadcastChannelError::MessageEvent(event)));
SendWrapper::new(event),
)));
}, },
UseEventListenerOptions::default().passive(true), UseEventListenerOptions::default().passive(true),
); );
@ -186,17 +181,17 @@ where
/// Return type of [`use_broadcast_channel`]. /// Return type of [`use_broadcast_channel`].
pub struct UseBroadcastChannelReturn<T, PFn, CFn, E, D> pub struct UseBroadcastChannelReturn<T, PFn, CFn, E, D>
where where
T: 'static, T: Send + Sync + 'static,
PFn: Fn(&T) + Clone, PFn: Fn(&T) + Clone,
CFn: Fn() + Clone, CFn: Fn() + Clone,
E: 'static, E: Send + Sync + 'static,
D: 'static, D: Send + Sync + 'static,
{ {
/// `true` if this browser supports `BroadcastChannel`s. /// `true` if this browser supports `BroadcastChannel`s.
pub 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
pub channel: Signal<Option<SendWrapper<web_sys::BroadcastChannel>>>, pub channel: Signal<Option<web_sys::BroadcastChannel>, LocalStorage>,
/// Latest message received from the channel /// Latest message received from the channel
pub message: Signal<Option<T>>, pub message: Signal<Option<T>>,
@ -208,7 +203,7 @@ where
pub close: CFn, pub close: CFn,
/// Latest error as reported by the `messageerror` event. /// Latest error as reported by the `messageerror` event.
pub error: Signal<Option<UseBroadcastChannelError<E, D>>>, pub error: Signal<Option<UseBroadcastChannelError<E, D>>, LocalStorage>,
/// Wether the channel is closed /// Wether the channel is closed
pub is_closed: Signal<bool>, pub is_closed: Signal<bool>,
@ -217,9 +212,9 @@ where
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum UseBroadcastChannelError<E, D> { pub enum UseBroadcastChannelError<E, D> {
#[error("failed to post message")] #[error("failed to post message")]
PostMessage(SendWrapper<JsValue>), PostMessage(JsValue),
#[error("channel message error")] #[error("channel message error")]
MessageEvent(SendWrapper<web_sys::MessageEvent>), MessageEvent(web_sys::MessageEvent),
#[error("failed to (de)encode value")] #[error("failed to (de)encode value")]
Codec(CodecError<E, D>), Codec(CodecError<E, D>),
#[error("received value is not a string")] #[error("received value is not a string")]

View file

@ -143,7 +143,7 @@ use std::sync::Arc;
pub fn use_cookie<T, C>(cookie_name: &str) -> (Signal<Option<T>>, WriteSignal<Option<T>>) pub fn use_cookie<T, C>(cookie_name: &str) -> (Signal<Option<T>>, WriteSignal<Option<T>>)
where where
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>, C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
T: Clone + Send + Sync, T: Clone + Send + Sync + 'static,
{ {
use_cookie_with_options::<T, C>(cookie_name, UseCookieOptions::default()) use_cookie_with_options::<T, C>(cookie_name, UseCookieOptions::default())
} }
@ -155,7 +155,7 @@ pub fn use_cookie_with_options<T, C>(
) -> (Signal<Option<T>>, WriteSignal<Option<T>>) ) -> (Signal<Option<T>>, WriteSignal<Option<T>>)
where where
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>, C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
T: Clone + Send + Sync, T: Clone + Send + Sync + 'static,
{ {
let UseCookieOptions { let UseCookieOptions {
max_age, max_age,
@ -363,31 +363,38 @@ where
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
{ {
if !readonly { if !readonly {
create_isomorphic_effect(move |_| { Effect::new_isomorphic({
let value = cookie let cookie_name = cookie_name.to_owned();
.with(|cookie| {
cookie.as_ref().map(|cookie| { move |_| {
C::encode(cookie) let domain = domain.clone();
.map_err(|err| on_error(CodecError::Encode(err))) let path = path.clone();
.ok()
let value = cookie
.with(|cookie| {
cookie.as_ref().map(|cookie| {
C::encode(cookie)
.map_err(|err| on_error(CodecError::Encode(err)))
.ok()
})
}) })
}) .flatten();
.flatten(); jar.update_value(|jar| {
jar.update_value(|jar| { write_server_cookie(
write_server_cookie( &cookie_name,
cookie_name, value,
value, jar,
jar, max_age,
max_age, expires,
expires, domain,
domain, path,
path, same_site,
same_site, secure,
secure, http_only,
http_only, Arc::clone(&ssr_set_cookie),
ssr_set_cookie, )
) });
}); }
}); });
} }
} }

View file

@ -173,7 +173,7 @@ where
#[derive(DefaultBuilder)] #[derive(DefaultBuilder)]
pub struct UseCycleListOptions<T> pub struct UseCycleListOptions<T>
where where
T: Clone + PartialEq + 'static, T: Clone + PartialEq + Send + Sync + 'static,
{ {
/// The initial value of the state. Can be a Signal. If none is provided the first entry /// The initial value of the state. Can be a Signal. If none is provided the first entry
/// of the list will be used. /// of the list will be used.
@ -191,7 +191,7 @@ where
impl<T> Default for UseCycleListOptions<T> impl<T> Default for UseCycleListOptions<T>
where where
T: Clone + PartialEq + 'static, T: Clone + PartialEq + Send + Sync + 'static,
{ {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -205,7 +205,7 @@ where
/// Return type of [`use_cycle_list`]. /// Return type of [`use_cycle_list`].
pub struct UseCycleListReturn<T, SetFn, NextFn, PrevFn, ShiftFn> pub struct UseCycleListReturn<T, SetFn, NextFn, PrevFn, ShiftFn>
where where
T: Clone + PartialEq + 'static, T: Clone + PartialEq + Send + Sync + 'static,
SetFn: Fn(usize) -> T + Clone, SetFn: Fn(usize) -> T + Clone,
NextFn: Fn() + Clone, NextFn: Fn() + Clone,
PrevFn: Fn() + Clone, PrevFn: Fn() + Clone,

View file

@ -68,8 +68,10 @@ pub fn use_device_orientation() -> UseDeviceOrientationReturn {
.once(false), .once(false),
); );
let cleanup = SendWrapper::new(cleanup); on_cleanup({
on_cleanup(move || cleanup()); let cleanup = SendWrapper::new(cleanup);
move || cleanup()
});
} }
}} }}

View file

@ -3,7 +3,6 @@ use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen::{JsCast, JsValue};
/// Reactive [`mediaDevices.getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) streaming. /// Reactive [`mediaDevices.getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) streaming.
@ -56,8 +55,7 @@ pub fn use_display_media_with_options(
let (enabled, set_enabled) = enabled.into_signal(); let (enabled, set_enabled) = enabled.into_signal();
let (stream, set_stream) = let (stream, set_stream) = signal_local(None::<Result<web_sys::MediaStream, JsValue>>);
signal(None::<Result<SendWrapper<web_sys::MediaStream>, SendWrapper<JsValue>>>);
let _start = move || async move { let _start = move || async move {
cfg_if! { if #[cfg(not(feature = "ssr"))] { cfg_if! { if #[cfg(not(feature = "ssr"))] {
@ -65,10 +63,7 @@ pub fn use_display_media_with_options(
return; return;
} }
let stream = create_media(audio) let stream = create_media(audio).await;
.await
.map(SendWrapper::new)
.map_err(SendWrapper::new);
set_stream.update(|s| *s = Some(stream)); set_stream.update(|s| *s = Some(stream));
} else { } else {
@ -181,7 +176,7 @@ where
/// Initially this is `None` until `start` resolved successfully. /// Initially this is `None` until `start` resolved successfully.
/// In case the stream couldn't be started, for example because the user didn't grant permission, /// In case the stream couldn't be started, for example because the user didn't grant permission,
/// this has the value `Some(Err(...))`. /// this has the value `Some(Err(...))`.
pub stream: Signal<Option<Result<SendWrapper<web_sys::MediaStream>, SendWrapper<JsValue>>>>, pub stream: Signal<Option<Result<web_sys::MediaStream, JsValue>>, LocalStorage>,
/// Starts the screen streaming. Triggers the ask for permission if not already granted. /// Starts the screen streaming. Triggers the ask for permission if not already granted.
pub start: StartFn, pub start: StartFn,

View file

@ -5,7 +5,6 @@ use leptos::ev::{pointerdown, pointermove, pointerup};
use leptos::prelude::diagnostics::SpecialNonReactiveZone; use leptos::prelude::diagnostics::SpecialNonReactiveZone;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::Arc; use std::sync::Arc;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
@ -93,12 +92,11 @@ where
let target = target.into(); let target = target.into();
let dragging_handle = if let Some(handle) = handle { let dragging_handle = if let Some(handle) = handle {
// let handle = Signal::derive(|| SendWrapper::new(handle));
let handle: ElementMaybeSignal<_, _> = handle.into(); let handle: ElementMaybeSignal<_, _> = handle.into();
Signal::derive(move || handle.get().map(|handle| SendWrapper::new(handle.into()))) Signal::derive_local(move || handle.get().map(|handle| handle.into()))
} else { } else {
let target = target.clone(); let target = target.clone();
Signal::derive(move || target.get().map(|target| SendWrapper::new(target.into()))) Signal::derive_local(move || target.get().map(|target| target.into()))
}; };
let (position, set_position) = initial_value.into_signal(); let (position, set_position) = initial_value.into_signal();

View file

@ -3,7 +3,6 @@ use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::sync::Arc; use std::sync::Arc;
@ -74,7 +73,7 @@ where
T: Into<web_sys::EventTarget> + Clone + 'static, T: Into<web_sys::EventTarget> + Clone + 'static,
{ {
let (is_over_drop_zone, set_over_drop_zone) = signal(false); let (is_over_drop_zone, set_over_drop_zone) = signal(false);
let (files, set_files) = signal(Vec::<SendWrapper<web_sys::File>>::new()); let (files, set_files) = signal_local(Vec::<web_sys::File>::new());
#[cfg(not(feature = "ssr"))] #[cfg(not(feature = "ssr"))]
{ {
@ -95,7 +94,7 @@ where
.map(|f| js_sys::Array::from(&f).to_vec()) .map(|f| js_sys::Array::from(&f).to_vec())
.unwrap_or_default() .unwrap_or_default()
.into_iter() .into_iter()
.map(|f| SendWrapper::new(web_sys::File::from(f))) .map(web_sys::File::from)
.collect(); .collect();
set_files.update(move |f| *f = files); set_files.update(move |f| *f = files);
@ -113,11 +112,7 @@ where
let _z = SpecialNonReactiveZone::enter(); let _z = SpecialNonReactiveZone::enter();
on_enter(UseDropZoneEvent { on_enter(UseDropZoneEvent {
files: files files: files.get_untracked().into_iter().collect(),
.get_untracked()
.into_iter()
.map(SendWrapper::take)
.collect(),
event, event,
}); });
}); });
@ -130,11 +125,7 @@ where
let _z = SpecialNonReactiveZone::enter(); let _z = SpecialNonReactiveZone::enter();
on_over(UseDropZoneEvent { on_over(UseDropZoneEvent {
files: files files: files.get_untracked().into_iter().collect(),
.get_untracked()
.into_iter()
.map(SendWrapper::take)
.collect(),
event, event,
}); });
}); });
@ -152,11 +143,7 @@ where
let _z = SpecialNonReactiveZone::enter(); let _z = SpecialNonReactiveZone::enter();
on_leave(UseDropZoneEvent { on_leave(UseDropZoneEvent {
files: files files: files.get_untracked().into_iter().collect(),
.get_untracked()
.into_iter()
.map(SendWrapper::take)
.collect(),
event, event,
}); });
}); });
@ -172,11 +159,7 @@ where
let _z = SpecialNonReactiveZone::enter(); let _z = SpecialNonReactiveZone::enter();
on_drop(UseDropZoneEvent { on_drop(UseDropZoneEvent {
files: files files: files.get_untracked().into_iter().collect(),
.get_untracked()
.into_iter()
.map(SendWrapper::take)
.collect(),
event, event,
}); });
}); });
@ -231,7 +214,7 @@ pub struct UseDropZoneEvent {
/// Return type of [`use_drop_zone`]. /// Return type of [`use_drop_zone`].
pub struct UseDropZoneReturn { pub struct UseDropZoneReturn {
/// Files being handled /// Files being handled
pub files: Signal<Vec<SendWrapper<web_sys::File>>>, pub files: Signal<Vec<web_sys::File>, LocalStorage>,
/// Whether the files (dragged by the pointer) are over the drop zone /// Whether the files (dragged by the pointer) are over the drop zone
pub is_over_drop_zone: Signal<bool>, pub is_over_drop_zone: Signal<bool>,
} }

View file

@ -188,8 +188,10 @@ where
cleanup_prev_element(); cleanup_prev_element();
}; };
let cleanup_stop = SendWrapper::new(stop.clone()); on_cleanup({
on_cleanup(move || cleanup_stop()); let stop = SendWrapper::new(stop.clone());
move || stop()
});
stop stop
} }

View file

@ -4,7 +4,6 @@ use codee::Decoder;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::diagnostics::SpecialNonReactiveZone; use leptos::prelude::diagnostics::SpecialNonReactiveZone;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, AtomicU32}; use std::sync::atomic::{AtomicBool, AtomicU32};
use std::sync::Arc; use std::sync::Arc;
@ -148,11 +147,11 @@ where
let url = url.to_owned(); let url = url.to_owned();
let (event, set_event) = signal(None::<SendWrapper<web_sys::Event>>); let (event, set_event) = signal_local(None::<web_sys::Event>);
let (data, set_data) = signal(None::<T>); let (data, set_data) = signal(None::<T>);
let (ready_state, set_ready_state) = signal(ConnectionReadyState::Closed); let (ready_state, set_ready_state) = signal(ConnectionReadyState::Closed);
let (event_source, set_event_source) = signal(None::<SendWrapper<web_sys::EventSource>>); let (event_source, set_event_source) = signal_local(None::<web_sys::EventSource>);
let (error, set_error) = signal(None::<UseEventSourceError<C::Error>>); let (error, set_error) = signal_local(None::<UseEventSourceError<C::Error>>);
let explicitly_closed = Arc::new(AtomicBool::new(false)); let explicitly_closed = Arc::new(AtomicBool::new(false));
let retried = Arc::new(AtomicU32::new(0)); let retried = Arc::new(AtomicU32::new(0));
@ -200,7 +199,7 @@ where
set_ready_state.set(ConnectionReadyState::Connecting); set_ready_state.set(ConnectionReadyState::Connecting);
set_event_source.set(Some(SendWrapper::new(es.clone()))); set_event_source.set(Some(es.clone()));
let on_open = Closure::wrap(Box::new(move |_: web_sys::Event| { let on_open = Closure::wrap(Box::new(move |_: web_sys::Event| {
set_ready_state.set(ConnectionReadyState::Open); set_ready_state.set(ConnectionReadyState::Open);
@ -217,7 +216,7 @@ where
move |e: web_sys::Event| { move |e: web_sys::Event| {
set_ready_state.set(ConnectionReadyState::Closed); set_ready_state.set(ConnectionReadyState::Closed);
set_error.set(Some(UseEventSourceError::Event(SendWrapper::new(e)))); set_error.set(Some(UseEventSourceError::Event(e)));
// only reconnect if EventSource isn't reconnecting by itself // only reconnect if EventSource isn't reconnecting by itself
// this is the case when the connection is closed (readyState is 2) // this is the case when the connection is closed (readyState is 2)
@ -262,7 +261,7 @@ where
es.clone(), es.clone(),
leptos::ev::Custom::<leptos::ev::Event>::new(event_name), leptos::ev::Custom::<leptos::ev::Event>::new(event_name),
move |e| { move |e| {
set_event.set(Some(SendWrapper::new(e.clone()))); set_event.set(Some(e.clone()));
let data_string = js!(e["data"]).ok().and_then(|d| d.as_string()); let data_string = js!(e["data"]).ok().and_then(|d| d.as_string());
set_data_from_string(data_string); set_data_from_string(data_string);
}, },
@ -373,10 +372,10 @@ where
pub ready_state: Signal<ConnectionReadyState>, pub ready_state: Signal<ConnectionReadyState>,
/// The latest named event /// The latest named event
pub event: Signal<Option<SendWrapper<web_sys::Event>>>, pub event: Signal<Option<web_sys::Event>, LocalStorage>,
/// The current error /// The current error
pub error: Signal<Option<UseEventSourceError<Err>>>, pub error: Signal<Option<UseEventSourceError<Err>>, LocalStorage>,
/// (Re-)Opens the `EventSource` connection /// (Re-)Opens the `EventSource` connection
/// If the current one is active, will close it before opening a new one. /// If the current one is active, will close it before opening a new one.
@ -386,13 +385,13 @@ where
pub close: CloseFn, pub close: CloseFn,
/// The `EventSource` instance /// The `EventSource` instance
pub event_source: Signal<Option<SendWrapper<web_sys::EventSource>>>, pub event_source: Signal<Option<web_sys::EventSource>, LocalStorage>,
} }
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum UseEventSourceError<Err> { pub enum UseEventSourceError<Err> {
#[error("Error event: {0:?}")] #[error("Error event: {0:?}")]
Event(SendWrapper<web_sys::Event>), Event(web_sys::Event),
#[error("Error decoding value")] #[error("Error decoding value")]
Deserialize(Err), Deserialize(Err),

View file

@ -2,7 +2,6 @@ use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
/// Reactive [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API). /// Reactive [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API).
/// It allows the user to provide their location to web applications if they so desire. For privacy reasons, /// It allows the user to provide their location to web applications if they so desire. For privacy reasons,
@ -44,8 +43,8 @@ pub fn use_geolocation_with_options(
options: UseGeolocationOptions, options: UseGeolocationOptions,
) -> UseGeolocationReturn<impl Fn() + Clone, impl Fn() + Clone> { ) -> UseGeolocationReturn<impl Fn() + Clone, impl Fn() + Clone> {
let (located_at, set_located_at) = signal(None::<f64>); let (located_at, set_located_at) = signal(None::<f64>);
let (error, set_error) = signal(None::<SendWrapper<web_sys::PositionError>>); let (error, set_error) = signal_local(None::<web_sys::PositionError>);
let (coords, set_coords) = signal(None::<SendWrapper<web_sys::Coordinates>>); let (coords, set_coords) = signal_local(None::<web_sys::Coordinates>);
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
let resume = || (); let resume = || ();
@ -62,12 +61,12 @@ pub fn use_geolocation_with_options(
let update_position = move |position: web_sys::Position| { let update_position = move |position: web_sys::Position| {
set_located_at.set(Some(position.timestamp())); set_located_at.set(Some(position.timestamp()));
set_coords.set(Some(SendWrapper::new(position.coords()))); set_coords.set(Some(position.coords()));
set_error.set(None); set_error.set(None);
}; };
let on_error = move |err: web_sys::PositionError| { let on_error = move |err: web_sys::PositionError| {
set_error.set(Some(SendWrapper::new(err))); set_error.set(Some(err));
}; };
let watch_handle = Arc::new(Mutex::new(None::<i32>)); let watch_handle = Arc::new(Mutex::new(None::<i32>));
@ -203,13 +202,13 @@ where
{ {
/// The coordinates of the current device like latitude and longitude. /// The coordinates of the current device like latitude and longitude.
/// See [`GeolocationCoordinates`](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates).. /// See [`GeolocationCoordinates`](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates)..
pub coords: Signal<Option<SendWrapper<web_sys::Coordinates>>>, pub coords: Signal<Option<web_sys::Coordinates>, LocalStorage>,
/// The timestamp of the current coordinates. /// The timestamp of the current coordinates.
pub located_at: Signal<Option<f64>>, pub located_at: Signal<Option<f64>>,
/// The last error received from `navigator.geolocation`. /// The last error received from `navigator.geolocation`.
pub error: Signal<Option<SendWrapper<web_sys::PositionError>>>, pub error: Signal<Option<web_sys::PositionError>, LocalStorage>,
/// Resume the geolocation watch. /// Resume the geolocation watch.
pub resume: ResumeFn, pub resume: ResumeFn,

View file

@ -9,7 +9,6 @@ use gloo_timers::future::sleep;
use leptos::prelude::diagnostics::SpecialNonReactiveZone; use leptos::prelude::diagnostics::SpecialNonReactiveZone;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::future::Future; use std::future::Future;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@ -111,20 +110,18 @@ where
let (is_loading, set_loading) = signal(false); let (is_loading, set_loading) = signal(false);
let el = el.into(); let el = el.into();
let observed_element = Signal::derive(move || { let observed_element = Signal::derive_local(move || {
let el = el.get(); let el = el.get();
el.map(|el| { el.map(|el| {
let el = el.into(); let el = el.into();
if el.is_instance_of::<web_sys::Window>() || el.is_instance_of::<web_sys::Document>() { if el.is_instance_of::<web_sys::Window>() || el.is_instance_of::<web_sys::Document>() {
SendWrapper::new( document()
document() .document_element()
.document_element() .expect("document element not found")
.expect("document element not found"),
)
} else { } else {
SendWrapper::new(el) el
} }
}) })
}); });

View file

@ -175,7 +175,7 @@ where
.expect("failed to create IntersectionObserver"); .expect("failed to create IntersectionObserver");
for target in targets.iter().flatten() { for target in targets.iter().flatten() {
let target: web_sys::Element = target.clone().take().into(); let target: web_sys::Element = target.clone().into();
obs.observe(&target); obs.observe(&target);
} }

View file

@ -141,8 +141,10 @@ where
on_cleanup(stop_watch); on_cleanup(stop_watch);
} }
let pause_cleanup = SendWrapper::new(pause.clone()); on_cleanup({
on_cleanup(move || pause_cleanup()); let pause = SendWrapper::new(pause.clone());
move || pause()
});
Pausable { Pausable {
is_active: is_active.into(), is_active: is_active.into(),

View file

@ -6,7 +6,6 @@ use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::wrappers::read::Signal; use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::fmt::Display; use std::fmt::Display;
use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen::{JsCast, JsValue};
@ -168,7 +167,7 @@ pub fn use_intl_number_format(options: UseIntlNumberFormatOptions) -> UseIntlNum
); );
UseIntlNumberFormatReturn { UseIntlNumberFormatReturn {
js_intl_number_format: SendWrapper::new(number_format), js_intl_number_format: number_format,
} }
}} }}
} }
@ -769,14 +768,14 @@ cfg_if! { if #[cfg(feature = "ssr")] {
/// Return type of [`use_intl_number_format`]. /// Return type of [`use_intl_number_format`].
pub struct UseIntlNumberFormatReturn { pub struct UseIntlNumberFormatReturn {
/// The instance of [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat). /// The instance of [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat).
pub js_intl_number_format: SendWrapper<js_sys::Intl::NumberFormat>, pub js_intl_number_format: js_sys::Intl::NumberFormat,
} }
}} }}
impl UseIntlNumberFormatReturn { impl UseIntlNumberFormatReturn {
/// Formats a number according to the [locale and formatting options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters) of this `Intl.NumberFormat` object. /// Formats a number according to the [locale and formatting options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters) of this `Intl.NumberFormat` object.
/// See [`use_intl_number_format`] for more information. /// See [`use_intl_number_format`] for more information.
pub fn format<N>(&self, number: impl Into<MaybeSignal<N>>) -> Signal<String> pub fn format<N>(&self, number: impl Into<MaybeSignal<N>>) -> Signal<String, LocalStorage>
where where
N: Clone + Display + Send + Sync + 'static, N: Clone + Display + Send + Sync + 'static,
js_sys::Number: From<N>, js_sys::Number: From<N>,
@ -784,13 +783,13 @@ impl UseIntlNumberFormatReturn {
let number = number.into(); let number = number.into();
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
Signal::derive(move || { Signal::derive_local(move || {
format!("{}", number.get()) format!("{}", number.get())
}) })
} else { } else {
let number_format = self.js_intl_number_format.clone(); let number_format = self.js_intl_number_format.clone();
Signal::derive(move || { Signal::derive_local(move || {
if let Ok(result) = number_format if let Ok(result) = number_format
.format() .format()
.call1(&number_format, &js_sys::Number::from(number.get()).into()) .call1(&number_format, &js_sys::Number::from(number.get()).into())
@ -853,7 +852,7 @@ impl UseIntlNumberFormatReturn {
&self, &self,
start: impl Into<MaybeSignal<NStart>>, start: impl Into<MaybeSignal<NStart>>,
end: impl Into<MaybeSignal<NEnd>>, end: impl Into<MaybeSignal<NEnd>>,
) -> Signal<String> ) -> Signal<String, LocalStorage>
where where
NStart: Clone + Display + Send + Sync + 'static, NStart: Clone + Display + Send + Sync + 'static,
NEnd: Clone + Display + Send + Sync + 'static, NEnd: Clone + Display + Send + Sync + 'static,
@ -864,13 +863,13 @@ impl UseIntlNumberFormatReturn {
let end = end.into(); let end = end.into();
cfg_if! { if #[cfg(feature = "ssr")] { cfg_if! { if #[cfg(feature = "ssr")] {
Signal::derive(move || { Signal::derive_local(move || {
format!("{} - {}", start.get(), end.get()) format!("{} - {}", start.get(), end.get())
}) })
} else { } else {
let number_format = self.js_intl_number_format.clone(); let number_format = self.js_intl_number_format.clone();
Signal::derive(move || { Signal::derive_local(move || {
if let Ok(function) = js!(number_format["formatRange"]) { if let Ok(function) = js!(number_format["formatRange"]) {
let function = function.unchecked_into::<js_sys::Function>(); let function = function.unchecked_into::<js_sys::Function>();

View file

@ -136,7 +136,7 @@ where
.expect("failed to create MutationObserver"); .expect("failed to create MutationObserver");
for target in targets.iter().flatten() { for target in targets.iter().flatten() {
let target: web_sys::Element = target.clone().take().into(); let target: web_sys::Element = target.clone().into();
let _ = obs.observe_with_options(&target, &options.clone().into()); let _ = obs.observe_with_options(&target, &options.clone().into());
} }

View file

@ -138,8 +138,10 @@ pub fn use_raf_fn_with_options(
resume(); resume();
} }
let pause_cleanup = send_wrapper::SendWrapper::new(pause.clone()); on_cleanup({
on_cleanup(move || pause_cleanup()); let pause = send_wrapper::SendWrapper::new(pause.clone());
move || pause()
});
Pausable { Pausable {
resume, resume,

View file

@ -138,7 +138,7 @@ where
.expect("failed to create ResizeObserver"); .expect("failed to create ResizeObserver");
for target in targets.iter().flatten() { for target in targets.iter().flatten() {
let target: web_sys::Element = target.clone().take().into(); let target: web_sys::Element = target.clone().into();
obs.observe_with_options(&target, &options.clone().into()); obs.observe_with_options(&target, &options.clone().into());
} }
observer.replace(Some(obs)); observer.replace(Some(obs));

View file

@ -221,8 +221,6 @@ where
let set_y = |_| {}; let set_y = |_| {};
let measure = || {}; let measure = || {};
} else { } else {
use send_wrapper::SendWrapper;
let signal = element.into(); let signal = element.into();
let behavior = options.behavior; let behavior = options.behavior;
@ -372,9 +370,9 @@ where
let target = { let target = {
let signal = signal.clone(); let signal = signal.clone();
Signal::derive(move || { Signal::derive_local(move || {
let element = signal.get(); let element = signal.get();
element.map(|element| SendWrapper::new(element.into().unchecked_into::<web_sys::EventTarget>())) element.map(|element| element.into().unchecked_into::<web_sys::EventTarget>())
}) })
}; };
@ -394,14 +392,14 @@ where
let _ = use_event_listener_with_options::< let _ = use_event_listener_with_options::<
_, _,
Signal<Option<SendWrapper<web_sys::EventTarget>>>, Signal<Option<web_sys::EventTarget>, LocalStorage>,
web_sys::EventTarget, web_sys::EventTarget,
_, _,
>(target, ev::scroll, handler, options.event_listener_options); >(target, ev::scroll, handler, options.event_listener_options);
} else { } else {
let _ = use_event_listener_with_options::< let _ = use_event_listener_with_options::<
_, _,
Signal<Option<SendWrapper<web_sys::EventTarget>>>, Signal<Option<web_sys::EventTarget>, LocalStorage>,
web_sys::EventTarget, web_sys::EventTarget,
_, _,
>( >(
@ -414,7 +412,7 @@ where
let _ = use_event_listener_with_options::< let _ = use_event_listener_with_options::<
_, _,
Signal<Option<SendWrapper<web_sys::EventTarget>>>, Signal<Option<web_sys::EventTarget>, LocalStorage>,
web_sys::EventTarget, web_sys::EventTarget,
_, _,
>( >(

View file

@ -146,7 +146,7 @@ pub fn use_service_worker_with_options(
check_for_update: move || { check_for_update: move || {
registration.with(|reg| { registration.with(|reg| {
if let Ok(reg) = reg { if let Ok(reg) = reg {
update_sw.dispatch(reg.clone()) update_sw.dispatch(reg.clone());
} }
}) })
}, },
@ -246,7 +246,7 @@ fn create_action_update() -> Action<
SendWrapper<ServiceWorkerRegistration>, SendWrapper<ServiceWorkerRegistration>,
Result<SendWrapper<ServiceWorkerRegistration>, SendWrapper<JsValue>>, Result<SendWrapper<ServiceWorkerRegistration>, SendWrapper<JsValue>>,
> { > {
Action::new( Action::new_unsync(
move |registration: &SendWrapper<ServiceWorkerRegistration>| { move |registration: &SendWrapper<ServiceWorkerRegistration>| {
let registration = registration.clone(); let registration = registration.clone();
async move { async move {
@ -268,7 +268,7 @@ fn create_action_create_or_update_registration() -> Action<
ServiceWorkerScriptUrl, ServiceWorkerScriptUrl,
Result<SendWrapper<ServiceWorkerRegistration>, SendWrapper<JsValue>>, Result<SendWrapper<ServiceWorkerRegistration>, SendWrapper<JsValue>>,
> { > {
Action::new(move |script_url: &ServiceWorkerScriptUrl| { Action::new_unsync(move |script_url: &ServiceWorkerScriptUrl| {
let script_url = script_url.0.to_owned(); let script_url = script_url.0.to_owned();
async move { async move {
if let Some(navigator) = use_window().navigator() { if let Some(navigator) = use_window().navigator() {
@ -287,7 +287,7 @@ fn create_action_create_or_update_registration() -> Action<
/// A leptos action which asynchronously fetches the current ServiceWorkerRegistration. /// A leptos action which asynchronously fetches the current ServiceWorkerRegistration.
fn create_action_get_registration( fn create_action_get_registration(
) -> Action<(), Result<SendWrapper<ServiceWorkerRegistration>, SendWrapper<JsValue>>> { ) -> Action<(), Result<SendWrapper<ServiceWorkerRegistration>, SendWrapper<JsValue>>> {
Action::new(move |(): &()| async move { Action::new_unsync(move |(): &()| async move {
if let Some(navigator) = use_window().navigator() { if let Some(navigator) = use_window().navigator() {
js_fut!(navigator.service_worker().get_registration()) js_fut!(navigator.service_worker().get_registration())
.await .await

View file

@ -78,7 +78,7 @@ pub fn use_sorted<S, I, T>(iterable: S) -> Signal<I>
where where
S: Into<MaybeSignal<I>>, S: Into<MaybeSignal<I>>,
T: Ord, T: Ord,
I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync, I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync + 'static,
{ {
let iterable = iterable.into(); let iterable = iterable.into();
@ -93,7 +93,7 @@ where
pub fn use_sorted_by<S, I, T, F>(iterable: S, cmp_fn: F) -> Signal<I> pub fn use_sorted_by<S, I, T, F>(iterable: S, cmp_fn: F) -> Signal<I>
where where
S: Into<MaybeSignal<I>>, S: Into<MaybeSignal<I>>,
I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync, I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync + 'static,
F: FnMut(&T, &T) -> Ordering + Clone + Send + Sync + 'static, F: FnMut(&T, &T) -> Ordering + Clone + Send + Sync + 'static,
{ {
let iterable = iterable.into(); let iterable = iterable.into();
@ -109,7 +109,7 @@ where
pub fn use_sorted_by_key<S, I, T, K, F>(iterable: S, key_fn: F) -> Signal<I> pub fn use_sorted_by_key<S, I, T, K, F>(iterable: S, key_fn: F) -> Signal<I>
where where
S: Into<MaybeSignal<I>>, S: Into<MaybeSignal<I>>,
I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync, I: DerefMut<Target = [T]> + Clone + PartialEq + Send + Sync + 'static,
K: Ord, K: Ord,
F: FnMut(&T) -> K + Clone + Send + Sync + 'static, F: FnMut(&T) -> K + Clone + Send + Sync + 'static,
{ {

View file

@ -2,7 +2,6 @@ use crate::core::MaybeRwSignal;
use cfg_if::cfg_if; use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::*; use leptos::prelude::*;
use send_wrapper::SendWrapper;
use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen::{JsCast, JsValue};
/// Reactive [`mediaDevices.getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) streaming. /// Reactive [`mediaDevices.getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) streaming.
@ -60,8 +59,7 @@ pub fn use_user_media_with_options(
let (enabled, set_enabled) = enabled.into_signal(); let (enabled, set_enabled) = enabled.into_signal();
let (stream, set_stream) = let (stream, set_stream) = signal_local(None::<Result<web_sys::MediaStream, JsValue>>);
signal(None::<Result<SendWrapper<web_sys::MediaStream>, SendWrapper<JsValue>>>);
let _start = move || async move { let _start = move || async move {
cfg_if! { if #[cfg(not(feature = "ssr"))] { cfg_if! { if #[cfg(not(feature = "ssr"))] {
@ -69,10 +67,7 @@ pub fn use_user_media_with_options(
return; return;
} }
let stream = create_media(video, audio) let stream = create_media(video, audio).await;
.await
.map(SendWrapper::new)
.map_err(SendWrapper::new);
set_stream.update(|s| *s = Some(stream)); set_stream.update(|s| *s = Some(stream));
} else { } else {
@ -192,7 +187,7 @@ where
/// Initially this is `None` until `start` resolved successfully. /// Initially this is `None` until `start` resolved successfully.
/// In case the stream couldn't be started, for example because the user didn't grant permission, /// In case the stream couldn't be started, for example because the user didn't grant permission,
/// this has the value `Some(Err(...))`. /// this has the value `Some(Err(...))`.
pub stream: Signal<Option<Result<SendWrapper<web_sys::MediaStream>, SendWrapper<JsValue>>>>, pub stream: Signal<Option<Result<web_sys::MediaStream, JsValue>>, LocalStorage>,
/// Starts the screen streaming. Triggers the ask for permission if not already granted. /// Starts the screen streaming. Triggers the ask for permission if not already granted.
pub start: StartFn, pub start: StartFn,

View file

@ -2,7 +2,6 @@ use crate::{use_supported, use_window};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder; use default_struct_builder::DefaultBuilder;
use leptos::prelude::{wrappers::read::Signal, *}; use leptos::prelude::{wrappers::read::Signal, *};
use send_wrapper::SendWrapper;
use std::rc::Rc; use std::rc::Rc;
/// Reactive [Notification API](https://developer.mozilla.org/en-US/docs/Web/API/Notification). /// Reactive [Notification API](https://developer.mozilla.org/en-US/docs/Web/API/Notification).
@ -52,7 +51,7 @@ pub fn use_web_notification_with_options(
) -> UseWebNotificationReturn<impl Fn(ShowOptions) + Clone, impl Fn() + Clone> { ) -> UseWebNotificationReturn<impl Fn(ShowOptions) + Clone, impl Fn() + Clone> {
let is_supported = use_supported(browser_supports_notifications); let is_supported = use_supported(browser_supports_notifications);
let (notification, set_notification) = signal(None::<SendWrapper<web_sys::Notification>>); let (notification, set_notification) = signal_local(None::<web_sys::Notification>);
let (permission, set_permission) = signal(NotificationPermission::default()); let (permission, set_permission) = signal(NotificationPermission::default());
@ -149,7 +148,7 @@ pub fn use_web_notification_with_options(
notification_value.set_onerror(Some(on_error_closure.unchecked_ref())); notification_value.set_onerror(Some(on_error_closure.unchecked_ref()));
notification_value.set_onshow(Some(on_show_closure.unchecked_ref())); notification_value.set_onshow(Some(on_show_closure.unchecked_ref()));
set_notification.set(Some(SendWrapper::new(notification_value))); set_notification.set(Some(notification_value));
}); });
} }
}; };
@ -462,7 +461,7 @@ where
CloseFn: Fn() + Clone, CloseFn: Fn() + Clone,
{ {
pub is_supported: Signal<bool>, pub is_supported: Signal<bool>,
pub notification: Signal<Option<SendWrapper<web_sys::Notification>>>, pub notification: Signal<Option<web_sys::Notification>, LocalStorage>,
pub show: ShowFn, pub show: ShowFn,
pub close: CloseFn, pub close: CloseFn,
pub permission: Signal<NotificationPermission>, pub permission: Signal<NotificationPermission>,

View file

@ -2,7 +2,6 @@
use cfg_if::cfg_if; use cfg_if::cfg_if;
use leptos::{leptos_dom::helpers::TimeoutHandle, prelude::*}; use leptos::{leptos_dom::helpers::TimeoutHandle, prelude::*};
use send_wrapper::SendWrapper;
use std::sync::{atomic::AtomicBool, Arc}; use std::sync::{atomic::AtomicBool, Arc};
use std::time::Duration; use std::time::Duration;
use thiserror::Error; use thiserror::Error;
@ -284,7 +283,7 @@ where
let (ready_state, set_ready_state) = signal(ConnectionReadyState::Closed); let (ready_state, set_ready_state) = signal(ConnectionReadyState::Closed);
let (message, set_message) = signal(None); let (message, set_message) = signal(None);
let ws_ref: StoredValue<Option<SendWrapper<WebSocket>>> = StoredValue::new(None); let ws_ref: StoredValue<Option<WebSocket>, _> = StoredValue::new_local(None);
let reconnect_timer_ref: StoredValue<Option<TimeoutHandle>> = StoredValue::new(None); let reconnect_timer_ref: StoredValue<Option<TimeoutHandle>> = StoredValue::new(None);
@ -305,9 +304,7 @@ where
&& !reconnect_limit.is_exceeded_by(reconnect_times_ref.get_value()) && !reconnect_limit.is_exceeded_by(reconnect_times_ref.get_value())
&& ws_ref && ws_ref
.get_value() .get_value()
.map_or(false, |ws: SendWrapper<WebSocket>| { .map_or(false, |ws: WebSocket| ws.ready_state() != WebSocket::OPEN)
ws.ready_state() != WebSocket::OPEN
})
{ {
reconnect_timer_ref.set_value( reconnect_timer_ref.set_value(
set_timeout_with_handle( set_timeout_with_handle(
@ -525,7 +522,7 @@ where
onclose_closure.forget(); onclose_closure.forget();
} }
ws_ref.set_value(Some(SendWrapper::new(web_socket))); ws_ref.set_value(Some(web_socket));
})) }))
}); });
} }
@ -721,7 +718,7 @@ where
/// Latest message received from `WebSocket`. /// Latest message received from `WebSocket`.
pub message: Signal<Option<T>>, pub message: Signal<Option<T>>,
/// The `WebSocket` instance. /// The `WebSocket` instance.
pub ws: Option<SendWrapper<WebSocket>>, pub ws: Option<WebSocket>,
/// Opens the `WebSocket` connection /// Opens the `WebSocket` connection
pub open: OpenFn, pub open: OpenFn,
/// Closes the `WebSocket` connection /// Closes the `WebSocket` connection