Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev/listener multiplexer #1542

Merged
merged 49 commits into from
Aug 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c1cd37d
yew: partial event listener multiplexer
bakape Aug 30, 2020
71327a1
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 30, 2020
1de087e
yew: partial event listener multiplexer
bakape Aug 30, 2020
de70a8c
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 31, 2020
37e269d
yew/listener: fix and test synchronous listeners
bakape Sep 1, 2020
48e68ac
yew/listener: add placeholder comments
bakape Sep 1, 2020
7c070a6
yew/listener: passive listener test
bakape Sep 2, 2020
2209c73
yew: extend and fix APIs and docs
bakape Sep 3, 2020
fe91f0a
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Sep 3, 2020
e56b508
yew/listener: event bubbling
bakape Sep 5, 2020
b49df05
clippy: ignore warning
bakape Sep 5, 2020
1d1747f
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Sep 5, 2020
51e4cc3
Update yew/src/callback.rs
bakape Sep 5, 2020
a5d8480
Update yew/src/html/listener/listener_stdweb.rs
bakape Sep 5, 2020
1268b81
Apply suggestions from code review
bakape Sep 5, 2020
af3fc32
Apply suggestions from code review
bakape Sep 5, 2020
d065b71
yew/listner: remove redundant function
bakape Sep 6, 2020
7db22d0
yew/listner: restore delibarate formatting
bakape Sep 6, 2020
e4cc4b7
yew/callback: make Flags a newtype
bakape Sep 6, 2020
389aad2
yew/listener: use utility function
bakape Sep 6, 2020
041e8e5
yew/listener: deferred listeners
bakape Sep 6, 2020
c29b786
yew/listner: input and change tests
bakape Sep 9, 2020
a948b0a
yew/listener: optimize listener registration
bakape Sep 11, 2020
c07dd47
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Sep 11, 2020
709de51
yew/listener: remove benchmark placeholders
bakape Sep 11, 2020
56255a6
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Sep 13, 2020
39fdb84
yew/callback: revert CallbackOnce -> Once
bakape Sep 13, 2020
47c0df9
yew: convert listener_tests to a build flag
bakape Sep 13, 2020
56afcee
Apply suggestions from code review
bakape Sep 14, 2020
460ef4f
yew: fix doc comments
bakape Sep 18, 2020
99a5139
yew: simplify iteration
bakape Sep 18, 2020
eb5cff8
yew/remove unneeded default passive listeners
bakape Sep 18, 2020
36d4ba5
Merge commit 'b872dabf1f9fe777e348f541de832eef38a4978c' into dev/list…
bakape Aug 7, 2021
b5ea356
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 7, 2021
ef595a1
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 7, 2021
4aaa3ec
yew/listeners: DRY some more
bakape Aug 7, 2021
c2a1673
yew/listener: fix clippy warnings
bakape Aug 7, 2021
a4a31c2
yew/listeners: remove legacy comment
bakape Aug 7, 2021
814ee94
yew/listeners: document stopping propagation
bakape Aug 7, 2021
2c29b00
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 15, 2021
f1b1720
yew/listeners: update tests
bakape Aug 15, 2021
13f4f0c
ci: see how test run on stable
bakape Aug 15, 2021
d1ea639
ci: let's find the new MSRV
bakape Aug 15, 2021
9bd2219
ci: try to run integration tests only on stable
bakape Aug 15, 2021
cd5a3bc
yew/test: clean up residual dirty state
bakape Aug 15, 2021
26172a2
yew/listeners: minor doc string and inline fixes
bakape Aug 15, 2021
939e97b
yew/listener: document reasonning for function
bakape Aug 21, 2021
cc0fa7f
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 28, 2021
58c6080
Merge remote-tracking branch 'upstream/master' into dev/listener-mult…
bakape Aug 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/yew-macro/src/html_tree/html_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl ToTokens for HtmlElement {
};

