app.rs
⎇
Raw
1use leptos::prelude::*;
2use wasm_bindgen_futures::spawn_local;
3
4use crate::api::{self, Me};
5use crate::router::{parse_location, Location};
6
7#[derive(Clone, Copy, PartialEq, Debug)]
8pub enum AuthPhase {
9 Loading,
10 Setup,
11 Login,
12 Authed,
13}
14
15#[component]
16pub fn App() -> impl IntoView {
17 let (phase, set_phase) = signal(AuthPhase::Loading);
18 let (me, set_me) = signal(Option::<Me>::None);
19 let (loc, set_loc) = signal(Location::root());
20
21 // The URL hash is the source of truth for the location.
22 {
23 let set_loc = set_loc;
24 set_loc.set(parse_location());
25 let set_loc = set_loc;
26 let _h = window_event_listener(leptos::ev::hashchange, move |_| {
27 set_loc.set(parse_location());
28 });
29 }
30
31 // Initial /me probe: first boot, signed in, or needs login.
32 spawn_local(async move {
33 match api::me().await {
34 Ok(m) => {
35 let first_boot = m.first_boot;
36 set_me.set(Some(m));
37 set_phase.set(if first_boot {
38 AuthPhase::Setup
39 } else {
40 AuthPhase::Authed
41 });
42 }
43 Err(_) => set_phase.set(AuthPhase::Login),
44 }
45 });
46
47 view! {
48 {move || {
49 match phase.get() {
50 AuthPhase::Loading => view! {
51 <div class="center-screen">
52 <p class="muted">"Loading…"</p>
53 </div>
54 }
55 .into_view()
56 .into_any(),
57 AuthPhase::Setup => view! {
58 <crate::views::setup::SetupView set_me=set_me set_phase=set_phase/>
59 }
60 .into_view()
61 .into_any(),
62 AuthPhase::Login => view! {
63 <crate::views::login::LoginView set_me=set_me set_phase=set_phase/>
64 }
65 .into_view()
66 .into_any(),
67 AuthPhase::Authed => view! {
68 <crate::views::shell::ShellView
69 me=me
70 set_me=set_me
71 set_phase=set_phase
72 loc=loc
73 />
74 }
75 .into_view()
76 .into_any(),
77 }
78 }}
79 }
80}
81