use cranpose_animation::{AnimationType, Easing, tween};
use cranpose_coroflow::ProvideViewModelStore;
use cranpose_services::{BackGesture, PredictiveBackHandler, ProvideSaveableScope};
use cranpose_ui::{CrossfadeSeek, SeekableCrossfade, composable};
use crate::controller::{Entry, NavController};
const DEFAULT_TRANSITION_MILLIS: u64 = 700;
#[composable(no_skip)]
pub fn NavHost<R, F>(controller: NavController<R>, content: F)
where
R: Clone + PartialEq + 'static,
F: FnMut(R) + 'static,
{
NavHostWith(
controller,
tween(DEFAULT_TRANSITION_MILLIS, Easing::FastOutSlowInEasing),
content,
);
}
#[composable(no_skip)]
pub fn NavHostWith<R, F>(controller: NavController<R>, transition: AnimationType, mut content: F)
where
R: Clone + PartialEq + 'static,
F: FnMut(R) + 'static,
{
let (top, beneath, can_pop) = controller
.stack
.read(|stack| (stack.top(), stack.beneath_top(), stack.can_pop()));
let gesture = cranpose_core::rememberMutableStateOf(|| None::<f32>);
PredictiveBackHandler(
can_pop,
move |step| {
gesture.set(match step {
BackGesture::Started(event) | BackGesture::Progressed(event) => {
Some(event.progress)
}
BackGesture::Cancelled => None,
});
},
move || {
gesture.set(None);
controller.navigate_up();
},
);
let seek = gesture
.get()
.zip(beneath)
.map(|(fraction, beneath)| CrossfadeSeek {
toward: Some(beneath),
fraction,
});
SeekableCrossfade(top, seek, transition, move |entry| {
if let Some(Entry {
route,
store,
saveables,
..
}) = entry
{
ProvideSaveableScope(saveables, || {
ProvideViewModelStore(store, || content(route));
});
}
});
}