Browse Source

make navigator non-generic

Evan Almloff 1 year ago
parent
commit
947a153347

+ 1 - 1
packages/router/examples/simple_routes.rs

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

+ 1 - 9
packages/router/src/components/link.rs

@@ -219,15 +219,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
     let do_default = onclick.is_none() || !onclick_only;
     let do_default = onclick.is_none() || !onclick_only;
     let action = move |event| {
     let action = move |event| {
         if do_default && is_router_nav {
         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 {
         if let Some(handler) = onclick {

+ 9 - 11
packages/router/src/contexts/navigator.rs

@@ -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.
 /// A view into the navigation state of a router.
 #[derive(Clone)]
 #[derive(Clone)]
@@ -34,20 +34,18 @@ impl GenericNavigator {
     /// Push a new location.
     /// Push a new location.
     ///
     ///
     /// The previous location will be available to go back to.
     /// 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.
     /// Replace the current location.
     ///
     ///
     /// The previous location will **not** be available to go back to.
     /// 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)
     }
     }
 }
 }

+ 33 - 1
packages/router/src/contexts/router.rs

@@ -7,7 +7,9 @@ use std::{
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 use crate::{
 use crate::{
-    navigation::NavigationTarget, prelude::AnyHistoryProvider, routable::Routable,
+    navigation::NavigationTarget,
+    prelude::{AnyHistoryProvider, IntoRoutable},
+    routable::Routable,
     router_cfg::RouterConfig,
     router_cfg::RouterConfig,
 };
 };
 
 
@@ -203,6 +205,21 @@ impl RouterContext {
         self.change_route()
         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.
     /// The route that is currently active.
     pub fn current<R: Routable>(&self) -> R {
     pub fn current<R: Routable>(&self) -> R {
         *self
         *self
@@ -224,6 +241,21 @@ impl RouterContext {
         (self.any_route_to_string)(route)
         (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.
     /// The prefix that is currently active.
     pub fn prefix(&self) -> Option<String> {
     pub fn prefix(&self) -> Option<String> {
         self.state.read().unwrap().prefix.clone()
         self.state.read().unwrap().prefix.clone()