flams_router_content/
components.rs

1#![allow(clippy::must_use_candidate)]
2
3use flams_web_utils::components::wait_and_then_fn;
4use ftml_components::{SidebarPosition, config::FtmlConfig};
5use ftml_dom::{FtmlViews, structure::TocSource, utils::css::CssExt};
6use ftml_uris::{
7    DocumentUri, Uri,
8    components::{
9        DocumentUriComponentTuple, DocumentUriComponents, UriComponentTuple, UriComponents,
10        UriComponentsTrait,
11    },
12};
13use leptos::prelude::*;
14use leptos_router::hooks::use_query_map;
15
16#[component(transparent)]
17pub fn URITop() -> AnyView {
18    ftml_dom::global_setup(move || {
19        crate::Views::top(move || {
20            use_query_map().with_untracked(|m| {
21                m.as_document().map_or_else(
22                    |_| match m.as_comps() {
23                        Ok(uri) => view!(<Fragment uri=uri.into() position=SidebarPosition::Next/>)
24                            .into_any(),
25                        Err(e) => flams_web_utils::components::display_error(
26                            format!("Invalid URI: {e}").into(),
27                        )
28                        .into_any(),
29                    },
30                    |doc| view!(<Document doc=doc.into()/>).into_any(),
31                )
32            })
33        })
34    })
35    .into_any()
36}
37
38#[component]
39pub fn DocumentOfTop(uri: Uri) -> AnyView {
40    use leptos_router::components::Redirect;
41    wait_and_then_fn(
42        move || super::server_fns::document_of(uri.clone()),
43        |u| {
44            view!(<Redirect path=format!("/?uri={}",urlencoding::encode(&u.to_string()))/>)
45                .into_any()
46        },
47    )
48    .into_any()
49}
50
51#[component]
52pub fn Fragment(uri: UriComponents, position: SidebarPosition) -> AnyView {
53    use ftml_dom::utils::css::CssExt;
54    // make sure this runs client side rather than server side because of hydration errors
55    // I don't understand.
56    let sig = RwSignal::new(false);
57    Effect::new(move || {
58        sig.track();
59        //#[cfg(feature = "hydrate")]
60        //{
61        sig.set(true);
62        //}
63    });
64    (move || {
65        let uri = uri.clone();
66        if sig.get() {
67            Some(ftml_components::utils::wait_and_then(
68                move || UriComponentTuple::from(uri).apply1(super::server_fns::fragment, None),
69                move |(uri, css, html)| {
70                    for css in css {
71                        css.inject();
72                    }
73                    let uri = match uri {
74                        Uri::Document(d) => {
75                            FtmlConfig::set_toc_source(TocSource::Get);
76                            Some(d.into())
77                        }
78                        Uri::DocumentElement(d) => {
79                            FtmlConfig::set_toc_source(TocSource::None);
80                            Some(d.into())
81                        }
82                        _ => {
83                            FtmlConfig::set_toc_source(TocSource::None);
84                            None
85                        }
86                    };
87                    crate::Views::render_fragment::<crate::backend::FtmlBackend>(
88                        uri,
89                        position,
90                        true,
91                        move || crate::Views::render_ftml(html.into_string(), None).into_any(),
92                    )
93                    .into_any()
94                },
95                |e| view!(<span style="color:red">{e.to_string()}</span>).into_any(),
96            ))
97        } else {
98            None
99        }
100    })
101    .into_any()
102    //})
103}
104
105#[component]
106pub fn Document(doc: DocumentUriComponents) -> AnyView {
107    let sig = RwSignal::new(false);
108    let _ = Effect::new(move || {
109        #[cfg(feature = "hydrate")]
110        {
111            sig.set(true);
112        }
113    });
114    (move || {
115        if sig.get() {
116            let doc = doc.clone();
117            Some(ftml_components::utils::wait_and_then(
118                move || DocumentUriComponentTuple::from(doc).apply(super::server_fns::document),
119                move |(uri, css, html)| {
120                    for c in css {
121                        c.inject();
122                    }
123                    {
124                        FtmlConfig::set_toc_source(TocSource::Get);
125                        crate::Views::setup_document::<crate::backend::FtmlBackend>(
126                            uri,
127                            SidebarPosition::Next,
128                            true,
129                            move || crate::Views::render_ftml(html.into_string(), None).into_any(),
130                        )
131                    }
132                    .into_any()
133                },
134                |e| view!(<span style="color:red">{e.to_string()}</span>).into_any(),
135            ))
136        } else {
137            None
138        }
139    })
140    .into_any()
141}
142
143#[component]
144pub fn DocumentInner(doc: DocumentUriComponents) -> AnyView {
145    let doc: UriComponents = doc.into();
146    wait_and_then_fn(
147        move || UriComponentTuple::from(doc.clone()).apply1(super::server_fns::fragment, None),
148        move |(uri, css, html)| {
149            for css in css {
150                css.inject();
151            }
152            view! {<div>{
153                crate::Views::setup_document::<crate::backend::FtmlBackend>(
154                    DocumentUri::no_doc().clone(),
155                    SidebarPosition::None,
156                    true,
157                    move || crate::Views::render_ftml(html.into_string(),None).into_any()
158                )
159            }</div>}
160            .into_any()
161        },
162    )
163    .into_any()
164}