123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- 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>,
- base_path: Option<String>,
- }
- 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(),
- base_path: None,
- }
- }
- /// Set the base path for the history. All routes will be prefixed with this path when rendered.
- ///
- /// ```rust
- /// # use dioxus_history::*;
- /// let mut history = MemoryHistory::default().with_prefix("/my-app");
- ///
- /// // The base path is set to "/my-app"
- /// assert_eq!(history.current_prefix(), Some("/my-app".to_string()));
- /// ```
- pub fn with_prefix(mut self, prefix: impl ToString) -> Self {
- self.base_path = Some(prefix.to_string());
- self
- }
- }
- impl History for MemoryHistory {
- fn current_prefix(&self) -> Option<String> {
- self.base_path.clone()
- }
- 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;
- }
- }
|