use yew::context::ContextHandle;
use yew::prelude::*;
use crate::history::Location;
use crate::navigator::Navigator;
use crate::routable::Routable;
use crate::router::{LocationContext, NavigatorContext};
pub struct LocationHandle {
_inner: ContextHandle<LocationContext>,
}
pub struct NavigatorHandle {
_inner: ContextHandle<NavigatorContext>,
}
pub trait RouterScopeExt {
fn navigator(&self) -> Option<Navigator>;
fn location(&self) -> Option<Location>;
fn route<R>(&self) -> Option<R>
where
R: Routable + 'static;
fn add_location_listener(&self, cb: Callback<Location>) -> Option<LocationHandle>;
fn add_navigator_listener(&self, cb: Callback<Navigator>) -> Option<NavigatorHandle>;
}
impl<COMP: Component> RouterScopeExt for yew::html::Scope<COMP> {
fn navigator(&self) -> Option<Navigator> {
self.context::<NavigatorContext>(Callback::from(|_| {}))
.map(|(m, _)| m.navigator())
}
fn location(&self) -> Option<Location> {
self.context::<LocationContext>(Callback::from(|_| {}))
.map(|(m, _)| m.location())
}
fn route<R>(&self) -> Option<R>
where
R: Routable + 'static,
{
let navigator = self.navigator()?;
let location = self.location()?;
let path = navigator.strip_basename(location.path().into());
R::recognize(&path)
}
fn add_location_listener(&self, cb: Callback<Location>) -> Option<LocationHandle> {
self.context::<LocationContext>(Callback::from(move |m: LocationContext| {
cb.emit(m.location())
}))
.map(|(_, m)| LocationHandle { _inner: m })
}
fn add_navigator_listener(&self, cb: Callback<Navigator>) -> Option<NavigatorHandle> {
self.context::<NavigatorContext>(Callback::from(move |m: NavigatorContext| {
cb.emit(m.navigator())
}))
.map(|(_, m)| NavigatorHandle { _inner: m })
}
}