Added more Send + Sync bounds and SendWrappers

This commit is contained in:
CorvusPrudens 2024-07-23 11:36:12 -06:00
parent 3433fc6608
commit 9866ac6231
14 changed files with 202 additions and 131 deletions

View file

@ -4,8 +4,10 @@ use cfg_if::cfg_if;
use leptos::html::{ElementType, HtmlElement};
use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::marker::PhantomData;
use std::ops::Deref;
use wasm_bindgen::JsCast;
/// Used as an argument type to make it easily possible to pass either
/// * a `web_sys` element that implements `E` (for example `EventTarget` or `Element`),
@ -58,9 +60,9 @@ impl<T, E> With for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
type Value = Vec<Option<T>>;
type Value = Vec<Option<SendWrapper<T>>>;
fn with<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> O {
fn with<O>(&self, f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O) -> O {
match self {
Self::Static(v) => f(v),
Self::Dynamic(s) => s.with(f),
@ -68,7 +70,7 @@ where
}
}
fn try_with<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> Option<O> {
fn try_with<O>(&self, f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O) -> Option<O> {
match self {
Self::Static(v) => Some(f(v)),
Self::Dynamic(s) => s.try_with(f),
@ -81,9 +83,9 @@ impl<T, E> WithUntracked for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
type Value = Vec<Option<T>>;
type Value = Vec<Option<SendWrapper<T>>>;
fn with_untracked<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> O {
fn with_untracked<O>(&self, f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O) -> O {
match self {
Self::Static(t) => f(t),
Self::Dynamic(s) => s.with_untracked(f),
@ -91,7 +93,10 @@ where
}
}
fn try_with_untracked<O>(&self, f: impl FnOnce(&Vec<Option<T>>) -> O) -> Option<O> {
fn try_with_untracked<O>(
&self,
f: impl FnOnce(&Vec<Option<SendWrapper<T>>>) -> O,
) -> Option<O> {
match self {
Self::Static(t) => Some(f(t)),
Self::Dynamic(s) => s.try_with_untracked(f),
@ -107,7 +112,7 @@ where
T: Into<E> + Clone + 'static,
{
fn from(value: T) -> Self {
ElementsMaybeSignal::Static(vec![Some(value)])
ElementsMaybeSignal::Static(vec![Some(SendWrapper::new(value))])
}
}
@ -116,7 +121,7 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: Option<T>) -> Self {
ElementsMaybeSignal::Static(vec![target])
ElementsMaybeSignal::Static(vec![target.map(SendWrapper::new)])
}
}
@ -127,7 +132,7 @@ macro_rules! impl_from_deref_option {
E: From<$ty2> + 'static,
{
fn from(value: $ty) -> Self {
Self::Static(vec![(*value).clone()])
Self::Static(vec![(*value).clone().map(SendWrapper::new)])
}
}
};
@ -185,7 +190,7 @@ macro_rules! impl_from_signal_string {
let mut list = Vec::with_capacity(node_list.length() as usize);
for i in 0..node_list.length() {
let node = node_list.get(i).expect("checked the range");
list.push(Some(node));
list.push(Some(SendWrapper::new(node)));
}
list
} else {
@ -209,8 +214,8 @@ impl_from_signal_string!(Memo<String>);
impl_from_signal_string!(Signal<&str>);
impl_from_signal_string!(ReadSignal<&str>);
impl_from_signal_string!(RwSignal<&str>);
impl_from_signal_string!(Memo<&str>);
impl_from_signal_string!(RwSignal<&'static str>);
impl_from_signal_string!(Memo<&'static str>);
// From single signal ///////////////////////////////////////////////////////////////
@ -227,10 +232,10 @@ macro_rules! impl_from_signal_option {
};
}
impl_from_signal_option!(Signal<Option<T>>);
impl_from_signal_option!(ReadSignal<Option<T>>);
impl_from_signal_option!(RwSignal<Option<T>>);
impl_from_signal_option!(Memo<Option<T>>);
impl_from_signal_option!(Signal<Option<SendWrapper<T>>>);
impl_from_signal_option!(ReadSignal<Option<SendWrapper<T>>>);
impl_from_signal_option!(RwSignal<Option<SendWrapper<T>>>);
impl_from_signal_option!(Memo<Option<SendWrapper<T>>>);
macro_rules! impl_from_signal {
($ty:ty) => {
@ -245,10 +250,10 @@ macro_rules! impl_from_signal {
};
}
impl_from_signal!(Signal<T>);
impl_from_signal!(ReadSignal<T>);
impl_from_signal!(RwSignal<T>);
impl_from_signal!(Memo<T>);
impl_from_signal!(Signal<SendWrapper<T>>);
impl_from_signal!(ReadSignal<SendWrapper<T>>);
impl_from_signal!(RwSignal<SendWrapper<T>>);
impl_from_signal!(Memo<SendWrapper<T>>);
// From single NodeRef //////////////////////////////////////////////////////////////
@ -257,13 +262,13 @@ macro_rules! impl_from_node_ref {
impl<R> From<NodeRef<R>> for ElementsMaybeSignal<$ty, $ty>
where
R: ElementType + Clone + 'static,
R::Output: JsCast + Into<$ty> + Clone + 'static,
{
fn from(node_ref: NodeRef<R>) -> Self {
Self::Dynamic(Signal::derive(move || {
vec![node_ref.get().map(move |el| {
let el = el.into_any();
let el: $ty = el.deref().clone().into();
el
let el: $ty = el.clone().into();
SendWrapper::new(el)
})]
}))
}
@ -276,23 +281,23 @@ impl_from_node_ref!(web_sys::Element);
// From single leptos::html::HTMLElement ///////////////////////////////////////////
macro_rules! impl_from_html_element {
($ty:ty) => {
impl<E, At, Ch, Rndr> From<HtmlElement<E, At, Ch, Rndr>> for ElementsMaybeSignal<$ty, $ty>
where
E: ElementType,
E::Output: std::ops::Deref<Target = $ty>,
{
fn from(value: HtmlElement<E, At, Ch, Rndr>) -> Self {
let el: &$ty = value.deref();
Self::Static(vec![Some(el.clone())])
}
}
};
}
impl_from_html_element!(web_sys::EventTarget);
impl_from_html_element!(web_sys::Element);
// macro_rules! impl_from_html_element {
// ($ty:ty) => {
// impl<E, At, Ch, Rndr> From<HtmlElement<E, At, Ch, Rndr>> for ElementsMaybeSignal<$ty, $ty>
// where
// E: ElementType,
// E::Output: std::ops::Deref<Target = $ty>,
// {
// fn from(value: HtmlElement<E, At, Ch, Rndr>) -> Self {
// let el: &$ty = value.deref();
// Self::Static(vec![Some(el.clone())])
// }
// }
// };
// }
//
// impl_from_html_element!(web_sys::EventTarget);
// impl_from_html_element!(web_sys::Element);
// From multiple static elements //////////////////////////////////////////////////////
@ -301,7 +306,12 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: &[T]) -> Self {
Self::Static(target.iter().map(|t| Some(t.clone())).collect())
Self::Static(
target
.iter()
.map(|t| Some(SendWrapper::new(t.clone())))
.collect(),
)
}
}
@ -310,7 +320,12 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: &[Option<T>]) -> Self {
Self::Static(target.to_vec())
Self::Static(
target
.iter()
.map(|t| t.clone().map(SendWrapper::new))
.collect(),
)
}
}
@ -319,7 +334,12 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: Vec<T>) -> Self {
Self::Static(target.iter().map(|t| Some(t.clone())).collect())
Self::Static(
target
.iter()
.map(|t| Some(SendWrapper::new(t.clone())))
.collect(),
)
}
}
@ -328,7 +348,12 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: Vec<Option<T>>) -> Self {
Self::Static(target.to_vec())
Self::Static(
target
.into_iter()
.map(|t| t.map(SendWrapper::new))
.collect(),
)
}
}
@ -337,7 +362,12 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: [T; C]) -> Self {
Self::Static(target.iter().map(|t| Some(t.clone())).collect())
Self::Static(
target
.into_iter()
.map(|t| Some(SendWrapper::new(t)))
.collect(),
)
}
}
@ -346,7 +376,12 @@ where
T: Into<E> + Clone + 'static,
{
fn from(target: [Option<T>; C]) -> Self {
Self::Static(target.to_vec())
Self::Static(
target
.into_iter()
.map(|t| t.map(SendWrapper::new))
.collect(),
)
}
}
@ -357,7 +392,7 @@ macro_rules! impl_from_strings_inner {
Self::Static(
$target
.iter()
.filter_map(|sel: &$str_ty| -> Option<Vec<Option<$el_ty>>> {
.filter_map(|sel: &$str_ty| -> Option<Vec<Option<SendWrapper<$el_ty>>>> {
cfg_if! { if #[cfg(feature = "ssr")] {
let _ = sel;
None
@ -368,7 +403,7 @@ macro_rules! impl_from_strings_inner {
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));
list.push(Some(SendWrapper::new(node)));
}
Some(list)
@ -417,33 +452,33 @@ impl_from_strings!(web_sys::EventTarget, String);
// From signal of vec ////////////////////////////////////////////////////////////////
impl<T, E> From<Signal<Vec<T>>> for ElementsMaybeSignal<T, E>
impl<T, E> From<Signal<Vec<SendWrapper<T>>>> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(signal: Signal<Vec<T>>) -> Self {
fn from(signal: Signal<Vec<SendWrapper<T>>>) -> Self {
Self::Dynamic(Signal::derive(move || {
signal.get().into_iter().map(|t| Some(t)).collect()
}))
}
}
impl<T, E> From<Signal<Vec<Option<T>>>> for ElementsMaybeSignal<T, E>
impl<T, E> From<Signal<Vec<Option<SendWrapper<T>>>>> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(target: Signal<Vec<Option<T>>>) -> Self {
fn from(target: Signal<Vec<Option<SendWrapper<T>>>>) -> Self {
Self::Dynamic(target)
}
}
// From multiple signals //////////////////////////////////////////////////////////////
impl<T, E> From<&[Signal<T>]> for ElementsMaybeSignal<T, E>
impl<T, E> From<&[Signal<SendWrapper<T>>]> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(list: &[Signal<T>]) -> Self {
fn from(list: &[Signal<SendWrapper<T>>]) -> Self {
let list = list.to_vec();
Self::Dynamic(Signal::derive(move || {
@ -452,11 +487,11 @@ where
}
}
impl<T, E> From<&[Signal<Option<T>>]> for ElementsMaybeSignal<T, E>
impl<T, E> From<&[Signal<Option<SendWrapper<T>>>]> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(list: &[Signal<Option<T>>]) -> Self {
fn from(list: &[Signal<Option<SendWrapper<T>>>]) -> Self {
let list = list.to_vec();
Self::Dynamic(Signal::derive(move || {
@ -465,11 +500,11 @@ where
}
}
impl<T, E> From<Vec<Signal<T>>> for ElementsMaybeSignal<T, E>
impl<T, E> From<Vec<Signal<SendWrapper<T>>>> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(list: Vec<Signal<T>>) -> Self {
fn from(list: Vec<Signal<SendWrapper<T>>>) -> Self {
let list = list.clone();
Self::Dynamic(Signal::derive(move || {
@ -478,11 +513,11 @@ where
}
}
impl<T, E> From<Vec<Signal<Option<T>>>> for ElementsMaybeSignal<T, E>
impl<T, E> From<Vec<Signal<Option<SendWrapper<T>>>>> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(list: Vec<Signal<Option<T>>>) -> Self {
fn from(list: Vec<Signal<Option<SendWrapper<T>>>>) -> Self {
let list = list.clone();
Self::Dynamic(Signal::derive(move || {
@ -491,11 +526,11 @@ where
}
}
impl<T, E, const C: usize> From<[Signal<T>; C]> for ElementsMaybeSignal<T, E>
impl<T, E, const C: usize> From<[Signal<SendWrapper<T>>; C]> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(list: [Signal<T>; C]) -> Self {
fn from(list: [Signal<SendWrapper<T>>; C]) -> Self {
let list = list.to_vec();
Self::Dynamic(Signal::derive(move || {
@ -504,11 +539,11 @@ where
}
}
impl<T, E, const C: usize> From<[Signal<Option<T>>; C]> for ElementsMaybeSignal<T, E>
impl<T, E, const C: usize> From<[Signal<Option<SendWrapper<T>>>; C]> for ElementsMaybeSignal<T, E>
where
T: Into<E> + Clone + 'static,
{
fn from(list: [Signal<Option<T>>; C]) -> Self {
fn from(list: [Signal<Option<SendWrapper<T>>>; C]) -> Self {
let list = list.to_vec();
Self::Dynamic(Signal::derive(move || {
@ -526,9 +561,8 @@ macro_rules! impl_from_multi_node_ref_inner {
.iter()
.map(|node_ref| {
node_ref.get().map(move |el| {
let el = el.into_any();
let el: $ty = el.deref().clone().into();
el
let el: $ty = el.clone().into();
SendWrapper::new(el)
})
})
.collect()
@ -541,6 +575,7 @@ macro_rules! impl_from_multi_node_ref {
impl<R> From<&[NodeRef<R>]> for ElementsMaybeSignal<$ty, $ty>
where
R: ElementType + Clone + 'static,
R::Output: JsCast + Into<$ty> + Clone + 'static,
{
fn from(node_refs: &[NodeRef<R>]) -> Self {
let node_refs = node_refs.to_vec();
@ -551,6 +586,7 @@ macro_rules! impl_from_multi_node_ref {
impl<R, const C: usize> From<[NodeRef<R>; C]> for ElementsMaybeSignal<$ty, $ty>
where
R: ElementType + Clone + 'static,
R::Output: JsCast + Into<$ty> + Clone + 'static,
{
fn from(node_refs: [NodeRef<R>; C]) -> Self {
let node_refs = node_refs.to_vec();
@ -561,6 +597,7 @@ macro_rules! impl_from_multi_node_ref {
impl<R> From<Vec<NodeRef<R>>> for ElementsMaybeSignal<$ty, $ty>
where
R: ElementType + Clone + 'static,
R::Output: JsCast + Into<$ty> + Clone + 'static,
{
fn from(node_refs: Vec<NodeRef<R>>) -> Self {
let node_refs = node_refs.clone();

View file

@ -50,26 +50,38 @@ impl<T> From<Signal<T>> for MaybeRwSignal<T> {
}
}
impl<T> From<ReadSignal<T>> for MaybeRwSignal<T> {
impl<T> From<ReadSignal<T>> for MaybeRwSignal<T>
where
T: Send + Sync,
{
fn from(s: ReadSignal<T>) -> Self {
Self::DynamicRead(s.into())
}
}
impl<T> From<Memo<T>> for MaybeRwSignal<T> {
impl<T> From<Memo<T>> for MaybeRwSignal<T>
where
T: Send + Sync,
{
fn from(s: Memo<T>) -> Self {
Self::DynamicRead(s.into())
}
}
impl<T> From<RwSignal<T>> for MaybeRwSignal<T> {
impl<T> From<RwSignal<T>> for MaybeRwSignal<T>
where
T: Send + Sync,
{
fn from(s: RwSignal<T>) -> 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
T: Send + Sync,
{
fn from(s: (ReadSignal<T>, WriteSignal<T>)) -> Self {
Self::DynamicRw(s.0.into(), s.1)
}
@ -87,7 +99,10 @@ impl From<&str> for MaybeRwSignal<String> {
}
}
impl<T: Clone> MaybeRwSignal<T> {
impl<T: Clone> MaybeRwSignal<T>
where
T: Send + Sync,
{
pub fn into_signal(self) -> (Signal<T>, WriteSignal<T>) {
match self {
Self::DynamicRead(s) => {

View file

@ -22,7 +22,7 @@ where
impl<T> Default for UseRwSignal<T>
where
T: Default,
T: Default + Send + Sync,
{
fn default() -> Self {
Self::Combined(Default::default())
@ -47,7 +47,10 @@ impl<T> DefinedAt for UseRwSignal<T> {
}
}
impl<T> With for UseRwSignal<T> {
impl<T> With for UseRwSignal<T>
where
T: Send + Sync,
{
type Value = T;
fn with<R>(&self, f: impl FnOnce(&T) -> R) -> R {
@ -65,7 +68,10 @@ impl<T> With for UseRwSignal<T> {
}
}
impl<T> WithUntracked for UseRwSignal<T> {
impl<T> WithUntracked for UseRwSignal<T>
where
T: Send + Sync,
{
type Value = T;
fn with_untracked<R>(&self, f: impl FnOnce(&T) -> R) -> R {

View file

@ -25,11 +25,11 @@ mod is_none;
mod is_ok;
mod is_some;
mod on_click_outside;
mod use_user_media;
mod signal_debounced;
mod signal_throttled;
mod sync_signal;
mod use_active_element;
mod use_user_media;
// mod use_active_element;
mod use_breakpoints;
mod use_broadcast_channel;
mod use_color_mode;
@ -91,11 +91,11 @@ pub use is_none::*;
pub use is_ok::*;
pub use is_some::*;
pub use on_click_outside::*;
pub use use_user_media::*;
pub use signal_debounced::*;
pub use signal_throttled::*;
pub use sync_signal::*;
pub use use_active_element::*;
pub use use_user_media::*;
// pub use use_active_element::*;
pub use use_breakpoints::*;
pub use use_broadcast_channel::*;
pub use use_color_mode::*;

View file

@ -7,9 +7,9 @@ macro_rules! use_partial_cmp {
pub fn $fn_name<C, S, N>(container: S) -> Signal<Option<N>>
where
S: Into<MaybeSignal<C>>,
C: 'static,
C: Send + Sync + 'static,
for<'a> &'a C: IntoIterator<Item = &'a N>,
N: PartialOrd + Clone,
N: PartialOrd + Clone + Send + Sync,
{
let container = container.into();
@ -47,8 +47,8 @@ macro_rules! use_simple_math {
$(#[$outer])*
pub fn [<use_ $fn_name>]<S, N>(x: S) -> Signal<N>
where
S: Into<MaybeSignal<N>>,
N: Float,
S: Into<MaybeSignal<N>> + Send + Sync,
N: Float + Send + Sync,
{
let x = x.into();
Signal::derive(move || x.get().$fn_name())

View file

@ -148,7 +148,7 @@ pub fn sync_signal<T>(
right: impl Into<UseRwSignal<T>>,
) -> impl Fn() + Clone
where
T: Clone + PartialEq + 'static,
T: Clone + PartialEq + Send + Sync + 'static,
{
sync_signal_with_options(left, right, SyncSignalOptions::default())
}
@ -160,8 +160,8 @@ pub fn sync_signal_with_options<L, R>(
options: SyncSignalOptions<L, R>,
) -> impl Fn() + Clone
where
L: Clone + PartialEq + 'static,
R: Clone + PartialEq + 'static,
L: Clone + PartialEq + Send + Sync + 'static,
R: Clone + PartialEq + Send + Sync + 'static,
{
let SyncSignalOptions {
immediate,

View file

@ -110,7 +110,7 @@ use std::hash::Hash;
///
/// Since internally this uses [`use_media_query`], which returns always `false` on the server,
/// the returned methods also will return `false`.
pub fn use_breakpoints<K: Eq + Hash + Debug + Clone>(
pub fn use_breakpoints<K: Eq + Hash + Debug + Clone + Send + Sync>(
breakpoints: HashMap<K, u32>,
) -> UseBreakpointsReturn<K> {
UseBreakpointsReturn { breakpoints }
@ -118,7 +118,7 @@ pub fn use_breakpoints<K: Eq + Hash + Debug + Clone>(
/// Return type of [`use_breakpoints`]
#[derive(Clone)]
pub struct UseBreakpointsReturn<K: Eq + Hash + Debug + Clone> {
pub struct UseBreakpointsReturn<K: Eq + Hash + Debug + Clone + Send + Sync> {
breakpoints: HashMap<K, u32>,
}
@ -184,7 +184,7 @@ macro_rules! impl_cmp_reactively {
};
}
impl<K: Eq + Hash + Debug + Clone> UseBreakpointsReturn<K> {
impl<K: Eq + Hash + Debug + Clone + Send + Sync> UseBreakpointsReturn<K> {
fn match_(query: &str) -> bool {
if let Ok(Some(query_list)) = use_window().match_media(query) {
return query_list.matches();

View file

@ -4,6 +4,7 @@ use crate::{
use codee::{CodecError, Decoder, Encoder};
use leptos::ev::messageerror;
use leptos::prelude::*;
use send_wrapper::SendWrapper;
use thiserror::Error;
use wasm_bindgen::JsValue;
@ -80,12 +81,15 @@ pub fn use_broadcast_channel<T, C>(
<C as Decoder<T>>::Error,
>
where
T: Send + Sync,
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
<C as Encoder<T>>::Error: Send + Sync,
<C as Decoder<T>>::Error: Send + Sync,
{
let is_supported = use_supported(|| js!("BroadcastChannel" in &window()));
let (is_closed, set_closed) = signal(false);
let (channel, set_channel) = signal(None::<web_sys::BroadcastChannel>);
let (channel, set_channel) = signal(None::<SendWrapper<web_sys::BroadcastChannel>>);
let (message, set_message) = signal(None::<T>);
let (error, set_error) = signal(
None::<UseBroadcastChannelError<<C as Encoder<T>>::Error, <C as Decoder<T>>::Error>>,
@ -99,7 +103,9 @@ where
channel
.post_message(&msg.into())
.map_err(|err| {
set_error.set(Some(UseBroadcastChannelError::PostMessage(err)))
set_error.set(Some(UseBroadcastChannelError::PostMessage(
SendWrapper::new(err),
)))
})
.ok();
}
@ -124,7 +130,7 @@ where
if is_supported.get_untracked() {
let channel_val = web_sys::BroadcastChannel::new(name).ok();
set_channel.set(channel_val.clone());
set_channel.set(channel_val.clone().map(SendWrapper::new));
if let Some(channel) = channel_val {
let _ = use_event_listener_with_options(
@ -151,7 +157,9 @@ where
channel.clone(),
messageerror,
move |event| {
set_error.set(Some(UseBroadcastChannelError::MessageEvent(event)));
set_error.set(Some(UseBroadcastChannelError::MessageEvent(
SendWrapper::new(event),
)));
},
UseEventListenerOptions::default().passive(true),
);
@ -188,7 +196,7 @@ where
pub is_supported: Signal<bool>,
/// The broadcast channel that is wrapped by this function
pub channel: Signal<Option<web_sys::BroadcastChannel>>,
pub channel: Signal<Option<SendWrapper<web_sys::BroadcastChannel>>>,
/// Latest message received from the channel
pub message: Signal<Option<T>>,
@ -209,9 +217,9 @@ where
#[derive(Debug, Error)]
pub enum UseBroadcastChannelError<E, D> {
#[error("failed to post message")]
PostMessage(JsValue),
PostMessage(SendWrapper<JsValue>),
#[error("channel message error")]
MessageEvent(web_sys::MessageEvent),
MessageEvent(SendWrapper<web_sys::MessageEvent>),
#[error("failed to (de)encode value")]
Codec(CodecError<E, D>),
#[error("received value is not a string")]

View file

@ -36,10 +36,10 @@ use leptos::prelude::wrappers::read::Signal;
pub fn use_device_orientation() -> UseDeviceOrientationReturn {
cfg_if! { if #[cfg(feature = "ssr")] {
let is_supported = Signal::derive(|| false);
let absolute = || false;
let alpha = || None;
let beta = || None;
let gamma = || None;
let absolute = Signal::derive(|| false);
let alpha = Signal::derive(|| None);
let beta = Signal::derive(|| None);
let gamma = Signal::derive(|| None);
} else {
use leptos::prelude::*;
use crate::{use_event_listener_with_options, UseEventListenerOptions, use_supported, js};

View file

@ -5,8 +5,9 @@ use leptos::ev::{pointerdown, pointermove, pointerup};
use leptos::prelude::diagnostics::SpecialNonReactiveZone;
use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::Arc;
use wasm_bindgen::JsCast;
use web_sys::PointerEvent;
@ -92,11 +93,12 @@ where
let target = target.into();
let dragging_handle = if let Some(handle) = handle {
let handle = (handle).into();
Signal::derive(move || handle.get().map(|handle| handle.into()))
// let handle = Signal::derive(|| SendWrapper::new(handle));
let handle: ElementMaybeSignal<_, _> = handle.into();
Signal::derive(move || handle.get().map(|handle| SendWrapper::new(handle.into())))
} else {
let target = target.clone();
Signal::derive(move || target.get().map(|target| target.into()))
Signal::derive(move || target.get().map(|target| SendWrapper::new(target.into())))
};
let (position, set_position) = initial_value.into_signal();
@ -280,13 +282,13 @@ where
initial_value: MaybeRwSignal<Position>,
/// Callback when the dragging starts. Return `false` to prevent dragging.
on_start: Rc<dyn Fn(UseDraggableCallbackArgs) -> bool>,
on_start: Arc<dyn Fn(UseDraggableCallbackArgs) -> bool + Send + Sync>,
/// Callback during dragging.
on_move: Rc<dyn Fn(UseDraggableCallbackArgs)>,
on_move: Arc<dyn Fn(UseDraggableCallbackArgs) + Send + Sync>,
/// Callback when dragging end.
on_end: Rc<dyn Fn(UseDraggableCallbackArgs)>,
on_end: Arc<dyn Fn(UseDraggableCallbackArgs) + Send + Sync>,
#[builder(skip)]
_marker1: PhantomData<DragT>,
@ -306,9 +308,9 @@ impl Default
handle: None,
pointer_types: vec![PointerType::Mouse, PointerType::Touch, PointerType::Pen],
initial_value: MaybeRwSignal::default(),
on_start: Rc::new(|_| true),
on_move: Rc::new(|_| {}),
on_end: Rc::new(|_| {}),
on_start: Arc::new(|_| true),
on_move: Arc::new(|_| {}),
on_end: Arc::new(|_| {}),
_marker1: PhantomData,
_marker2: PhantomData,
}

View file

@ -3,8 +3,9 @@ use cfg_if::cfg_if;
use default_struct_builder::DefaultBuilder;
use leptos::prelude::wrappers::read::Signal;
use leptos::prelude::*;
use send_wrapper::SendWrapper;
use std::fmt::{Debug, Formatter};
use std::rc::Rc;
use std::sync::Arc;
cfg_if! { if #[cfg(not(feature = "ssr"))] {
use crate::use_event_listener;
@ -73,7 +74,7 @@ where
T: Into<web_sys::EventTarget> + Clone + 'static,
{
let (is_over_drop_zone, set_over_drop_zone) = signal(false);
let (files, set_files) = signal(Vec::<web_sys::File>::new());
let (files, set_files) = signal(Vec::<SendWrapper<web_sys::File>>::new());
#[cfg(not(feature = "ssr"))]
{
@ -176,22 +177,22 @@ where
#[cfg_attr(feature = "ssr", allow(dead_code))]
pub struct UseDropZoneOptions {
/// Event handler for the [`drop`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event) event
on_drop: Rc<dyn Fn(UseDropZoneEvent)>,
on_drop: Arc<dyn Fn(UseDropZoneEvent) + Send + Sync>,
/// Event handler for the [`dragenter`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragenter_event) event
on_enter: Rc<dyn Fn(UseDropZoneEvent)>,
on_enter: Arc<dyn Fn(UseDropZoneEvent) + Send + Sync>,
/// Event handler for the [`dragleave`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragleave_event) event
on_leave: Rc<dyn Fn(UseDropZoneEvent)>,
on_leave: Arc<dyn Fn(UseDropZoneEvent) + Send + Sync>,
/// Event handler for the [`dragover`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragover_event) event
on_over: Rc<dyn Fn(UseDropZoneEvent)>,
on_over: Arc<dyn Fn(UseDropZoneEvent) + Send + Sync>,
}
impl Default for UseDropZoneOptions {
fn default() -> Self {
Self {
on_drop: Rc::new(|_| {}),
on_enter: Rc::new(|_| {}),
on_leave: Rc::new(|_| {}),
on_over: Rc::new(|_| {}),
on_drop: Arc::new(|_| {}),
on_enter: Arc::new(|_| {}),
on_leave: Arc::new(|_| {}),
on_over: Arc::new(|_| {}),
}
}
}
@ -214,7 +215,7 @@ pub struct UseDropZoneEvent {
/// Return type of [`use_drop_zone`].
pub struct UseDropZoneReturn {
/// Files being handled
pub files: Signal<Vec<web_sys::File>>,
pub files: Signal<Vec<SendWrapper<web_sys::File>>>,
/// Whether the files (dragged by the pointer) are over the drop zone
pub is_over_drop_zone: Signal<bool>,
}

View file

@ -259,9 +259,9 @@ where
for event_name in named_events.clone() {
let _ = use_event_listener(
es.clone(),
leptos::ev::Custom::<ev::Event>::new(event_name),
leptos::ev::Custom::<leptos::ev::Event>::new(event_name),
move |e| {
set_event.set(Some(e.clone()));
set_event.set(Some(SendWrapper::new(e.clone())));
let data_string = js!(e["data"]).ok().and_then(|d| d.as_string());
set_data_from_string(data_string);
},

View file

@ -303,9 +303,11 @@ where
Some(Arc::new(move || {
if !manually_closed_ref.get_value()
&& !reconnect_limit.is_exceeded_by(reconnect_times_ref.get_value())
&& ws_ref.get_value().map_or(false, |ws: SendWrapper<WebSocket>| {
ws.ready_state() != WebSocket::OPEN
})
&& ws_ref
.get_value()
.map_or(false, |ws: SendWrapper<WebSocket>| {
ws.ready_state() != WebSocket::OPEN
})
{
reconnect_timer_ref.set_value(
set_timeout_with_handle(
@ -417,7 +419,7 @@ where
on_message(&val);
#[cfg(debug_assertions)]
drop(zone);
drop(zone);
set_message.set(Some(val));
}
@ -628,7 +630,7 @@ impl ReconnectLimit {
}
}
type ArcFnBytes = Arc<dyn Fn(&[u8])>;
type ArcFnBytes = Arc<dyn Fn(&[u8]) + Send + Sync>;
/// Options for [`use_websocket_with_options`].
#[derive(DefaultBuilder)]
@ -644,7 +646,7 @@ where
/// `WebSocket` message callback for text.
on_message_raw: Arc<dyn Fn(&str) + Send + Sync>,
/// `WebSocket` message callback for binary.
on_message_raw_bytes: ArcFnBytes + Send + Sync,
on_message_raw_bytes: ArcFnBytes,
/// `WebSocket` error callback.
#[builder(skip)]
on_error: Arc<dyn Fn(UseWebSocketError<E, D>) + Send + Sync>,

View file

@ -15,7 +15,7 @@ macro_rules! signal_filtered {
) -> Signal<T>
where
S: Into<Signal<T>>,
T: Clone + 'static,
T: Clone + Send + Sync + 'static,
{
[<signal_ $filter_name d_with_options>](value, ms, [<$filter_name:camel Options>]::default())
}
@ -36,7 +36,7 @@ macro_rules! signal_filtered {
) -> Signal<T>
where
S: Into<Signal<T>>,
T: Clone + 'static,
T: Clone + Send + Sync + 'static,
{
let value = value.into();
let ms = ms.into();