service.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. use gloo::history::{BrowserHistory, History, HistoryListener};
  2. use std::{
  3. cell::{Cell, RefCell},
  4. collections::HashMap,
  5. rc::Rc,
  6. };
  7. use dioxus_core::ScopeId;
  8. pub struct RouterService {
  9. pub(crate) regen_route: Rc<dyn Fn(ScopeId)>,
  10. history: Rc<RefCell<BrowserHistory>>,
  11. registerd_routes: RefCell<RouteSlot>,
  12. slots: Rc<RefCell<Vec<(ScopeId, String)>>>,
  13. root_found: Rc<Cell<bool>>,
  14. cur_root: RefCell<String>,
  15. listener: HistoryListener,
  16. }
  17. enum RouteSlot {
  18. Routes {
  19. // the partial route
  20. partial: String,
  21. // the total route
  22. total: String,
  23. // Connections to other routs
  24. rest: Vec<RouteSlot>,
  25. },
  26. }
  27. impl RouterService {
  28. pub fn new(regen_route: Rc<dyn Fn(ScopeId)>, root_scope: ScopeId) -> Self {
  29. let history = BrowserHistory::default();
  30. let location = history.location();
  31. let path = location.path();
  32. let slots: Rc<RefCell<Vec<(ScopeId, String)>>> = Default::default();
  33. let _slots = slots.clone();
  34. let root_found = Rc::new(Cell::new(false));
  35. let regen = regen_route.clone();
  36. let _root_found = root_found.clone();
  37. let listener = history.listen(move || {
  38. _root_found.set(false);
  39. // checking if the route is valid is cheap, so we do it
  40. for (slot, _) in _slots.borrow_mut().iter().rev() {
  41. log::debug!("regenerating slot {:?}", slot);
  42. regen(*slot);
  43. }
  44. });
  45. Self {
  46. registerd_routes: RefCell::new(RouteSlot::Routes {
  47. partial: String::from("/"),
  48. total: String::from("/"),
  49. rest: Vec::new(),
  50. }),
  51. root_found,
  52. history: Rc::new(RefCell::new(history)),
  53. regen_route,
  54. slots,
  55. cur_root: RefCell::new(path.to_string()),
  56. listener,
  57. }
  58. }
  59. pub fn push_route(&self, route: &str) {
  60. self.history.borrow_mut().push(route);
  61. }
  62. pub fn register_total_route(&self, route: String, scope: ScopeId, fallback: bool) {
  63. self.slots.borrow_mut().push((scope, route));
  64. }
  65. pub fn should_render(&self, scope: ScopeId) -> bool {
  66. if self.root_found.get() {
  67. return false;
  68. }
  69. let location = self.history.borrow().location();
  70. let path = location.path();
  71. let roots = self.slots.borrow();
  72. let root = roots.iter().find(|(id, route)| id == &scope);
  73. // fallback logic
  74. match root {
  75. Some((_id, route)) => {
  76. if route == path {
  77. self.root_found.set(true);
  78. true
  79. } else {
  80. if route == "" {
  81. self.root_found.set(true);
  82. true
  83. } else {
  84. false
  85. }
  86. }
  87. }
  88. None => false,
  89. }
  90. }
  91. }
  92. pub struct RouterCfg {
  93. initial_route: String,
  94. }
  95. impl RouterCfg {
  96. pub fn new(initial_route: String) -> Self {
  97. Self { initial_route }
  98. }
  99. }