#![allow(dead_code)]
use std::{
cell::{Cell, RefCell},
rc::Rc,
sync::{
Arc,
atomic::{AtomicUsize, Ordering},
},
};
use cranpose_core::DisposableEffect;
use cranpose_coroflow::viewModel;
use cranpose_navigation::{NavController, NavHost, rememberNavController};
use cranpose_testing::ComposeTestRule;
const SETTLE_FRAMES: u64 = 60;
const FRAME_NANOS: u64 = 16_666_667;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum Screen {
Home,
Detail(u32),
Settings,
}
pub struct DropMarker(pub Arc<AtomicUsize>);
impl Drop for DropMarker {
fn drop(&mut self) {
self.0.fetch_add(1, Ordering::SeqCst);
}
}
pub struct ScreenModel {
pub screen: Screen,
_dropped: DropMarker,
}
#[derive(Clone, Default)]
pub struct Probe {
pub live: Rc<RefCell<Vec<Screen>>>,
pub built: Rc<RefCell<Vec<Screen>>>,
pub dropped: Arc<AtomicUsize>,
}
impl Probe {
pub fn live(&self) -> Vec<Screen> {
self.live.borrow().clone()
}
pub fn built(&self) -> Vec<Screen> {
self.built.borrow().clone()
}
pub fn dropped(&self) -> usize {
self.dropped.load(Ordering::SeqCst)
}
pub fn screen(&self, screen: Screen) {
let live = Rc::clone(&self.live);
DisposableEffect(screen, move |scope| {
live.borrow_mut().push(screen);
scope.on_dispose(move || live.borrow_mut().retain(|shown| *shown != screen))
});
let (built, dropped) = (Rc::clone(&self.built), Arc::clone(&self.dropped));
let model = viewModel((), move |_| {
built.borrow_mut().push(screen);
ScreenModel {
screen,
_dropped: DropMarker(dropped),
}
});
assert_eq!(model.get().screen, screen, "each entry has its own store");
}
}
pub struct Host {
pub rule: ComposeTestRule,
now: u64,
}
impl Host {
pub fn new(content: impl FnMut() + 'static) -> Self {
let mut rule = ComposeTestRule::new();
rule.set_content(content).expect("compose");
let mut host = Self { rule, now: 0 };
host.settle();
host
}
pub fn settle(&mut self) {
self.run_frames(SETTLE_FRAMES);
}
pub fn run_frames(&mut self, count: u64) {
for _ in 0..count {
self.rule.runtime_handle().drain_ui();
self.now += FRAME_NANOS;
self.rule.advance_frame(self.now).expect("frame");
}
}
}
pub fn screens(probe: &Probe) -> (Host, Rc<Cell<Option<NavController<Screen>>>>) {
let nav = Rc::new(Cell::new(None));
let (captured, probe) = (Rc::clone(&nav), probe.clone());
let host = Host::new(move || {
let controller = rememberNavController(Screen::Home);
captured.set(Some(controller));
let probe = probe.clone();
NavHost(controller, move |screen| probe.screen(screen));
});
(host, nav)
}