stellation_backend/
root.rs

1use std::borrow::Cow;
2
3use anymap2::AnyMap;
4use bounce::helmet::{HelmetBridge, StaticWriter};
5use bounce::BounceRoot;
6use stellation_bridge::links::Link;
7use stellation_bridge::state::BridgeState;
8use stellation_bridge::Bridge;
9use yew::prelude::*;
10use yew_router::history::{AnyHistory, History, MemoryHistory};
11use yew_router::Router;
12
13use crate::hooks::HeadContents;
14use crate::props::ServerAppProps;
15use crate::Request;
16
17#[derive(Properties)]
18pub(crate) struct StellationRootProps<CTX, REQ, L>
19where
20    L: Link,
21{
22    pub helmet_writer: StaticWriter,
23    pub server_app_props: ServerAppProps<CTX, REQ>,
24    pub bridge: Option<Bridge<L>>,
25    pub head_contents: HeadContents,
26}
27
28impl<CTX, REQ, L> PartialEq for StellationRootProps<CTX, REQ, L>
29where
30    L: Link,
31{
32    fn eq(&self, other: &Self) -> bool {
33        self.helmet_writer == other.helmet_writer
34            && self.server_app_props == other.server_app_props
35            && self.bridge == other.bridge
36    }
37}
38
39impl<CTX, REQ, L> Clone for StellationRootProps<CTX, REQ, L>
40where
41    L: Link,
42{
43    fn clone(&self) -> Self {
44        Self {
45            helmet_writer: self.helmet_writer.clone(),
46            server_app_props: self.server_app_props.clone(),
47            bridge: self.bridge.clone(),
48            head_contents: self.head_contents.clone(),
49        }
50    }
51}
52
53#[function_component]
54pub(crate) fn StellationRoot<COMP, CTX, REQ, L>(props: &StellationRootProps<CTX, REQ, L>) -> Html
55where
56    COMP: BaseComponent<Properties = ServerAppProps<CTX, REQ>>,
57    REQ: 'static + Request<Context = CTX>,
58    CTX: 'static,
59    L: 'static + Link,
60{
61    let StellationRootProps {
62        helmet_writer,
63        server_app_props,
64        bridge,
65        head_contents,
66        ..
67    } = props.clone();
68
69    let get_init_states = use_callback(
70        move |_, bridge| {
71            let mut states = AnyMap::new();
72            states.insert(head_contents.clone());
73            if let Some(m) = bridge.clone().map(BridgeState::from_bridge) {
74                states.insert(m);
75            }
76
77            states
78        },
79        bridge,
80    );
81
82    let history: AnyHistory = MemoryHistory::new().into();
83    history
84        .push_with_query(
85            server_app_props.path(),
86            server_app_props
87                .queries::<Vec<(Cow<'_, str>, Cow<'_, str>)>>()
88                .expect("failed to parse queries"),
89        )
90        .expect("failed to push path.");
91
92    let children = html! { <COMP ..server_app_props /> };
93
94    html! {
95        <BounceRoot {get_init_states}>
96            <HelmetBridge writer={helmet_writer} />
97            <Router {history}>
98                {children}
99            </Router>
100        </BounceRoot>
101    }
102}