stellation_backend/
root.rs1use 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}