lib.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. use std::{
  2. cell::{Ref, RefMut},
  3. fmt::Display,
  4. marker::PhantomData,
  5. ops::{Add, Div, Mul, Sub},
  6. };
  7. mod rt;
  8. use dioxus_core::ScopeState;
  9. pub use rt::*;
  10. pub fn use_init_signal_rt(cx: &ScopeState) {
  11. cx.use_hook(|| {
  12. let rt = claim_rt(cx.schedule_update_any());
  13. cx.provide_context(rt);
  14. });
  15. }
  16. pub fn use_signal<T: 'static>(cx: &ScopeState, f: impl FnOnce() -> T) -> Signal<T> {
  17. cx.use_hook(|| {
  18. let rt: &'static SignalRt = match cx.consume_context() {
  19. Some(rt) => rt,
  20. None => cx.provide_context(claim_rt(cx.schedule_update_any())),
  21. };
  22. let id = rt.init(f());
  23. rt.subscribe(id, cx.scope_id());
  24. struct SignalHook<T> {
  25. signal: Signal<T>,
  26. }
  27. impl<T> Drop for SignalHook<T> {
  28. fn drop(&mut self) {
  29. self.signal.rt.remove(self.signal.id);
  30. }
  31. }
  32. SignalHook {
  33. signal: Signal {
  34. id,
  35. rt,
  36. t: PhantomData,
  37. },
  38. }
  39. })
  40. .signal
  41. }
  42. pub struct Signal<T> {
  43. id: usize,
  44. rt: &'static SignalRt,
  45. t: PhantomData<T>,
  46. }
  47. impl<T: 'static> Signal<T> {
  48. pub fn read(&self) -> Ref<T> {
  49. self.rt.read(self.id)
  50. }
  51. pub fn write(&self) -> RefMut<T> {
  52. self.rt.write(self.id)
  53. }
  54. pub fn set(&mut self, value: T) {
  55. self.rt.set(self.id, value);
  56. }
  57. pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
  58. let write = self.read();
  59. f(&*write)
  60. }
  61. pub fn update<O>(&self, _f: impl FnOnce(&mut T) -> O) -> O {
  62. let mut write = self.write();
  63. _f(&mut *write)
  64. }
  65. }
  66. impl<T: Clone + 'static> Signal<T> {
  67. pub fn get(&self) -> T {
  68. self.rt.get(self.id)
  69. }
  70. }
  71. impl<T: Clone + 'static> std::ops::Deref for Signal<T> {
  72. type Target = dyn Fn() -> T;
  73. fn deref(&self) -> &Self::Target {
  74. self.rt.getter(self.id)
  75. }
  76. }
  77. impl<T> std::clone::Clone for Signal<T> {
  78. fn clone(&self) -> Self {
  79. *self
  80. }
  81. }
  82. impl<T> Copy for Signal<T> {}
  83. impl<T: Display + 'static> Display for Signal<T> {
  84. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  85. self.rt.with::<T, _>(self.id, |v| T::fmt(v, f))
  86. }
  87. }
  88. impl<T: Add<Output = T> + Copy + 'static> std::ops::AddAssign<T> for Signal<T> {
  89. fn add_assign(&mut self, rhs: T) {
  90. self.set(self.get() + rhs);
  91. }
  92. }
  93. impl<T: Sub<Output = T> + Copy + 'static> std::ops::SubAssign<T> for Signal<T> {
  94. fn sub_assign(&mut self, rhs: T) {
  95. self.set(self.get() - rhs);
  96. }
  97. }
  98. impl<T: Mul<Output = T> + Copy + 'static> std::ops::MulAssign<T> for Signal<T> {
  99. fn mul_assign(&mut self, rhs: T) {
  100. self.set(self.get() * rhs);
  101. }
  102. }
  103. impl<T: Div<Output = T> + Copy + 'static> std::ops::DivAssign<T> for Signal<T> {
  104. fn div_assign(&mut self, rhs: T) {
  105. self.set(self.get() / rhs);
  106. }
  107. }