use gloo_net::http::Request; use protocol::UserInfo; use std::rc::Rc; use yew::prelude::*; #[derive(Properties, Clone, PartialEq, Debug)] pub struct ErrorInfoProperties { pub message: String, } #[derive(Clone, Debug, PartialEq, Default)] pub struct AppContext { pub error: Option, pub user: Option, } #[derive(Properties, Clone, PartialEq)] pub struct Props { pub children: Children, } async fn initialize_user_info() -> Result { let response = Request::get("/api/user/info").send().await?; if response.status() == 401 { web_sys::window() .unwrap() .location() .assign("/api/login") .unwrap(); }; let user_info = response.json().await?; Ok(user_info) } #[function_component(AppContextProvider)] pub fn app_context_provider(props: &Props) -> Html { let context: UseStateHandle>> = use_state(|| None); { let context = context.clone(); use_effect_with_deps( move |_| { wasm_bindgen_futures::spawn_local(async move { let previous_context: AppContext = context .as_ref() .map_or(Default::default(), |c| (**c).clone()); context.set(Some(Rc::new(match initialize_user_info().await { Ok(user_info) => AppContext { user: Some(user_info), ..previous_context }, Err(e) => AppContext { error: Some(ErrorInfoProperties { message: format!("Could not contact server"), }), ..previous_context }, }))); }); || () }, (), ); } match &*context { None => html! {

{ "Loading app..." }

}, Some(context) => html! { > {context}> { for props.children.iter() } >> }, } }