let listeners = if listeners.is_empty() {
quote! { ::std::vec![] }
quote! { ::yew::virtual_dom::listeners::Listeners::None }
} else {
let listeners_it = listeners.iter().map(|Prop { label, value, .. }| {
let name = &label.name;
Expand All @@ -278,7 +278,11 @@ impl ToTokens for HtmlElement {
}
});

quote! { ::std::vec![#(#listeners_it),*].into_iter().flatten().collect() }
quote! {
::yew::virtual_dom::listeners::Listeners::Pending(
::std::boxed::Box::new([#(#listeners_it),*])
)
}
};

// TODO: if none of the children have possibly None expressions or literals as keys, we can
Expand Down
38 changes: 30 additions & 8 deletions packages/yew/src/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@ use std::rc::Rc;
/// </aside>
/// An `Rc` wrapper is used to make it cloneable.
pub enum Callback<IN> {
/// A callback which can be called multiple times
Callback(Rc<dyn Fn(IN)>),
/// A callback which can be called multiple times with optional modifier flags
Callback {
/// A callback which can be called multiple times
cb: Rc<dyn Fn(IN)>,

/// Setting `passive` to [Some] explicitly makes the event listener passive or not.
/// Yew sets sane defaults depending on the type of the listener.
/// See
/// [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).
passive: Option<bool>,
},

/// A callback which can only be called once. The callback will panic if it is
/// called more than once.
CallbackOnce(Rc<CallbackOnce<IN>>),
Expand All @@ -28,14 +38,20 @@ type CallbackOnce<IN> = RefCell<Option<Box<dyn FnOnce(IN)>>>;

impl<IN, F: Fn(IN) + 'static> From<F> for Callback<IN> {
fn from(func: F) -> Self {
Callback::Callback(Rc::new(func))
Callback::Callback {
cb: Rc::new(func),
passive: None,
}
}
}

impl<IN> Clone for Callback<IN> {
fn clone(&self) -> Self {
match self {
Callback::Callback(cb) => Callback::Callback(cb.clone()),
Callback::Callback { cb, passive } => Callback::Callback {
cb: cb.clone(),
passive: *passive,
},
Callback::CallbackOnce(cb) => Callback::CallbackOnce(cb.clone()),
}
}
Expand All @@ -45,10 +61,16 @@ impl<IN> Clone for Callback<IN> {
impl<IN> PartialEq for Callback<IN> {
fn eq(&self, other: &Callback<IN>) -> bool {
match (&self, &other) {
(Callback::Callback(cb), Callback::Callback(other_cb)) => Rc::ptr_eq(cb, other_cb),
(Callback::CallbackOnce(cb), Callback::CallbackOnce(other_cb)) => {
Rc::ptr_eq(cb, other_cb)
}
(
Callback::Callback { cb, passive },
Callback::Callback {
cb: rhs_cb,
passive: rhs_passive,
},
) => Rc::ptr_eq(cb, rhs_cb) && passive == rhs_passive,
_ => false,
}
}
Expand All @@ -57,7 +79,7 @@ impl<IN> PartialEq for Callback<IN> {
impl<IN> fmt::Debug for Callback<IN> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let data = match self {
Callback::Callback(_) => "Callback<_>",
Callback::Callback { .. } => "Callback<_>",
Callback::CallbackOnce(_) => "CallbackOnce<_>",
};

Expand All @@ -69,10 +91,10 @@ impl<IN> Callback<IN> {
/// This method calls the callback's function.
pub fn emit(&self, value: IN) {
match self {
Callback::Callback(cb) => cb(value),
Callback::Callback { cb, .. } => cb(value),
Callback::CallbackOnce(rc) => {
let cb = rc.replace(None);
let f = cb.expect("callback in CallbackOnce has already been used");
let f = cb.expect("callback contains `FnOnce` which has already been used");
f(value)
}
};
Expand Down
2 changes: 1 addition & 1 deletion packages/yew/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct ContextProviderProps<T: Clone + PartialEq> {
/// The context provider component.
///
/// Every child (direct or indirect) of this component may access the context value.
/// In order to consume contexts, [`ComponentLink::context`][Scope::context] method is used,
/// In order to consume contexts, [`Scope::context`][Scope::context] method is used,
/// In function components the `use_context` hook is used.
#[derive(Debug)]
pub struct ContextProvider<T: Clone + PartialEq + 'static> {
Expand Down
28 changes: 27 additions & 1 deletion packages/yew/src/html/component/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,29 @@ impl<COMP: Component> Scope<COMP> {
/// synchronously schedules a call to the [Component](Component)
/// interface.
pub fn callback<F, IN, M>(&self, function: F) -> Callback<IN>
where
M: Into<COMP::Message>,
F: Fn(IN) -> M + 'static,
{
self.callback_with_passive(None, function)
}

/// Creates a `Callback` which will send a message to the linked
/// component's update method when invoked.
///
/// Setting `passive` to [Some] explicitly makes the event listener passive or not.
/// Yew sets sane defaults depending on the type of the listener.
/// See
/// [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).
///
/// Please be aware that currently the result of this callback
/// synchronously schedules a call to the [Component](Component)
/// interface.
pub fn callback_with_passive<F, IN, M>(
&self,
passive: impl Into<Option<bool>>,
function: F,
) -> Callback<IN>
where
M: Into<COMP::Message>,
F: Fn(IN) -> M + 'static,
Expand All @@ -264,7 +287,10 @@ impl<COMP: Component> Scope<COMP> {
let output = function(input);
scope.send_message(output);
};
closure.into()
Callback::Callback {
passive: passive.into(),
cb: Rc::new(closure),
}
}

/// Creates a `Callback` from an `FnOnce` which will send a message
Expand Down