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
@@ -0,0 +1,100 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::History;
|
||||
|
||||
struct MemoryHistoryState {
|
||||
current: String,
|
||||
history: Vec<String>,
|
||||
future: Vec<String>,
|
||||
}
|
||||
|
||||
/// A [`History`] provider that stores all navigation information in memory.
|
||||
pub struct MemoryHistory {
|
||||
state: RefCell<MemoryHistoryState>,
|
||||
}
|
||||
|
||||
impl Default for MemoryHistory {
|
||||
fn default() -> Self {
|
||||
Self::with_initial_path("/")
|
||||
}
|
||||
}
|
||||
|
||||
impl MemoryHistory {
|
||||
/// Create a [`MemoryHistory`] starting at `path`.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use dioxus_router::prelude::*;
|
||||
/// # use dioxus::prelude::*;
|
||||
/// # #[component]
|
||||
/// # fn Index() -> Element { VNode::empty() }
|
||||
/// # #[component]
|
||||
/// # fn OtherPage() -> Element { VNode::empty() }
|
||||
/// #[derive(Clone, Routable, Debug, PartialEq)]
|
||||
/// enum Route {
|
||||
/// #[route("/")]
|
||||
/// Index {},
|
||||
/// #[route("/some-other-page")]
|
||||
/// OtherPage {},
|
||||
/// }
|
||||
///
|
||||
/// let mut history = dioxus_history::MemoryHistory::with_initial_path(Route::Index {});
|
||||
/// assert_eq!(history.current_route(), Route::Index {}.to_string());
|
||||
/// assert_eq!(history.can_go_back(), false);
|
||||
/// ```
|
||||
pub fn with_initial_path(path: impl ToString) -> Self {
|
||||
Self {
|
||||
state: MemoryHistoryState{
|
||||
current: path.to_string().parse().unwrap_or_else(|err| {
|
||||
panic!("index route does not exist:\n{err}\n use MemoryHistory::with_initial_path to set a custom path")
|
||||
}),
|
||||
history: Vec::new(),
|
||||
future: Vec::new(),}.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl History for MemoryHistory {
|
||||
fn current_route(&self) -> String {
|
||||
self.state.borrow().current.clone()
|
||||
}
|
||||
|
||||
fn can_go_back(&self) -> bool {
|
||||
!self.state.borrow().history.is_empty()
|
||||
}
|
||||
|
||||
fn go_back(&self) {
|
||||
let mut write = self.state.borrow_mut();
|
||||
if let Some(last) = write.history.pop() {
|
||||
let old = std::mem::replace(&mut write.current, last);
|
||||
write.future.push(old);
|
||||
}
|
||||
}
|
||||
|
||||
fn can_go_forward(&self) -> bool {
|
||||
!self.state.borrow().future.is_empty()
|
||||
}
|
||||
|
||||
fn go_forward(&self) {
|
||||
let mut write = self.state.borrow_mut();
|
||||
if let Some(next) = write.future.pop() {
|
||||
let old = std::mem::replace(&mut write.current, next);
|
||||
write.history.push(old);
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&self, new: String) {
|
||||
let mut write = self.state.borrow_mut();
|
||||
// don't push the same route twice
|
||||
if write.current == new {
|
||||
return;
|
||||
}
|
||||
let old = std::mem::replace(&mut write.current, new);
|
||||
write.history.push(old);
|
||||
write.future.clear();
|
||||
}
|
||||
|
||||
fn replace(&self, path: String) {
|
||||
let mut write = self.state.borrow_mut();
|
||||
write.current = path;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user