stellation_backend/
hooks.rs1use std::cell::RefCell;
4use std::fmt;
5use std::rc::Rc;
6
7use bounce::{use_atom_value, Atom};
8use futures::future::LocalBoxFuture;
9use futures::{Future, FutureExt};
10use yew::prelude::*;
11
12type RenderAppendHead = Box<dyn FnOnce() -> LocalBoxFuture<'static, String>>;
13
14#[derive(Atom, Clone)]
15pub(crate) struct HeadContents {
16 inner: Rc<RefCell<Vec<RenderAppendHead>>>,
17}
18
19impl Default for HeadContents {
20 fn default() -> Self {
21 panic!("Attempting to use use_append_head_content on client side rendering!");
22 }
23}
24
25impl PartialEq for HeadContents {
26 fn eq(&self, _other: &Self) -> bool {
28 true
29 }
30}
31
32impl Eq for HeadContents {}
33
34impl HeadContents {
35 pub(crate) fn new() -> Self {
36 Self {
37 inner: Rc::default(),
38 }
39 }
40
41 pub(crate) async fn render_into(&self, w: &mut dyn fmt::Write) {
42 for i in self.inner.take() {
43 let _ = write!(w, "{}", i().await);
44 }
45 }
46}
47
48#[hook]
67pub fn use_append_head_content<F, Fut>(f: F)
68where
69 F: 'static + FnOnce() -> Fut,
70 Fut: 'static + Future<Output = String>,
71{
72 let boxed_f: RenderAppendHead = Box::new(move || f().boxed_local());
73 let head_contents = use_atom_value::<HeadContents>();
74
75 head_contents.inner.borrow_mut().push(boxed_f);
76}