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:
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! {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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)),
|
||||
|
||||
Reference in new issue
Block a user