make navigator non-generic

This commit is contained in:
Evan Almloff 2023-07-26 11:08:45 -07:00
parent 0ebcb5f1be
commit 947a153347
4 changed files with 44 additions and 22 deletions

View file

@ -90,7 +90,7 @@ fn Route3(cx: Scope, dynamic: String) -> Element {
"hello world link"
}
button {
onclick: move |_| { navigator.push(NavigationTarget::<Route>::External("https://www.google.com".to_string())); },
onclick: move |_| { navigator.push("https://www.google.com"); },
"google link"
}
p { "Site Map" }

View file

@ -219,15 +219,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
let do_default = onclick.is_none() || !onclick_only;
let action = move |event| {
if do_default && is_router_nav {
let href = match to {
IntoRoutable::FromStr(url) => url.to_string(),
IntoRoutable::Route(route) => router.any_route_to_string(&**route),
};
let parsed_route: NavigationTarget<Box<dyn Any>> = match router.route_from_str(&href) {
Ok(route) => NavigationTarget::Internal(route.into()),
Err(err) => NavigationTarget::External(err),
};
router.push_any(parsed_route);
router.push_any(router.resolve_into_routable(to));
}
if let Some(handler) = onclick {

View file

@ -1,4 +1,4 @@
use crate::prelude::{ExternalNavigationFailure, NavigationTarget, Routable, RouterContext};
use crate::prelude::{ExternalNavigationFailure, IntoRoutable, RouterContext};
/// A view into the navigation state of a router.
#[derive(Clone)]
@ -34,20 +34,18 @@ impl GenericNavigator {
/// Push a new location.
///
/// The previous location will be available to go back to.
pub fn push<R: Routable>(
&self,
target: impl Into<NavigationTarget<R>>,
) -> Option<ExternalNavigationFailure> {
self.0.push(target)
pub fn push(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
let target = target.into();
let as_any_navigation_target = self.0.resolve_into_routable(&target);
self.0.push_any(as_any_navigation_target)
}
/// Replace the current location.
///
/// The previous location will **not** be available to go back to.
pub fn replace<R: Routable>(
&self,
target: impl Into<NavigationTarget<R>>,
) -> Option<ExternalNavigationFailure> {
self.0.replace(target)
pub fn replace(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
let target = target.into();
let as_any_navigation_target = self.0.resolve_into_routable(&target);
self.0.replace_any(as_any_navigation_target)
}
}

View file

@ -7,7 +7,9 @@ use std::{
use dioxus::prelude::*;
use crate::{
navigation::NavigationTarget, prelude::AnyHistoryProvider, routable::Routable,
navigation::NavigationTarget,
prelude::{AnyHistoryProvider, IntoRoutable},
routable::Routable,
router_cfg::RouterConfig,
};
@ -203,6 +205,21 @@ impl RouterContext {
self.change_route()
}
pub(crate) fn replace_any(
&self,
target: NavigationTarget<Box<dyn Any>>,
) -> Option<ExternalNavigationFailure> {
match target {
NavigationTarget::Internal(p) => {
let mut state = self.state_mut();
state.history.replace(p)
}
NavigationTarget::External(e) => return self.external(e),
}
self.change_route()
}
/// The route that is currently active.
pub fn current<R: Routable>(&self) -> R {
*self
@ -224,6 +241,21 @@ impl RouterContext {
(self.any_route_to_string)(route)
}
pub(crate) fn resolve_into_routable(
&self,
into_routable: &IntoRoutable,
) -> NavigationTarget<Box<dyn Any>> {
let href = match into_routable {
IntoRoutable::FromStr(url) => url.to_string(),
IntoRoutable::Route(route) => self.any_route_to_string(&**route),
};
let parsed_route: NavigationTarget<Box<dyn Any>> = match self.route_from_str(&href) {
Ok(route) => NavigationTarget::Internal(route.into()),
Err(err) => NavigationTarget::External(err),
};
parsed_route
}
/// The prefix that is currently active.
pub fn prefix(&self) -> Option<String> {
self.state.read().unwrap().prefix.clone()