//! # Rust Letter Backend //! //! `rust_letter_be` handles the backend execution using Rocket. #[macro_use] extern crate rocket; /// A module that handles the backend for the site. pub mod web_app_backend { use rocket::fs::FileServer; use rocket::http::{Cookie, CookieJar}; use rocket::response::Redirect; use rocket::{Build, Rocket}; use rocket_dyn_templates::{context, Template}; use void_fe::utils::prop_structs::PoemRequest; use void_fe::void_app::{self, VirtualDom}; use void_fe::utils::user_prefs::*; async fn get_user_prefs(cookies: &CookieJar<'_>) -> UserPrefs { let user_theme = match cookies.get("theme") { Some(c) => match c.value() { "auto" => ThemePref::Auto, "light" => ThemePref::Light, "dark" => ThemePref::Dark, _ => { cookies.remove(Cookie::named("theme")); cookies.add(Cookie::new("theme", "auto")); ThemePref::Auto } }, None => { cookies.add(Cookie::new("theme", "auto")); ThemePref::Auto } }; let user_font = match cookies.get("font") { Some(c) => match c.value() { "nerd" => FontPref::NerdFont, "open" => FontPref::OpenDyslexic, _ => { cookies.remove(Cookie::named("font")); cookies.add(Cookie::new("font", "open")); FontPref::OpenDyslexic } }, None => { cookies.add(Cookie::new("font", "open")); FontPref::OpenDyslexic } }; UserPrefs::new(user_theme, user_font) } async fn set_user_theme(cookies: &CookieJar<'_>, theme: &str) { if theme == "light" || theme == "dark" || theme == "auto" { cookies.remove(Cookie::named("theme")); cookies.add(Cookie::new("theme", format!("{theme}"))); } else { return; } } async fn set_user_font(cookies: &CookieJar<'_>, font: &str) { if font == "nerd" || font == "open" { cookies.remove(Cookie::named("font")); cookies.add(Cookie::new("font", format!("{font}"))); } else { return; } } #[get("/")] async fn index(cookies: &CookieJar<'_>) -> Template { let user_prefs = get_user_prefs(cookies).await; let mut vdom = VirtualDom::new_with_props(void_app::HomePage, user_prefs); let _ = vdom.rebuild(); let output = dioxus_ssr::render(&vdom); Template::render( "index", context! { app_title: "A Letter to the Void", style_include: "", test: &output, dark_mode: "", }, ) } #[get("/", rank = 3)] async fn settings(cookies: &CookieJar<'_>) -> Template { let user_prefs = get_user_prefs(cookies).await; let mut vdom = VirtualDom::new_with_props(void_app::SettingsPage, user_prefs); let _ = vdom.rebuild(); let output = dioxus_ssr::render(&vdom); Template::render( "index", context! { app_title: "Settings", style_include: "", test: &output, dark_mode: "" }, ) } #[get("/?", rank = 2)] async fn theme(cookies: &CookieJar<'_>, theme: &str) -> Redirect { set_user_theme(cookies, theme).await; Redirect::to("/settings") } #[get("/?")] async fn font(cookies: &CookieJar<'_>, font: &str) -> Redirect { set_user_font(cookies, font).await; Redirect::to("/settings") } #[get("/")] async fn poem_list(cookies: &CookieJar<'_>) -> Template { let user_prefs = get_user_prefs(cookies).await; let mut vdom = VirtualDom::new_with_props(void_app::PoemListPage, user_prefs); let _ = vdom.rebuild(); let output = dioxus_ssr::render(&vdom); Template::render( "index", context! { app_title: "A Letter to the Void", style_include: "", test: &output, dark_mode: "", }, ) } #[get("/")] async fn poem(cookies: &CookieJar<'_>, entry: &str) -> Template { let user_prefs = get_user_prefs(cookies).await; let mut vdom = VirtualDom::new_with_props( void_app::PoemPage, PoemRequest { slug: format!("{entry}"), user_prefs, }, ); let _ = vdom.rebuild(); let output = dioxus_ssr::render(&vdom); Template::render( "index", context! { app_title: "A Letter to the Void", style_include: "", test: &output, dark_mode: "", }, ) } /// This runs `rocket::build()` with the needed mounts and routes. pub async fn build_rocket() -> Rocket { rocket::build() .mount("/images", FileServer::from("public/images")) .mount("/styles", FileServer::from("public/styles")) .mount("/fonts", FileServer::from("public/fonts")) .mount("/poems", routes![poem_list, poem]) .mount("/settings", routes![settings, theme, font]) .mount("/", routes![index]) .attach(Template::fairing()) } }