ratatui_kit/hooks/
mod.rs

1#![allow(unused)]
2use crate::{
3    context::ContextStack,
4    render::{ComponentDrawer, ComponentUpdater},
5};
6use std::{
7    any::Any,
8    pin::Pin,
9    task::{Context, Poll},
10};
11mod use_context;
12pub use use_context::*;
13mod use_events;
14pub use use_events::*;
15mod use_future;
16pub use use_future::*;
17mod use_state;
18pub use use_state::*;
19mod use_memo;
20pub use use_memo::*;
21mod use_effect;
22pub use use_effect::*;
23mod use_insert_before;
24pub use use_insert_before::*;
25
26#[cfg(feature = "router")]
27mod use_router;
28#[cfg(feature = "router")]
29pub use use_router::*;
30
31pub trait Hook: Unpin + Send {
32    fn poll_change(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<()> {
33        Poll::Pending
34    }
35
36    fn pre_component_update(&mut self, _updater: &mut ComponentUpdater) {}
37    fn post_component_update(&mut self, _updater: &mut ComponentUpdater) {}
38
39    fn pre_component_draw(&mut self, _drawer: &mut ComponentDrawer) {}
40    fn post_component_draw(&mut self, _drawer: &mut ComponentDrawer) {}
41}
42
43pub(crate) trait AnyHook: Hook {
44    fn any_self_mut(&mut self) -> &mut dyn Any;
45}
46
47impl<T: Hook + 'static> AnyHook for T {
48    fn any_self_mut(&mut self) -> &mut dyn Any {
49        self
50    }
51}
52
53impl Hook for Vec<Box<dyn AnyHook>> {
54    fn poll_change(mut self: Pin<&mut Self>, _cx: &mut Context) -> Poll<()> {
55        let mut is_ready = false;
56        for hook in self.iter_mut() {
57            if Pin::new(&mut **hook).poll_change(_cx).is_ready() {
58                is_ready = true;
59            }
60        }
61
62        if is_ready {
63            Poll::Ready(())
64        } else {
65            Poll::Pending
66        }
67    }
68
69    fn pre_component_update(&mut self, _updater: &mut ComponentUpdater) {
70        for hook in self.iter_mut() {
71            hook.pre_component_update(_updater);
72        }
73    }
74
75    fn post_component_update(&mut self, _updater: &mut ComponentUpdater) {
76        for hook in self.iter_mut() {
77            hook.post_component_update(_updater);
78        }
79    }
80
81    fn pre_component_draw(&mut self, _updater: &mut ComponentDrawer) {
82        for hook in self.iter_mut() {
83            hook.pre_component_draw(_updater);
84        }
85    }
86
87    fn post_component_draw(&mut self, _updater: &mut ComponentDrawer) {
88        for hook in self.iter_mut() {
89            hook.post_component_draw(_updater);
90        }
91    }
92}
93
94pub struct Hooks<'a, 'b: 'a> {
95    hooks: &'a mut Vec<Box<dyn AnyHook>>,
96    first_update: bool,
97    hook_index: usize,
98    pub(crate) context: Option<&'a ContextStack<'b>>,
99}
100
101impl<'a> Hooks<'a, '_> {
102    pub(crate) fn new(hooks: &'a mut Vec<Box<dyn AnyHook>>, first_update: bool) -> Self {
103        Self {
104            hooks,
105            first_update,
106            hook_index: 0,
107            context: None,
108        }
109    }
110
111    pub fn with_context_stack<'c, 'd>(
112        &'c mut self,
113        context: &'c ContextStack<'d>,
114    ) -> Hooks<'c, 'd> {
115        Hooks {
116            hooks: self.hooks,
117            first_update: self.first_update,
118            hook_index: self.hook_index,
119            context: Some(context),
120        }
121    }
122
123    pub fn use_hook<F, H>(&mut self, f: F) -> &mut H
124    where
125        F: FnOnce() -> H,
126        H: Hook + Unpin + 'static,
127    {
128        if self.first_update {
129            self.hooks.push(Box::new(f()));
130        }
131        let idx = self.hook_index;
132        self.hook_index += 1;
133
134        self.hooks
135            .get_mut(idx)
136            .and_then(|hook| hook.any_self_mut().downcast_mut::<H>())
137            .expect("Hook type mismatch, ensure the hook is of the correct type")
138    }
139}