Make deprecated use router (#1260)

* make router props expansion better

* fix router data fields

* make a deprecated use_router hook
This commit is contained in:
ealmloff authored and GitHub committed 2023-07-27 10:32:23 -07:00
1 parent 5e3451a6f2
commit cfd62e274e
12 files changed
+82 -149

No files matched your search

@@ -1,9 +1,11 @@
#[allow(deprecated)]
use crate::hooks::use_router;
use dioxus::prelude::*;
/// The default component to render when an external navigation fails.
#[allow(non_snake_case)]
pub fn FailureExternalNavigation(cx: Scope) -> Element {
#[allow(deprecated)]
let router = use_router(cx);
render! {
+7 -10
View File
@@ -1,5 +1,6 @@
use std::any::Any;
use std::fmt::Debug;
use std::rc::Rc;
use dioxus::prelude::*;
use log::error;
@@ -9,25 +10,24 @@ use crate::prelude::Routable;
use crate::utils::use_router_internal::use_router_internal;
/// Something that can be converted into a [`NavigationTarget`].
#[derive(Clone)]
pub enum IntoRoutable {
/// A raw string target.
FromStr(String),
/// A internal target.
Route(Box<dyn Any>),
Route(Rc<dyn Any>),
}
impl<R: Routable> From<R> for IntoRoutable {
fn from(value: R) -> Self {
IntoRoutable::Route(Box::new(value) as Box<dyn Any>)
IntoRoutable::Route(Rc::new(value) as Rc<dyn Any>)
}
}
impl<R: Routable> From<NavigationTarget<R>> for IntoRoutable {
fn from(value: NavigationTarget<R>) -> Self {
match value {
NavigationTarget::Internal(route) => {
IntoRoutable::Route(Box::new(route) as Box<dyn Any>)
}
NavigationTarget::Internal(route) => IntoRoutable::Route(Rc::new(route) as Rc<dyn Any>),
NavigationTarget::External(url) => IntoRoutable::FromStr(url),
}
}
@@ -197,10 +197,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
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),
Err(err) => NavigationTarget::External(err),
};
let parsed_route: NavigationTarget<Rc<dyn Any>> = router.resolve_into_routable(to.clone());
let ac = active_class
.and_then(|active_class| (href == current_url).then(|| format!(" {active_class}")))
.unwrap_or_default();
@@ -219,7 +216,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 {
router.push_any(router.resolve_into_routable(to));
router.push_any(router.resolve_into_routable(to.clone()));
}
if let Some(handler) = onclick {
+2 -6
View File
@@ -35,17 +35,13 @@ impl Navigator {
///
/// The previous location will be available to go back to.
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)
self.0.push(target)
}
/// Replace the current location.
///
/// The previous location will **not** be available to go back to.
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)
self.0.replace(target)
}
}
+34 -51
View File
@@ -1,6 +1,7 @@
use std::{
any::Any,
collections::HashSet,
rc::Rc,
sync::{Arc, RwLock, RwLockWriteGuard},
};
@@ -18,9 +19,10 @@ use crate::{
pub struct ExternalNavigationFailure(String);
/// A function the router will call after every routing update.
pub(crate) type RoutingCallback<R> = Arc<dyn Fn(LinkContext<R>) -> Option<NavigationTarget<R>>>;
pub(crate) type RoutingCallback<R> =
Arc<dyn Fn(GenericRouterContext<R>) -> Option<NavigationTarget<R>>>;
pub(crate) type AnyRoutingCallback =
Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Box<dyn Any>>>>;
Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Rc<dyn Any>>>>;
struct MutableRouterState {
/// The current prefix.
@@ -70,18 +72,18 @@ impl RouterContext {
routing_callback: cfg.on_update.map(|update| {
Arc::new(move |ctx| {
let ctx = LinkContext {
let ctx = GenericRouterContext {
inner: ctx,
_marker: std::marker::PhantomData,
};
update(ctx).map(|t| match t {
NavigationTarget::Internal(r) => {
NavigationTarget::Internal(Box::new(r) as Box<dyn Any>)
NavigationTarget::Internal(Rc::new(r) as Rc<dyn Any>)
}
NavigationTarget::External(s) => NavigationTarget::External(s),
})
})
as Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Box<dyn Any>>>>
as Arc<dyn Fn(RouterContext) -> Option<NavigationTarget<Rc<dyn Any>>>>
}),
failure_external_navigation: cfg.failure_external_navigation,
@@ -114,7 +116,7 @@ impl RouterContext {
myself
}
pub(crate) fn route_from_str(&self, route: &str) -> Result<Box<dyn Any>, String> {
pub(crate) fn route_from_str(&self, route: &str) -> Result<Rc<dyn Any>, String> {
let state = self.state.read().unwrap();
state.history.parse_route(route)
}
@@ -155,7 +157,7 @@ impl RouterContext {
pub(crate) fn push_any(
&self,
target: NavigationTarget<Box<dyn Any>>,
target: NavigationTarget<Rc<dyn Any>>,
) -> Option<ExternalNavigationFailure> {
match target {
NavigationTarget::Internal(p) => {
@@ -171,15 +173,12 @@ impl RouterContext {
/// 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> {
let target = target.into();
pub fn push(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
let target = self.resolve_into_routable(target.into());
match target {
NavigationTarget::Internal(p) => {
let mut state = self.state_mut();
state.history.push(Box::new(p))
state.history.push(Rc::new(p))
}
NavigationTarget::External(e) => return self.external(e),
}
@@ -190,16 +189,13 @@ impl RouterContext {
/// 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> {
let target = target.into();
pub fn replace(&self, target: impl Into<IntoRoutable>) -> Option<ExternalNavigationFailure> {
let target = self.resolve_into_routable(target.into());
{
let mut state = self.state_mut();
match target {
NavigationTarget::Internal(p) => state.history.replace(Box::new(p)),
NavigationTarget::Internal(p) => state.history.replace(Rc::new(p)),
NavigationTarget::External(e) => return self.external(e),
}
}
@@ -207,31 +203,17 @@ 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
.state
self.state
.read()
.unwrap()
.history
.current_route()
.downcast::<R>()
.unwrap()
.as_ref()
.clone()
}
/// The route that is currently active.
@@ -245,17 +227,18 @@ impl RouterContext {
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),
Err(err) => NavigationTarget::External(err),
};
parsed_route
into_routable: IntoRoutable,
) -> NavigationTarget<Rc<dyn Any>> {
match into_routable {
IntoRoutable::FromStr(url) => {
let parsed_route: NavigationTarget<Rc<dyn Any>> = match self.route_from_str(&url) {
Ok(route) => NavigationTarget::Internal(route),
Err(err) => NavigationTarget::External(err),
};
parsed_route
}
IntoRoutable::Route(route) => NavigationTarget::Internal(route),
}
}
/// The prefix that is currently active.
@@ -332,12 +315,12 @@ impl RouterContext {
}
}
pub struct LinkContext<R> {
pub struct GenericRouterContext<R> {
inner: RouterContext,
_marker: std::marker::PhantomData<R>,
}
impl<R> LinkContext<R>
impl<R> GenericRouterContext<R>
where
R: Routable,
{
@@ -374,7 +357,7 @@ where
&self,
target: impl Into<NavigationTarget<R>>,
) -> Option<ExternalNavigationFailure> {
self.inner.push(target)
self.inner.push(target.into())
}
/// Replace the current location.
@@ -384,7 +367,7 @@ where
&self,
target: impl Into<NavigationTarget<R>>,
) -> Option<ExternalNavigationFailure> {
self.inner.replace(target)
self.inner.replace(target.into())
}
/// The route that is currently active.
+15 -13
View File
@@ -10,7 +10,7 @@
//! 1) [`MemoryHistory`] for desktop/mobile/ssr platforms
//! 2) [`WebHistory`] for web platforms
use std::{any::Any, sync::Arc};
use std::{any::Any, rc::Rc, sync::Arc};
mod memory;
pub use memory::*;
@@ -279,13 +279,13 @@ pub trait HistoryProvider<R: Routable> {
}
pub(crate) trait AnyHistoryProvider {
fn parse_route(&self, route: &str) -> Result<Box<dyn Any>, String>;
fn parse_route(&self, route: &str) -> Result<Rc<dyn Any>, String>;
#[must_use]
fn accepts_type_id(&self, type_id: &std::any::TypeId) -> bool;
#[must_use]
fn current_route(&self) -> Box<dyn Any>;
fn current_route(&self) -> Rc<dyn Any>;
#[must_use]
fn current_prefix(&self) -> Option<String> {
@@ -306,9 +306,9 @@ pub(crate) trait AnyHistoryProvider {
fn go_forward(&mut self);
fn push(&mut self, route: Box<dyn Any>);
fn push(&mut self, route: Rc<dyn Any>);
fn replace(&mut self, path: Box<dyn Any>);
fn replace(&mut self, path: Rc<dyn Any>);
#[allow(unused_variables)]
fn external(&mut self, url: String) -> bool {
@@ -345,19 +345,19 @@ where
<R as std::str::FromStr>::Err: std::fmt::Display,
H: HistoryProvider<R>,
{
fn parse_route(&self, route: &str) -> Result<Box<dyn Any>, String> {
fn parse_route(&self, route: &str) -> Result<Rc<dyn Any>, String> {
R::from_str(route)
.map_err(|err| err.to_string())
.map(|route| Box::new(route) as Box<dyn Any>)
.map(|route| Rc::new(route) as Rc<dyn Any>)
}
fn accepts_type_id(&self, type_id: &std::any::TypeId) -> bool {
type_id == &std::any::TypeId::of::<R>()
}
fn current_route(&self) -> Box<dyn Any> {
fn current_route(&self) -> Rc<dyn Any> {
let route = self.inner.current_route();
Box::new(route)
Rc::new(route)
}
fn current_prefix(&self) -> Option<String> {
@@ -380,12 +380,14 @@ where
self.inner.go_forward()
}
fn push(&mut self, route: Box<dyn Any>) {
self.inner.push(*route.downcast().unwrap())
fn push(&mut self, route: Rc<dyn Any>) {
self.inner
.push(route.downcast::<R>().unwrap().as_ref().clone())
}
fn replace(&mut self, path: Box<dyn Any>) {
self.inner.replace(*path.downcast().unwrap())
fn replace(&mut self, route: Rc<dyn Any>) {
self.inner
.replace(route.downcast::<R>().unwrap().as_ref().clone())
}
fn external(&mut self, url: String) -> bool {
+1
View File
@@ -2,6 +2,7 @@ use dioxus::prelude::ScopeState;
use crate::{prelude::RouterContext, utils::use_router_internal::use_router_internal};
#[deprecated = "prefer the use_navigator or use_route functions"]
/// A hook that provides access to information about the router.
pub fn use_router(cx: &ScopeState) -> &RouterContext {
use_router_internal(cx)
+1 -1
View File
@@ -42,7 +42,7 @@ mod history;
/// Hooks for interacting with the router in components.
pub mod hooks {
mod use_router;
pub(crate) use use_router::*;
pub use use_router::*;
mod use_route;
pub use use_route::*;
+1 -1
View File
@@ -112,7 +112,7 @@ where
/// Defaults to [`None`].
pub fn on_update(
self,
callback: impl Fn(LinkContext<R>) -> Option<NavigationTarget<R>> + 'static,
callback: impl Fn(GenericRouterContext<R>) -> Option<NavigationTarget<R>> + 'static,
) -> Self {
Self {
on_update: Some(Arc::new(callback)),