From 3433fc660812ceb40e79e82e3e94c0d85c08561a Mon Sep 17 00:00:00 2001 From: CorvusPrudens Date: Tue, 23 Jul 2024 10:50:20 -0600 Subject: [PATCH] Reintroduced proper watch --- src/core/element_maybe_signal.rs | 255 ++++++++++++++++-------------- src/core/elements_maybe_signal.rs | 148 ++++++++--------- src/use_cycle_list.rs | 3 +- src/use_interval_fn.rs | 4 +- src/watch_with_options.rs | 6 +- 5 files changed, 224 insertions(+), 192 deletions(-) diff --git a/src/core/element_maybe_signal.rs b/src/core/element_maybe_signal.rs index 27e4e6b..780ed55 100644 --- a/src/core/element_maybe_signal.rs +++ b/src/core/element_maybe_signal.rs @@ -1,10 +1,11 @@ use crate::{UseDocument, UseWindow}; use cfg_if::cfg_if; -use leptos::html::HtmlElement; +use leptos::html::{CreateElement, ElementType}; 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`, `Element` or `HtmlElement`), @@ -17,9 +18,9 @@ pub enum ElementMaybeSignal where T: Into + Clone + 'static, { - Static(Option), - Dynamic(Signal>), - _Phantom(PhantomData), + Static(Option>), + Dynamic(Signal>>), + _Phantom(PhantomData E>), } impl Default for ElementMaybeSignal @@ -61,16 +62,28 @@ where fn with(&self, f: impl FnOnce(&Option) -> O) -> O { match self { - Self::Static(t) => f(t), - Self::Dynamic(s) => s.with(f), + Self::Static(t) => { + let value = t.as_ref().map(|t| t.clone().take()); + f(&value) + } + Self::Dynamic(s) => s.with(|s| { + let value = s.as_ref().map(|s| s.clone().take()); + f(&value) + }), _ => unreachable!(), } } fn try_with(&self, f: impl FnOnce(&Option) -> O) -> Option { match self { - Self::Static(t) => Some(f(t)), - Self::Dynamic(s) => s.try_with(f), + Self::Static(t) => { + let value = t.as_ref().map(|t| t.clone().take()); + Some(f(&value)) + } + Self::Dynamic(s) => s.try_with(|s| { + let value = s.as_ref().map(|s| s.clone().take()); + f(&value) + }), _ => unreachable!(), } } @@ -84,16 +97,28 @@ where fn with_untracked(&self, f: impl FnOnce(&Option) -> O) -> O { match self { - Self::Static(t) => f(t), - Self::Dynamic(s) => s.with_untracked(f), + Self::Static(t) => { + let value = t.as_ref().map(|t| t.clone().take()); + f(&value) + } + Self::Dynamic(s) => s.with_untracked(|s| { + let value = s.as_ref().map(|s| s.clone().take()); + f(&value) + }), _ => unreachable!(), } } fn try_with_untracked(&self, f: impl FnOnce(&Option) -> O) -> Option { match self { - Self::Static(t) => Some(f(t)), - Self::Dynamic(s) => s.try_with_untracked(f), + Self::Static(t) => { + let value = t.as_ref().map(|t| t.clone().take()); + Some(f(&value)) + } + Self::Dynamic(s) => s.try_with_untracked(|s| { + let value = s.as_ref().map(|s| s.clone().take()); + f(&value) + }), _ => unreachable!(), } } @@ -106,7 +131,7 @@ where T: Into + Clone + 'static, { fn from(value: T) -> Self { - ElementMaybeSignal::Static(Some(value)) + ElementMaybeSignal::Static(Some(SendWrapper::new(value))) } } @@ -115,7 +140,7 @@ where T: Into + Clone + 'static, { fn from(target: Option) -> Self { - ElementMaybeSignal::Static(target) + ElementMaybeSignal::Static(target.map(SendWrapper::new)) } } @@ -126,7 +151,7 @@ macro_rules! impl_from_deref_option { E: From<$ty2> + 'static, { fn from(value: $ty) -> Self { - Self::Static((*value).clone()) + Self::Static((*value).clone().map(SendWrapper::new)) } } }; @@ -205,10 +230,10 @@ macro_rules! impl_from_signal_option { }; } -impl_from_signal_option!(Signal>); -impl_from_signal_option!(ReadSignal>); -impl_from_signal_option!(RwSignal>); -impl_from_signal_option!(Memo>); +impl_from_signal_option!(Signal>>); +impl_from_signal_option!(ReadSignal>>); +impl_from_signal_option!(RwSignal>>); +impl_from_signal_option!(Memo>>); macro_rules! impl_from_signal { ($ty:ty) => { @@ -223,10 +248,10 @@ macro_rules! impl_from_signal { }; } -impl_from_signal!(Signal); -impl_from_signal!(ReadSignal); -impl_from_signal!(RwSignal); -impl_from_signal!(Memo); +impl_from_signal!(Signal>); +impl_from_signal!(ReadSignal>); +impl_from_signal!(RwSignal>); +impl_from_signal!(Memo>); // From NodeRef ////////////////////////////////////////////////////////////// @@ -234,14 +259,14 @@ macro_rules! impl_from_node_ref { ($ty:ty) => { impl From> for ElementMaybeSignal<$ty, $ty> where - R: ElementDescriptor + Clone + 'static, + R: ElementType + CreateElement + Clone + Send + Sync + 'static, + R::Output: JsCast + Into<$ty> + Clone + 'static, { fn from(node_ref: NodeRef) -> Self { Self::Dynamic(Signal::derive(move || { 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) }) })) } @@ -253,90 +278,90 @@ impl_from_node_ref!(web_sys::EventTarget); impl_from_node_ref!(web_sys::Element); impl_from_node_ref!(web_sys::HtmlElement); -// From leptos::html::HTMLElement /////////////////////////////////////////////// - -macro_rules! impl_from_html_element { - ($ty:ty) => { - impl From> for ElementMaybeSignal<$ty, $ty> - where - HtmlEl: ElementDescriptor + std::ops::Deref, - { - fn from(value: HtmlElement) -> Self { - let el: &$ty = value.deref(); - Self::Static(Some(el.clone())) - } - } - }; -} - -impl_from_html_element!(web_sys::EventTarget); -impl_from_html_element!(web_sys::Element); -impl_from_html_element!(web_sys::HtmlElement); - -// From Signal ///////////////////////////////////////// - -macro_rules! impl_from_signal_html_element { - ($signal:ty, $ty:ty) => { - impl From<$signal> for ElementMaybeSignal<$ty, $ty> - where - HtmlEl: ElementDescriptor + std::ops::Deref + Clone, - { - fn from(value: $signal) -> Self { - Self::Dynamic(Signal::derive(move || { - let value = value.get(); - let el: &$ty = value.deref(); - Some(el.clone()) - })) - } - } - }; -} - -impl_from_signal_html_element!(Signal>, web_sys::EventTarget); -impl_from_signal_html_element!(ReadSignal>, web_sys::EventTarget); -impl_from_signal_html_element!(RwSignal>, web_sys::EventTarget); -impl_from_signal_html_element!(Memo>, web_sys::EventTarget); - -impl_from_signal_html_element!(Signal>, web_sys::Element); -impl_from_signal_html_element!(ReadSignal>, web_sys::Element); -impl_from_signal_html_element!(RwSignal>, web_sys::Element); -impl_from_signal_html_element!(Memo>, web_sys::Element); - -// From Signal> ///////////////////////////////////////// - -macro_rules! impl_from_signal_html_element { - ($signal:ty, $ty:ty) => { - impl From<$signal> for ElementMaybeSignal<$ty, $ty> - where - HtmlEl: ElementDescriptor + std::ops::Deref + Clone, - { - fn from(value: $signal) -> Self { - Self::Dynamic(Signal::derive(move || { - let el: Option<$ty> = value.get().map(|el| el.deref().clone()); - el - })) - } - } - }; -} - -impl_from_signal_html_element!(Signal>>, web_sys::EventTarget); -impl_from_signal_html_element!( - ReadSignal>>, - web_sys::EventTarget -); -impl_from_signal_html_element!(RwSignal>>, web_sys::EventTarget); -impl_from_signal_html_element!(Memo>>, web_sys::EventTarget); - -impl_from_signal_html_element!(Signal>>, web_sys::Element); -impl_from_signal_html_element!(ReadSignal>>, web_sys::Element); -impl_from_signal_html_element!(RwSignal>>, web_sys::Element); -impl_from_signal_html_element!(Memo>>, web_sys::Element); - -impl_from_signal_html_element!(Signal>>, web_sys::HtmlElement); -impl_from_signal_html_element!( - ReadSignal>>, - web_sys::HtmlElement -); -impl_from_signal_html_element!(RwSignal>>, web_sys::HtmlElement); -impl_from_signal_html_element!(Memo>>, web_sys::HtmlElement); +// // From leptos::html::HTMLElement /////////////////////////////////////////////// +// +// macro_rules! impl_from_html_element { +// ($ty:ty) => { +// impl From> for ElementMaybeSignal<$ty, $ty> +// where +// HtmlEl: ElementDescriptor + std::ops::Deref, +// { +// fn from(value: HtmlElement) -> Self { +// let el: &$ty = value.deref(); +// Self::Static(Some(el.clone())) +// } +// } +// }; +// } +// +// impl_from_html_element!(web_sys::EventTarget); +// impl_from_html_element!(web_sys::Element); +// impl_from_html_element!(web_sys::HtmlElement); +// +// // From Signal ///////////////////////////////////////// +// +// macro_rules! impl_from_signal_html_element { +// ($signal:ty, $ty:ty) => { +// impl From<$signal> for ElementMaybeSignal<$ty, $ty> +// where +// HtmlEl: ElementDescriptor + std::ops::Deref + Clone, +// { +// fn from(value: $signal) -> Self { +// Self::Dynamic(Signal::derive(move || { +// let value = value.get(); +// let el: &$ty = value.deref(); +// Some(el.clone()) +// })) +// } +// } +// }; +// } +// +// impl_from_signal_html_element!(Signal>, web_sys::EventTarget); +// impl_from_signal_html_element!(ReadSignal>, web_sys::EventTarget); +// impl_from_signal_html_element!(RwSignal>, web_sys::EventTarget); +// impl_from_signal_html_element!(Memo>, web_sys::EventTarget); +// +// impl_from_signal_html_element!(Signal>, web_sys::Element); +// impl_from_signal_html_element!(ReadSignal>, web_sys::Element); +// impl_from_signal_html_element!(RwSignal>, web_sys::Element); +// impl_from_signal_html_element!(Memo>, web_sys::Element); +// +// // From Signal> ///////////////////////////////////////// +// +// macro_rules! impl_from_signal_html_element { +// ($signal:ty, $ty:ty) => { +// impl From<$signal> for ElementMaybeSignal<$ty, $ty> +// where +// HtmlEl: ElementDescriptor + std::ops::Deref + Clone, +// { +// fn from(value: $signal) -> Self { +// Self::Dynamic(Signal::derive(move || { +// let el: Option<$ty> = value.get().map(|el| el.deref().clone()); +// el +// })) +// } +// } +// }; +// } +// +// impl_from_signal_html_element!(Signal>>, web_sys::EventTarget); +// impl_from_signal_html_element!( +// ReadSignal>>, +// web_sys::EventTarget +// ); +// impl_from_signal_html_element!(RwSignal>>, web_sys::EventTarget); +// impl_from_signal_html_element!(Memo>>, web_sys::EventTarget); +// +// impl_from_signal_html_element!(Signal>>, web_sys::Element); +// impl_from_signal_html_element!(ReadSignal>>, web_sys::Element); +// impl_from_signal_html_element!(RwSignal>>, web_sys::Element); +// impl_from_signal_html_element!(Memo>>, web_sys::Element); +// +// impl_from_signal_html_element!(Signal>>, web_sys::HtmlElement); +// impl_from_signal_html_element!( +// ReadSignal>>, +// web_sys::HtmlElement +// ); +// impl_from_signal_html_element!(RwSignal>>, web_sys::HtmlElement); +// impl_from_signal_html_element!(Memo>>, web_sys::HtmlElement); diff --git a/src/core/elements_maybe_signal.rs b/src/core/elements_maybe_signal.rs index d316944..9902280 100644 --- a/src/core/elements_maybe_signal.rs +++ b/src/core/elements_maybe_signal.rs @@ -1,7 +1,7 @@ use crate::core::ElementMaybeSignal; use crate::{UseDocument, UseWindow}; use cfg_if::cfg_if; -use leptos::html::ElementDescriptor; +use leptos::html::{ElementType, HtmlElement}; use leptos::prelude::wrappers::read::Signal; use leptos::prelude::*; use std::marker::PhantomData; @@ -18,9 +18,9 @@ pub enum ElementsMaybeSignal where T: Into + Clone + 'static, { - Static(Vec>), - Dynamic(Signal>>), - _Phantom(PhantomData), + Static(Vec>>), + Dynamic(Signal>>>), + _Phantom(PhantomData E>), } impl Default for ElementsMaybeSignal @@ -256,7 +256,7 @@ macro_rules! impl_from_node_ref { ($ty:ty) => { impl From> for ElementsMaybeSignal<$ty, $ty> where - R: ElementDescriptor + Clone + 'static, + R: ElementType + Clone + 'static, { fn from(node_ref: NodeRef) -> Self { Self::Dynamic(Signal::derive(move || { @@ -278,11 +278,12 @@ impl_from_node_ref!(web_sys::Element); macro_rules! impl_from_html_element { ($ty:ty) => { - impl From> for ElementsMaybeSignal<$ty, $ty> + impl From> for ElementsMaybeSignal<$ty, $ty> where - HtmlEl: ElementDescriptor + std::ops::Deref, + E: ElementType, + E::Output: std::ops::Deref, { - fn from(value: HtmlElement) -> Self { + fn from(value: HtmlElement) -> Self { let el: &$ty = value.deref(); Self::Static(vec![Some(el.clone())]) } @@ -539,7 +540,7 @@ macro_rules! impl_from_multi_node_ref { ($ty:ty) => { impl From<&[NodeRef]> for ElementsMaybeSignal<$ty, $ty> where - R: ElementDescriptor + Clone + 'static, + R: ElementType + Clone + 'static, { fn from(node_refs: &[NodeRef]) -> Self { let node_refs = node_refs.to_vec(); @@ -549,7 +550,7 @@ macro_rules! impl_from_multi_node_ref { impl From<[NodeRef; C]> for ElementsMaybeSignal<$ty, $ty> where - R: ElementDescriptor + Clone + 'static, + R: ElementType + Clone + 'static, { fn from(node_refs: [NodeRef; C]) -> Self { let node_refs = node_refs.to_vec(); @@ -559,7 +560,7 @@ macro_rules! impl_from_multi_node_ref { impl From>> for ElementsMaybeSignal<$ty, $ty> where - R: ElementDescriptor + Clone + 'static, + R: ElementType + Clone + 'static, { fn from(node_refs: Vec>) -> Self { let node_refs = node_refs.clone(); @@ -572,66 +573,71 @@ macro_rules! impl_from_multi_node_ref { impl_from_multi_node_ref!(web_sys::EventTarget); impl_from_multi_node_ref!(web_sys::Element); -// From multiple leptos::html::HTMLElement ///////////////////////////////////////// - -macro_rules! impl_from_multi_html_element { - ($ty:ty) => { - impl From<&[HtmlElement]> for ElementsMaybeSignal<$ty, $ty> - where - HtmlEl: ElementDescriptor + std::ops::Deref, - { - fn from(value: &[HtmlElement]) -> Self { - Self::Static( - value - .iter() - .map(|el| { - let el: &$ty = el.deref(); - Some(el.clone()) - }) - .collect(), - ) - } - } - - impl From<[HtmlElement; C]> - for ElementsMaybeSignal<$ty, $ty> - where - HtmlEl: ElementDescriptor + std::ops::Deref, - { - fn from(value: [HtmlElement; C]) -> Self { - Self::Static( - value - .iter() - .map(|el| { - let el: &$ty = el.deref(); - Some(el.clone()) - }) - .collect(), - ) - } - } - - impl From>> for ElementsMaybeSignal<$ty, $ty> - where - HtmlEl: ElementDescriptor + std::ops::Deref, - { - fn from(value: Vec>) -> Self { - Self::Static( - value - .iter() - .map(|el| { - let el: &$ty = el.deref(); - Some(el.clone()) - }) - .collect(), - ) - } - } - }; -} - -impl_from_multi_html_element!(web_sys::EventTarget); -impl_from_multi_html_element!(web_sys::Element); +// // From multiple leptos::html::HTMLElement ///////////////////////////////////////// +// +// macro_rules! impl_from_multi_html_element { +// ($ty:ty) => { +// impl From<&[HtmlElement]> +// for ElementsMaybeSignal<$ty, $ty> +// where +// E: ElementType, +// E::Output: std::ops::Deref, +// { +// fn from(value: &[HtmlElement]) -> Self { +// Self::Static( +// value +// .iter() +// .map(|el| { +// let el: &$ty = el.deref(); +// Some(el.clone()) +// }) +// .collect(), +// ) +// } +// } +// +// impl From<[HtmlElement; C]> +// for ElementsMaybeSignal<$ty, $ty> +// where +// E: ElementType, +// E::Output: std::ops::Deref, +// { +// fn from(value: [HtmlElement; C]) -> Self { +// Self::Static( +// value +// .iter() +// .map(|el| { +// let el: &$ty = el.deref(); +// Some(el.clone()) +// }) +// .collect(), +// ) +// } +// } +// +// impl From>> +// for ElementsMaybeSignal<$ty, $ty> +// where +// E: ElementType, +// E::Output: std::ops::Deref, +// { +// fn from(value: Vec>) -> Self { +// Self::Static( +// value +// .iter() +// .map(|el| { +// let el: &$ty = el.deref(); +// Some(el.clone()) +// }) +// .collect(), +// ) +// } +// } +// }; +// } +// +// impl_from_multi_html_element!(web_sys::EventTarget); +// impl_from_multi_html_element!(web_sys::Element); // From ElementMaybeSignal ////////////////////////////////////////////////////////////// diff --git a/src/use_cycle_list.rs b/src/use_cycle_list.rs index b7999c8..2a38b3b 100644 --- a/src/use_cycle_list.rs +++ b/src/use_cycle_list.rs @@ -1,6 +1,5 @@ use crate::core::MaybeRwSignal; use default_struct_builder::DefaultBuilder; -use leptos::prelude::wrappers::read::Signal; use leptos::prelude::*; /// Cycle through a list of items. @@ -156,7 +155,7 @@ where let _ = { let set = set.clone(); - leptos::watch(move || list.get(), move |_, _, _| set(index.get()), false) + watch(move || list.get(), move |_, _, _| set(index.get()), false) }; UseCycleListReturn { diff --git a/src/use_interval_fn.rs b/src/use_interval_fn.rs index b34e752..4fab709 100644 --- a/src/use_interval_fn.rs +++ b/src/use_interval_fn.rs @@ -5,6 +5,7 @@ use default_struct_builder::DefaultBuilder; use leptos::leptos_dom::helpers::IntervalHandle; use leptos::prelude::diagnostics::SpecialNonReactiveZone; use leptos::prelude::*; +use send_wrapper::SendWrapper; use std::cell::Cell; use std::rc::Rc; use std::time::Duration; @@ -140,7 +141,8 @@ where on_cleanup(stop_watch); } - on_cleanup(pause.clone()); + let pause_cleanup = SendWrapper::new(pause.clone()); + on_cleanup(move || pause_cleanup()); Pausable { is_active: is_active.into(), diff --git a/src/watch_with_options.rs b/src/watch_with_options.rs index 86e30ca..e33678a 100644 --- a/src/watch_with_options.rs +++ b/src/watch_with_options.rs @@ -130,7 +130,7 @@ where let filtered_callback = create_filter_wrapper(options.filter.filter_fn(), wrapped_callback.clone()); - leptos::watch( + leptos::prelude::watch( deps, move |deps_value, previous_deps_value, did_run_before| { cur_deps_value.replace(Some(deps_value.clone())); @@ -139,7 +139,7 @@ where let callback_value = if options.immediate && did_run_before.is_none() { Some(wrapped_callback()) } else { - filtered_callback().take() + filtered_callback().lock().unwrap().take() }; prev_callback_value.replace(callback_value); @@ -197,5 +197,5 @@ where W: Clone + 'static, T: Clone + 'static, { - leptos::watch(deps, callback, false) + leptos::prelude::watch(deps, callback, false) }