1
0

router.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. use dioxus_lib::prelude::*;
  2. use std::{cell::RefCell, str::FromStr};
  3. use crate::{prelude::Outlet, routable::Routable, router_cfg::RouterConfig};
  4. /// The config for [`Router`].
  5. pub struct RouterConfigFactory<R: Routable> {
  6. #[allow(clippy::type_complexity)]
  7. config: RefCell<Option<Box<dyn FnOnce() -> RouterConfig<R>>>>,
  8. }
  9. #[cfg(feature = "serde")]
  10. impl<R: Routable> Default for RouterConfigFactory<R>
  11. where
  12. <R as FromStr>::Err: std::fmt::Display,
  13. R: serde::Serialize + serde::de::DeserializeOwned,
  14. {
  15. fn default() -> Self {
  16. Self::from(RouterConfig::default)
  17. }
  18. }
  19. #[cfg(not(feature = "serde"))]
  20. impl<R: Routable> Default for RouterConfigFactory<R>
  21. where
  22. <R as FromStr>::Err: std::fmt::Display,
  23. {
  24. fn default() -> Self {
  25. Self::from(RouterConfig::default)
  26. }
  27. }
  28. impl<R: Routable, F: FnOnce() -> RouterConfig<R> + 'static> From<F> for RouterConfigFactory<R> {
  29. fn from(value: F) -> Self {
  30. Self {
  31. config: RefCell::new(Some(Box::new(value))),
  32. }
  33. }
  34. }
  35. #[cfg(feature = "serde")]
  36. /// The props for [`Router`].
  37. #[derive(Props)]
  38. pub struct RouterProps<R: Routable>
  39. where
  40. <R as FromStr>::Err: std::fmt::Display,
  41. R: serde::Serialize + serde::de::DeserializeOwned,
  42. {
  43. #[props(default, into)]
  44. config: RouterConfigFactory<R>,
  45. }
  46. #[cfg(not(feature = "serde"))]
  47. /// The props for [`Router`].
  48. #[derive(Props)]
  49. pub struct RouterProps<R: Routable>
  50. where
  51. <R as FromStr>::Err: std::fmt::Display,
  52. {
  53. #[props(default, into)]
  54. config: RouterConfigFactory<R>,
  55. }
  56. impl<T: Routable> Clone for RouterProps<T>
  57. where
  58. <T as FromStr>::Err: std::fmt::Display,
  59. {
  60. fn clone(&self) -> Self {
  61. todo!()
  62. }
  63. }
  64. #[cfg(not(feature = "serde"))]
  65. impl<R: Routable> Default for RouterProps<R>
  66. where
  67. <R as FromStr>::Err: std::fmt::Display,
  68. {
  69. fn default() -> Self {
  70. Self {
  71. config: RouterConfigFactory::default(),
  72. }
  73. }
  74. }
  75. #[cfg(feature = "serde")]
  76. impl<R: Routable> Default for RouterProps<R>
  77. where
  78. <R as FromStr>::Err: std::fmt::Display,
  79. R: serde::Serialize + serde::de::DeserializeOwned,
  80. {
  81. fn default() -> Self {
  82. Self {
  83. config: RouterConfigFactory::default(),
  84. }
  85. }
  86. }
  87. #[cfg(not(feature = "serde"))]
  88. impl<R: Routable> PartialEq for RouterProps<R>
  89. where
  90. <R as FromStr>::Err: std::fmt::Display,
  91. {
  92. fn eq(&self, _: &Self) -> bool {
  93. // prevent the router from re-rendering when the initial url or config changes
  94. true
  95. }
  96. }
  97. #[cfg(feature = "serde")]
  98. impl<R: Routable> PartialEq for RouterProps<R>
  99. where
  100. <R as FromStr>::Err: std::fmt::Display,
  101. R: serde::Serialize + serde::de::DeserializeOwned,
  102. {
  103. fn eq(&self, _: &Self) -> bool {
  104. // prevent the router from re-rendering when the initial url or config changes
  105. true
  106. }
  107. }
  108. #[cfg(not(feature = "serde"))]
  109. /// A component that renders the current route.
  110. pub fn Router<R: Routable + Clone>(props: RouterProps<R>) -> Element
  111. where
  112. <R as FromStr>::Err: std::fmt::Display,
  113. {
  114. use crate::prelude::{outlet::OutletContext, RouterContext};
  115. todo!();
  116. // use_context_provider(|| {
  117. // RouterContext::new(
  118. // (props
  119. // .config
  120. // .config
  121. // .take()
  122. // .expect("use_context_provider ran twice"))(),
  123. // schedule_update_any(),
  124. // )
  125. // });
  126. // use_context_provider(|| OutletContext::<R> {
  127. // current_level: 0,
  128. // _marker: std::marker::PhantomData,
  129. // });
  130. render! { Outlet::<R> {} }
  131. }
  132. #[cfg(feature = "serde")]
  133. /// A component that renders the current route.
  134. pub fn Router<R: Routable + Clone>(cx: Scope<RouterProps<R>>) -> Element
  135. where
  136. <R as FromStr>::Err: std::fmt::Display,
  137. R: serde::Serialize + serde::de::DeserializeOwned,
  138. {
  139. use_context_provider(|| {
  140. RouterContext::new(
  141. (cx.props
  142. .config
  143. .config
  144. .take()
  145. .expect("use_context_provider ran twice"))(),
  146. cx.schedule_update_any(),
  147. )
  148. });
  149. use_context_provider(|| OutletContext::<R> {
  150. current_level: 0,
  151. _marker: std::marker::PhantomData,
  152. });
  153. render! { Outlet::<R> {} }
  154. }