Skip to content

Commit

Permalink
Fix Child view to support nested updates
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Jan 20, 2024
1 parent b056deb commit e0e5fa5
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 35 deletions.
34 changes: 17 additions & 17 deletions crates/concoct-web/src/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::WebContext;
use concoct::{
hook::{use_context, use_on_drop, use_provider, use_ref},
view::Child,
View, ViewBuilder,
Tree, View, ViewBuilder,
};
use std::{borrow::Cow, cell::RefCell, rc::Rc};
use web_sys::{
Expand All @@ -13,8 +13,8 @@ use web_sys::{
macro_rules! make_tag_fns {
($($name:tt),*) => {
$(
pub fn $name<C: View>(child: C) -> Html<C> {
Html::new(stringify!($name), child)
pub fn $name(child: impl View) -> Html<impl Tree> {
html(stringify!($name), child)
}
)*
};
Expand All @@ -24,11 +24,11 @@ make_tag_fns!(
a, abbr, address, area, article, aside, audio, b, base, bdi, bdo, blockquote, body, br, button,
canvas, caption, cite, code, col, colgroup, data, datalist, dd, del, details, dfn, dialog, div,
dl, dt, em, embed, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, head,
header, hr, html, i, iframe, img, input, ins, kbd, label, legend, li, link, main, map, mark,
meta, meter, nav, noscript, object, ol, optgroup, option, output, p, param, picture, pre,
progress, q, rp, rt, ruby, s, samp, script, section, select, small, source, span, strong, sub,
summary, sup, svg, table, tbody, td, template, textarea, tfoot, th, thead, time, title, tr,
track, u, ul, var, video, wbr
header, hr, i, iframe, img, input, ins, kbd, label, legend, li, link, main, map, mark, meta,
meter, nav, noscript, object, ol, optgroup, option, output, p, param, picture, pre, progress,
q, rp, rt, ruby, s, samp, script, section, select, small, source, span, strong, sub, summary,
sup, svg, table, tbody, td, template, textarea, tfoot, th, thead, time, title, tr, track, u,
ul, var, video, wbr
);

#[derive(Default)]
Expand Down Expand Up @@ -67,16 +67,16 @@ macro_rules! impl_handler_methods {
};
}

impl<C> Html<C> {
pub fn new(tag: impl Into<Cow<'static, str>>, child: C) -> Self {
Self {
tag: tag.into(),
attrs: Vec::new(),
handlers: Vec::new(),
child: Child::new(child),
}
pub fn html(tag: impl Into<Cow<'static, str>>, child: impl View) -> Html<impl Tree> {
Html {
tag: tag.into(),
attrs: Vec::new(),
handlers: Vec::new(),
child: concoct::view::child(child),
}
}

impl<C> Html<C> {
pub fn attr(
mut self,
name: impl Into<Cow<'static, str>>,
Expand Down Expand Up @@ -108,7 +108,7 @@ impl<C> Html<C> {
);
}

impl<C: View> ViewBuilder for Html<C> {
impl<C: Tree> ViewBuilder for Html<C> {
fn build(&self) -> impl View {
let data = use_ref(|| RefCell::new(Data::default()));
let mut data_ref = data.borrow_mut();
Expand Down
44 changes: 27 additions & 17 deletions crates/concoct/src/view/child.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
use crate::{Tree, View};
use std::{cell::RefCell, rc::Rc};
use std::{any::Any, cell::RefCell, rc::Rc};

/// Child view.
/// Create a child view.
///
/// This type should be cloned and returned from a parent view to wrap its content.
///
/// ## Panics
/// This view can only be used once, then it will panic.
pub struct Child<V> {
cell: Rc<RefCell<Option<V>>>,
pub fn child(view: impl View) -> Child<impl Tree> {
Child {
tree: Rc::new(RefCell::new(view.into_tree())),
}
}

impl<B> Child<B> {
pub fn new(view: B) -> Self {
Self {
cell: Rc::new(RefCell::new(Some(view))),
}
}
pub struct Child<T> {
tree: Rc<RefCell<T>>,
}

impl<B> Clone for Child<B> {
impl<T> Clone for Child<T> {
fn clone(&self) -> Self {
Self {
cell: self.cell.clone(),
tree: self.tree.clone(),
}
}
}

impl<B: View> View for Child<B> {
impl<T: Tree> View for Child<T> {
fn into_tree(self) -> impl Tree {
self.cell.take().unwrap().into_tree()
self
}
}

impl<T: Tree> Tree for Child<T> {
unsafe fn build(&mut self) {
self.tree.borrow_mut().build()
}

unsafe fn rebuild(&mut self, last: &mut dyn Any) {
let last = last.downcast_mut::<Self>().unwrap();
self.tree.borrow_mut().rebuild(&mut *last.tree.borrow_mut())
}

unsafe fn remove(&mut self) {
self.tree.borrow_mut().remove()
}
}
2 changes: 1 addition & 1 deletion crates/concoct/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{Node, Tree, ViewBuilder};
use std::hash::Hash;

mod child;
pub use child::Child;
pub use child::{child, Child};

mod empty;
pub use empty::Empty;
Expand Down

0 comments on commit e0e5fa5

Please sign in to comment.