handle listeners

This commit is contained in:
Evan Almloff committed 2022-05-27 10:50:33 -05:00
1 parent a0c7e4d78a
commit 6b03a60fee
3 files changed
+52 -15

No files matched your search

+10 -3
View File
@@ -6,25 +6,32 @@ fn main() {
}
fn app(cx: Scope) -> Element {
let count = use_state(&cx, || 0);
let count = use_state(&cx, || 170);
use_future(&cx, (), move |_| {
let mut count = count.clone();
async move {
loop {
tokio::time::sleep(Duration::from_millis(10)).await;
tokio::time::sleep(Duration::from_millis(1000)).await;
count += 1;
}
}
});
cx.render(rsx! {
h1 {
div {
width: format!("{}px", count),
background_color: "#999999",
onclick: move |_| {
count.modify(|count| *count + 1);
},
"High-Five counter: {count}",
Comp{
color: "#083289"
}
Comp{
color: "green"
}
}
})
}
@@ -1,5 +1,5 @@
use dioxus_core::VNode;
use dioxus_rsx::{BodyNode, CallBody, Component, ElementAttr, IfmtInput};
use dioxus_core::{Listener, VNode};
use dioxus_rsx::{BodyNode, CallBody, Component, ElementAttr, ElementAttrNamed, IfmtInput};
use quote::{quote, ToTokens, TokenStreamExt};
use std::collections::HashMap;
use syn::Expr;
@@ -11,6 +11,7 @@ pub struct CapturedContextBuilder {
pub components: Vec<Component>,
pub iterators: Vec<Expr>,
pub captured_expressions: Vec<Expr>,
pub listeners: Vec<ElementAttrNamed>,
}
impl CapturedContextBuilder {
@@ -19,6 +20,7 @@ impl CapturedContextBuilder {
self.text.extend(other.text);
self.components.extend(other.components);
self.iterators.extend(other.iterators);
self.listeners.extend(other.listeners);
self.captured_expressions.extend(other.captured_expressions);
}
@@ -52,6 +54,7 @@ impl CapturedContextBuilder {
ElementAttr::CustomAttrExpression { name: _, value } => {
captured.captured_expressions.push(value);
}
ElementAttr::EventTokens { .. } => captured.listeners.push(attr),
_ => (),
}
}
@@ -82,11 +85,14 @@ impl ToTokens for CapturedContextBuilder {
components,
iterators,
captured_expressions,
listeners,
} = self;
let listeners_str = listeners
.iter()
.map(|comp| comp.to_token_stream().to_string());
let compontents_str = components
.iter()
.map(|comp| comp.to_token_stream().to_string());
let components = components.iter().map(|comp| comp);
let iterators_str = iterators
.iter()
.map(|expr| expr.to_token_stream().to_string());
@@ -109,6 +115,7 @@ impl ToTokens for CapturedContextBuilder {
components: vec![#((#compontents_str, #components)),*],
iterators: vec![#((#iterators_str, #iterators)),*],
expressions: vec![#((#captured_attr_expressions_text, #captured_expressions.to_string())),*],
listeners: vec![#((#listeners_str, #listeners)),*],
}
})
}
@@ -125,6 +132,8 @@ pub struct CapturedContext<'a> {
pub iterators: Vec<(&'static str, VNode<'a>)>,
// map expression to the value resulting from the expression
pub expressions: Vec<(&'static str, String)>,
// map listener code to the resulting listener
pub listeners: Vec<(&'static str, Listener<'a>)>,
}
pub struct IfmtArgs {
+30 -9
View File
@@ -1,5 +1,5 @@
use dioxus_core::{Attribute, NodeFactory, VNode};
use dioxus_rsx::{BodyNode, CallBody, Component, ElementAttr};
use dioxus_rsx::{BodyNode, CallBody, ElementAttr};
use quote::ToTokens;
use std::str::FromStr;
use syn::{parse2, parse_str, Expr};
@@ -111,10 +111,10 @@ fn build_node<'a>(
}
BodyNode::Element(el) => {
let attributes: &mut Vec<Attribute> = bump.alloc(Vec::new());
for attr in el.attributes {
match attr.attr {
for attr in &el.attributes {
match &attr.attr {
ElementAttr::AttrText { .. } | ElementAttr::CustomAttrText { .. } => {
let (name, value): (String, InterperedIfmt) = match attr.attr {
let (name, value): (String, InterperedIfmt) = match &attr.attr {
ElementAttr::AttrText { name, value } => {
(name.to_string(), value.value().parse().unwrap())
}
@@ -140,7 +140,7 @@ fn build_node<'a>(
ElementAttr::AttrExpression { .. }
| ElementAttr::CustomAttrExpression { .. } => {
let (name, value) = match attr.attr {
let (name, value) = match &attr.attr {
ElementAttr::AttrExpression { name, value } => {
(name.to_string(), value)
}
@@ -153,7 +153,7 @@ fn build_node<'a>(
if let Some((_, resulting_value)) = ctx
.expressions
.iter()
.find(|(n, _)| parse_str::<Expr>(*n).unwrap() == value)
.find(|(n, _)| parse_str::<Expr>(*n).unwrap() == *value)
{
if let Some((name, namespace)) = attrbute_to_static_str(&name) {
let value = bump.alloc(resulting_value.clone());
@@ -169,8 +169,6 @@ fn build_node<'a>(
panic!("could not resolve expression {:?}", value);
}
}
// Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident { ident: \"count\", span: #0 bytes(497..502) }, arguments: None }] } })
// Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(count), arguments: None }] } })
_ => (),
};
}
@@ -181,12 +179,35 @@ fn build_node<'a>(
children.push(node);
}
}
let listeners = bump.alloc(Vec::new());
for attr in el.attributes {
match attr.attr {
ElementAttr::EventTokens { .. } => {
let expr: Expr = parse2(attr.to_token_stream()).unwrap();
if let Some(idx) = ctx
.listeners
.iter()
.position(|(code, _)| parse_str::<Expr>(*code).unwrap() == expr)
{
let (_, listener) = ctx.listeners.remove(idx);
listeners.push(listener)
} else {
panic!(
"could not resolve listener {:?} \n in: {:#?}",
expr.to_token_stream().to_string(),
ctx.listeners.iter().map(|(s, _)| s).collect::<Vec<_>>()
);
}
}
_ => (),
}
}
let tag = bump.alloc(el.name.to_string());
if let Some((tag, ns)) = element_to_static_str(tag) {
Some(factory.raw_element(
tag,
ns,
&[],
listeners,
attributes.as_slice(),
children.as_slice(),
Some(format_args!("{}", key)),