Fixing bug where children_signal_vec wouldn't trigger after_removed

This commit is contained in:
Pauan 2021-04-29 19:44:21 +02:00
parent 2d9ae38c9d
commit 672af7b3ed
1 changed files with 37 additions and 18 deletions

View File

@ -144,13 +144,15 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
where A: SignalVec<Item = Dom> + 'static {
struct State {
element: Node,
is_inserted: bool,
children: Vec<Dom>,
}
impl State {
fn new() -> Rc<RefCell<Self>> {
fn new(element: Node) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(State {
element,
is_inserted: false,
children: vec![],
}))
@ -170,41 +172,47 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
});
}
fn clear(&mut self, element: &Node) {
fn clear(&mut self) {
for dom in self.children.drain(..) {
bindings::remove_child(element, &dom.element);
bindings::remove_child(&self.element, &dom.element);
dom.callbacks.discard();
}
}
fn insert_at(&self, element: &Node, new_index: usize, child: &Node) {
fn on_remove(&mut self) {
for dom in self.children.drain(..) {
dom.callbacks.discard();
}
}
fn insert_at(&self, new_index: usize, child: &Node) {
if let Some(dom) = self.children.get(new_index) {
bindings::insert_child_before(element, child, &dom.element);
bindings::insert_child_before(&self.element, child, &dom.element);
} else {
bindings::append_child(element, child);
bindings::append_child(&self.element, child);
}
}
// TODO verify that this will drop `children`
fn process_change(&mut self, element: &Node, change: VecDiff<Dom>) {
fn process_change(&mut self, change: VecDiff<Dom>) {
match change {
VecDiff::Replace { values } => {
self.clear(element);
self.clear();
self.children = values;
let is_inserted = self.is_inserted;
for dom in self.children.iter_mut() {
bindings::append_child(element, &dom.element);
bindings::append_child(&self.element, &dom.element);
after_insert(is_inserted, &mut dom.callbacks);
}
},
VecDiff::InsertAt { index, mut value } => {
self.insert_at(element, index, &value.element);
self.insert_at(index, &value.element);
after_insert(self.is_inserted, &mut value.callbacks);
@ -213,7 +221,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
},
VecDiff::Push { mut value } => {
bindings::append_child(element, &value.element);
bindings::append_child(&self.element, &value.element);
after_insert(self.is_inserted, &mut value.callbacks);
@ -224,7 +232,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
VecDiff::UpdateAt { index, mut value } => {
let dom = &mut self.children[index];
bindings::replace_child(element, &value.element, &dom.element);
bindings::replace_child(&self.element, &value.element, &dom.element);
after_insert(self.is_inserted, &mut value.callbacks);
@ -238,7 +246,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
VecDiff::Move { old_index, new_index } => {
let value = self.children.remove(old_index);
self.insert_at(element, new_index, &value.element);
self.insert_at(new_index, &value.element);
self.children.insert(new_index, value);
},
@ -246,7 +254,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
VecDiff::RemoveAt { index } => {
let dom = self.children.remove(index);
bindings::remove_child(element, &dom.element);
bindings::remove_child(&self.element, &dom.element);
dom.callbacks.discard();
},
@ -254,24 +262,35 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
VecDiff::Pop {} => {
let dom = self.children.pop().unwrap_throw();
bindings::remove_child(element, &dom.element);
bindings::remove_child(&self.element, &dom.element);
dom.callbacks.discard();
},
VecDiff::Clear {} => {
self.clear(element);
self.clear();
},
}
}
}
let state = State::new();
struct OnRemove(Rc<RefCell<State>>);
impl Discard for OnRemove {
#[inline]
fn discard(self) {
self.0.borrow_mut().on_remove();
}
}
let state = State::new(element);
State::after_insert(state.clone(), callbacks);
callbacks.after_remove(OnRemove(state.clone()));
callbacks.after_remove(for_each_vec(signal, move |change| {
let mut state = state.borrow_mut();
state.process_change(&element, change);
state.process_change(change);
}));
}