//! # 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())
}
}