diff --git a/packages/router/Cargo.toml b/packages/router/Cargo.toml index abf207438..064947908 100644 --- a/packages/router/Cargo.toml +++ b/packages/router/Cargo.toml @@ -11,9 +11,14 @@ keywords = ["dom", "ui", "gui", "react", "wasm"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-rwlock = "1.3.0" dioxus = { path="../dioxus" } dioxus-router-core = { path = "../router-core"} +futures-channel = "0.3.25" +futures-util = "0.3.25" # for wasm [features] +regex = ["dioxus-router-core/regex"] +serde = ["dioxus-router-core/serde"] diff --git a/packages/router/src/contexts/router.rs b/packages/router/src/contexts/router.rs new file mode 100644 index 000000000..3755ddc96 --- /dev/null +++ b/packages/router/src/contexts/router.rs @@ -0,0 +1,12 @@ +use std::sync::Arc; + +use async_rwlock::RwLock; +use dioxus::prelude::{Component, ScopeId}; +use dioxus_router_core::{RouterMessage, RouterState}; +use futures_channel::mpsc::UnboundedSender; + +#[derive(Clone)] +pub(crate) struct RouterContext { + pub(crate) state: Arc>>, + pub(crate) sender: UnboundedSender>, +} diff --git a/packages/router/src/hooks/use_router.rs b/packages/router/src/hooks/use_router.rs new file mode 100644 index 000000000..ed55e74d1 --- /dev/null +++ b/packages/router/src/hooks/use_router.rs @@ -0,0 +1,81 @@ +use async_rwlock::RwLockReadGuard; +use dioxus::prelude::*; +use dioxus_router_core::{ + history::{HistoryProvider, MemoryHistory}, + routes::{ContentAtom, Segment}, + RouterService, RouterState, RoutingCallback, +}; + +use crate::contexts::router::RouterContext; + +pub fn use_router<'a>( + cx: &'a ScopeState, + cfg: &dyn Fn() -> RouterConfiguration, + content: &dyn Fn() -> Segment, +) -> (RwLockReadGuard<'a, RouterState>, ()) { + let (service, state, sender) = cx.use_hook(|| { + let cfg = cfg(); + let content = content(); + + let (mut service, sender, state) = RouterService::new( + content, + cfg.history, + cx.schedule_update_any(), + cfg.on_update, + cfg.failure_external_navigation, + cfg.failure_named_navigation, + cfg.failure_redirection_limit, + ); + + cx.provide_context(RouterContext { + state: state.clone(), + sender: sender.clone(), + }); + + ( + if cfg.synchronous { + Some(service) + } else { + cx.spawn(async move { service.run().await }); + None + }, + state, + sender, + ) + }); + + if let Some(service) = service { + service.run_current(); + } + + ( + loop { + if let Some(state) = state.try_read() { + break state; + } + }, + (), + ) +} + +pub struct RouterConfiguration { + pub failure_external_navigation: ContentAtom, + pub failure_named_navigation: ContentAtom, + pub failure_redirection_limit: ContentAtom, + pub history: Box, + pub on_update: Option>, + pub synchronous: bool, +} + +impl Default for RouterConfiguration { + fn default() -> Self { + Self { + failure_external_navigation: todo!("provide default component for external navigation"), + failure_named_navigation: todo!("provide default component for named navigation"), + failure_redirection_limit: todo!("provide default component for redirection limit"), + history: Box::new(MemoryHistory::default()), + on_update: None, + synchronous: false, + } + } +} diff --git a/packages/router/src/lib.rs b/packages/router/src/lib.rs index eb952d6b2..8cbf51900 100644 --- a/packages/router/src/lib.rs +++ b/packages/router/src/lib.rs @@ -1,3 +1,12 @@ +pub(crate) mod contexts { + pub(crate) mod router; +} + +pub mod hooks { + mod use_router; + pub use use_router::*; +} + pub mod prelude { pub use dioxus_router_core::prelude::*; }