use cranpose_core::{Applier, MemoryApplier, NodeError, NodeId};
use super::{LayoutNode, read_live_layout_node};
pub fn can_skip_scroll_reveal_from_applier(
applier: &mut MemoryApplier,
root: NodeId,
target: NodeId,
) -> Result<bool, NodeError> {
let mut current = target;
let mut child = None;
for _ in 0..applier.capacity() {
let Some((parent, accepted)) = read_live_layout_node(applier, current, |node| {
let accepted = node.state().is_placed()
&& (current == root || !node.is_window_root())
&& child.is_none_or(|child| node.with_children(|ids| ids.contains(&child)))
&& (child.is_none()
|| !node
.semantics()
.is_some_and(|config| config.scroll_by.is_some()));
(node.parent(), accepted)
})?
else {
return Ok(false);
};
if !accepted {
return Ok(false);
}
if current == root {
return Ok(true);
}
let Some(parent) = parent else {
return Ok(false);
};
let parent = match applier.get_mut(parent) {
Ok(node) => node
.as_any_mut()
.downcast_mut::<LayoutNode>()
.filter(|node| node.is_virtual())
.map_or(Some(parent), |node| node.parent()),
Err(NodeError::Missing { .. }) => None,
Err(error) => return Err(error),
};
let Some(parent) = parent else {
return Ok(false);
};
child = Some(current);
current = parent;
}
Ok(false)
}