Move the history provider into the context (#3048)
* move history providers into a separate crate * start moving route providers into the renderers * clean up intoroutable * remove into routable * fix router tests * Provide history providers in each renderer * implement nested routers * move the lens out of the history crate * re-export dioxus history trait in the prelude * also re-export the history function * fix history doctests * some light cleanups --------- Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
1 parent
e5a1a62644
commit
281087469a
48 files changed
+875
-1419
No files matched your search
@@ -1,4 +1,4 @@
|
||||
use crate::prelude::*;
|
||||
use crate::{components::FailureExternalNavigation, prelude::*};
|
||||
use dioxus_lib::prelude::*;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -17,42 +17,29 @@ use std::sync::Arc;
|
||||
/// #[route("/")]
|
||||
/// Index {},
|
||||
/// }
|
||||
/// let cfg = RouterConfig::default().history(MemoryHistory::<Route>::default());
|
||||
///
|
||||
/// fn ExternalNavigationFailure() -> Element {
|
||||
/// rsx! {
|
||||
/// "Failed to navigate to external URL"
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let cfg = RouterConfig::<Route>::default().failure_external_navigation(ExternalNavigationFailure);
|
||||
/// ```
|
||||
pub struct RouterConfig<R> {
|
||||
pub(crate) failure_external_navigation: fn() -> Element,
|
||||
pub(crate) history: Option<Box<dyn AnyHistoryProvider>>,
|
||||
pub(crate) on_update: Option<RoutingCallback<R>>,
|
||||
pub(crate) initial_route: Option<R>,
|
||||
}
|
||||
|
||||
impl<R> Default for RouterConfig<R> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
failure_external_navigation: FailureExternalNavigation,
|
||||
history: None,
|
||||
on_update: None,
|
||||
initial_route: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Routable + Clone> RouterConfig<R>
|
||||
where
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
pub(crate) fn take_history(&mut self) -> Box<dyn AnyHistoryProvider> {
|
||||
self.history
|
||||
.take()
|
||||
.unwrap_or_else(|| {
|
||||
let initial_route = self.initial_route.clone().unwrap_or_else(|| "/".parse().unwrap_or_else(|err|
|
||||
panic!("index route does not exist:\n{}\n use MemoryHistory::with_initial_path or RouterConfig::initial_route to set a custom path", err)
|
||||
));
|
||||
default_history(initial_route)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> RouterConfig<R>
|
||||
where
|
||||
R: Routable,
|
||||
@@ -81,24 +68,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`HistoryProvider`] the router should use.
|
||||
///
|
||||
/// Defaults to a different history provider depending on the target platform.
|
||||
pub fn history(self, history: impl HistoryProvider<R> + 'static) -> Self {
|
||||
Self {
|
||||
history: Some(Box::new(AnyHistoryProviderImplWrapper::new(history))),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// The initial route the router should use if no history provider is set.
|
||||
pub fn initial_route(self, route: R) -> Self {
|
||||
Self {
|
||||
initial_route: Some(route),
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// A component to render when an external navigation fails.
|
||||
///
|
||||
/// Defaults to a router-internal component called [`FailureExternalNavigation`]
|
||||
@@ -109,47 +78,3 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the default history provider for the current platform.
|
||||
#[allow(unreachable_code, unused)]
|
||||
fn default_history<R: Routable + Clone>(initial_route: R) -> Box<dyn AnyHistoryProvider>
|
||||
where
|
||||
<R as std::str::FromStr>::Err: std::fmt::Display,
|
||||
{
|
||||
// If we're on the web and have wasm, use the web history provider
|
||||
|
||||
#[cfg(all(target_arch = "wasm32", feature = "web"))]
|
||||
return Box::new(AnyHistoryProviderImplWrapper::new(
|
||||
WebHistory::<R>::default(),
|
||||
));
|
||||
|
||||
// If we're using fullstack and server side rendering, use the memory history provider
|
||||
#[cfg(all(feature = "fullstack", feature = "ssr"))]
|
||||
return Box::new(AnyHistoryProviderImplWrapper::new(
|
||||
MemoryHistory::<R>::with_initial_path(
|
||||
dioxus_fullstack::prelude::server_context()
|
||||
.request_parts()
|
||||
.uri
|
||||
.to_string()
|
||||
.parse()
|
||||
.unwrap_or_else(|err| {
|
||||
tracing::error!("Failed to parse uri: {}", err);
|
||||
"/".parse().unwrap_or_else(|err| {
|
||||
panic!("Failed to parse uri: {}", err);
|
||||
})
|
||||
}),
|
||||
),
|
||||
));
|
||||
|
||||
// If liveview is enabled, use the liveview history provider
|
||||
#[cfg(feature = "liveview")]
|
||||
return Box::new(AnyHistoryProviderImplWrapper::new(
|
||||
LiveviewHistory::new_with_initial_path(initial_route),
|
||||
));
|
||||
|
||||
// If none of the above, use the memory history provider, which is a decent enough fallback
|
||||
// Eventually we want to integrate with the mobile history provider, and other platform providers
|
||||
Box::new(AnyHistoryProviderImplWrapper::new(
|
||||
MemoryHistory::with_initial_path(initial_route),
|
||||
))
|
||||
}
|
||||
Reference in new issue
Block a user