Added toggle for dark mode, changed font to OpenDyslexic, details now changes label on open/close.

This commit is contained in:
Ada Werefox 2023-04-10 18:19:02 -05:00
parent 4fcb8972ff
commit dfeb15394a
13 changed files with 163 additions and 32 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
{{{style_include}}} {{{style_include}}}
</head> </head>
<body> <body class="{{dark_mode}}">
<div id="main">{{{test}}}</div> <div id="main">{{{test}}}</div>
</body> </body>
</html> </html>

View File

@ -8,14 +8,24 @@ extern crate rocket;
/// A module that handles the backend for the site. /// A module that handles the backend for the site.
pub mod web_app_backend { pub mod web_app_backend {
use std::path::{PathBuf, Path};
use rocket::fs::FileServer; use rocket::fs::FileServer;
use rocket::http::{Cookie, CookieJar};
use rocket::response::Redirect;
use rocket::{Build, Rocket}; use rocket::{Build, Rocket};
use rocket_dyn_templates::{context, Template}; use rocket_dyn_templates::{context, Template};
use void_fe::void_app::{self, PoemRequest, VirtualDom}; use void_fe::void_app::{self, PoemRequest, VirtualDom, HomeProps};
#[get("/")] #[get("/")]
async fn index() -> Template { async fn index(cookies: &CookieJar<'_>) -> Template {
let mut vdom = VirtualDom::new(void_app::HomePage); let dark_mode = match cookies.get("dark-mode") {
Some(_) => true,
None => false,
};
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, HomeProps {
dark_mode: dark_mode,
});
let _ = vdom.rebuild(); let _ = vdom.rebuild();
let output = dioxus_ssr::render(&vdom); let output = dioxus_ssr::render(&vdom);
Template::render( Template::render(
@ -23,17 +33,48 @@ pub mod web_app_backend {
context! { context! {
app_title: "A Letter to the Void", app_title: "A Letter to the Void",
style_include: "<link href=/styles/tailwind.min.css rel=stylesheet />", style_include: "<link href=/styles/tailwind.min.css rel=stylesheet />",
test: &output test: &output,
dark_mode: match dark_mode {
true => "dark",
false => ""
},
}, },
) )
} }
#[get("/?set-dark-mode")]
async fn dark_mode_root(cookies: &CookieJar<'_>) -> Redirect {
match cookies.get("dark-mode") {
Some(_) => cookies.remove(Cookie::named("dark-mode")),
None => cookies.add(Cookie::new("dark-mode", "true")),
};
// let path_str = String::from(Path::new("/").join(path).to_str().expect("valid path"));
// let angy = path_str.as_str().to_owned();
Redirect::to("/")
}
#[get("/poem/<entry>?set-dark-mode")]
async fn dark_mode(cookies: &CookieJar<'_>, entry: PathBuf) -> Redirect {
match cookies.get("dark-mode") {
Some(_) => cookies.remove(Cookie::named("dark-mode")),
None => cookies.add(Cookie::new("dark-mode", "true")),
};
let path_str = String::from(Path::new("/poem/").join(entry).to_str().expect("valid path"));
let _angy = path_str.as_str().to_owned();
Redirect::to(path_str.as_str().to_owned().clone())
}
#[get("/poem/<entry>")] #[get("/poem/<entry>")]
async fn poem(entry: &str) -> Template { async fn poem(cookies: &CookieJar<'_>, entry: &str) -> Template {
let dark_mode = match cookies.get("dark-mode") {
Some(_) => true,
None => false,
};
let mut vdom = VirtualDom::new_with_props( let mut vdom = VirtualDom::new_with_props(
void_app::PoemPage, void_app::PoemPage,
PoemRequest { PoemRequest {
slug: entry.to_string(), slug: entry.to_string(),
dark_mode: Some(dark_mode),
}, },
); );
let _ = vdom.rebuild(); let _ = vdom.rebuild();
@ -43,7 +84,11 @@ pub mod web_app_backend {
context! { context! {
app_title: "A Letter to the Void", app_title: "A Letter to the Void",
style_include: "<link href=/styles/tailwind.min.css rel=stylesheet />", style_include: "<link href=/styles/tailwind.min.css rel=stylesheet />",
test: &output test: &output,
dark_mode: match dark_mode {
true => "dark",
false => ""
},
}, },
) )
} }
@ -54,7 +99,7 @@ pub mod web_app_backend {
.mount("/images", FileServer::from("public/images")) .mount("/images", FileServer::from("public/images"))
.mount("/styles", FileServer::from("public/styles")) .mount("/styles", FileServer::from("public/styles"))
.mount("/fonts", FileServer::from("public/fonts")) .mount("/fonts", FileServer::from("public/fonts"))
.mount("/", routes![index, poem]) .mount("/", routes![dark_mode_root, index, dark_mode, poem])
.attach(Template::fairing()) .attach(Template::fairing())
} }
} }

View File

@ -3,6 +3,6 @@
@tailwind utilities; @tailwind utilities;
@font-face { @font-face {
font-family: "DejaVuSansMono"; font-family: "OpenDyslexic";
src: url("/fonts/DejaVuSansMono.ttf"); src: url("/fonts/OpenDyslexic-Regular.otf");
} }

View File

@ -20,6 +20,12 @@ pub mod void_app {
#[derive(PartialEq, Props)] #[derive(PartialEq, Props)]
pub struct PoemRequest { pub struct PoemRequest {
pub slug: String, pub slug: String,
pub dark_mode: Option<bool>,
}
#[derive(PartialEq, Props)]
pub struct HomeProps {
pub dark_mode: bool,
} }
#[derive(PartialEq, Props)] #[derive(PartialEq, Props)]
@ -28,6 +34,7 @@ pub mod void_app {
content: Option<String>, content: Option<String>,
creation_date: Option<String>, creation_date: Option<String>,
slug: Option<String>, slug: Option<String>,
dark_mode: Option<bool>,
} }
#[derive(RustEmbed)] #[derive(RustEmbed)]
@ -57,16 +64,41 @@ pub mod void_app {
} }
/// Renders the app and returns the rendered Element. /// Renders the app and returns the rendered Element.
pub fn HomePage(cx: Scope) -> Element { pub fn HomePage(cx: Scope<HomeProps>) -> Element {
let dark_mode = cx.props.dark_mode.clone();
cx.render(rsx!{ cx.render(rsx!{
div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey", div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
div { class: "container space-y-4 mx-auto p-4", div { class: "container space-y-4 mx-auto p-4",
div { class: "p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light", div { class: "p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light",
p { class: "text-lg text-center", p { class: "flex flex-row mx-auto max-w-full justify-center text-lg text-center",
"A Letter to the Void" "A Letter to the Void&nbsp;"
a { class: "max-h-sm",
href: "?set-dark-mode",
match dark_mode {
true => {
rsx! {
img { class: "",
src: "/images/white_square_button.png",
alt: "A white square button that can toggle dark mode.",
}
}
},
false => {
rsx! {
img { class: "",
src: "/images/black_square_button.png",
alt: "A black square button that can toggle dark mode.",
}
}
},
}
}
} }
} }
PoemList {} PoemList {}
div { class: "p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light",
"This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License"
}
} }
} }
}) })
@ -104,7 +136,8 @@ pub mod void_app {
#[cfg(any(target_family = "unix", target_family = "windows"))] #[cfg(any(target_family = "unix", target_family = "windows"))]
pub fn PoemPage(cx: Scope<PoemRequest>) -> Element { pub fn PoemPage(cx: Scope<PoemRequest>) -> Element {
let slug = cx.props.slug.clone(); let slug = String::from(cx.props.slug.clone());
let dark_mode = cx.props.dark_mode.clone().expect("Dark mode prop not passed.");
cx.render(rsx!{ cx.render(rsx!{
div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey", div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
div { class: "container space-y-4 mx-auto p-4", div { class: "container space-y-4 mx-auto p-4",
@ -115,7 +148,8 @@ pub mod void_app {
} }
} }
} }
GetPoem { slug: slug } } GetPoem { slug: slug, dark_mode: dark_mode }
}
} }
}) })
} }
@ -127,6 +161,7 @@ pub mod void_app {
.segment("slug") .segment("slug")
.expect("No slug specified."), .expect("No slug specified."),
); );
let dark_mode = cx.props.dark_mode.clone().expect("Dark mode prop not passed.");
cx.render(rsx!{ cx.render(rsx!{
div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey", div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
div { class: "container space-y-4 mx-auto p-4", div { class: "container space-y-4 mx-auto p-4",
@ -137,7 +172,7 @@ pub mod void_app {
} }
} }
} }
GetPoem { slug: slug } GetPoem { slug: slug, dark_mode: dark_mode }
} }
} }
}) })
@ -174,8 +209,10 @@ pub mod void_app {
} }
fn GetPoem(cx: Scope<PoemData>) -> Element { fn GetPoem(cx: Scope<PoemData>) -> Element {
let dark_mode = cx.props.dark_mode.clone().expect("Dark mode prop not passed.");
let slug = String::from(cx.props.slug.clone().expect("No slug specified."));
let filename = let filename =
String::from(String::from(cx.props.slug.clone().expect("No slug specified.")) + ".md"); String::from(String::from(slug.clone()) + ".md");
let creation_date = let creation_date =
String::from(String::from("<br>Written on: ") + filename.split("_").next().unwrap()); String::from(String::from("<br>Written on: ") + filename.split("_").next().unwrap());
let poem_content = Poems::get(&filename).expect("Found poem {filename:?}"); let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
@ -189,30 +226,76 @@ pub mod void_app {
let poem_content_to_html_string = let poem_content_to_html_string =
markdown::to_html_with_options(poem_content.as_str(), &Options::gfm()).unwrap(); markdown::to_html_with_options(poem_content.as_str(), &Options::gfm()).unwrap();
cx.render(rsx!{ cx.render(rsx!{
MakePoem{ title: poem_title_to_html_string, content: poem_content_to_html_string, creation_date: creation_date } } MakePoem{ title: poem_title_to_html_string, content: poem_content_to_html_string, creation_date: creation_date, slug: slug, dark_mode: dark_mode } }
) )
} }
#[cfg(any(target_family = "unix", target_family = "windows"))] #[cfg(any(target_family = "unix", target_family = "windows"))]
fn RenderPoemTitle(cx: Scope<PoemData>) -> Element { fn RenderPoemTitle(cx: Scope<PoemData>) -> Element {
let slug = cx.props.slug.clone().expect("Slug prop was not passed.");
let dark_mode = cx.props.dark_mode.clone().expect("Dark mode prop not passed.");
let title = cx.props.title.clone().expect("No title specified."); let title = cx.props.title.clone().expect("No title specified.");
cx.render(rsx!{ cx.render(rsx!{
span { class: "mx-auto max-w-fit flex justify-center bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4", span { class: "mx-auto max-w-fit flex justify-center bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
"{title}" "{title}&nbsp;"
a { class: "max-h-sm",
href: "/poem/{slug}?set-dark-mode",
match dark_mode {
true => {
rsx! {
img { class: "",
src: "/images/white_square_button.png",
alt: "A white square button that can toggle dark mode.",
}
}
},
false => {
rsx! {
img { class: "",
src: "/images/black_square_button.png",
alt: "A black square button that can toggle dark mode.",
}
}
},
}
}
} }
}) })
} }
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
fn RenderPoemTitle(cx: Scope<PoemData>) -> Element { fn RenderPoemTitle(cx: Scope<PoemData>) -> Element {
let slug = cx.props.slug.clone().expect("Slug prop was not passed.");
let dark_mode = cx.props.dark_mode.clone().expect("Dark mode prop not passed.");
let title = cx let title = cx
.props .props
.title .title
.clone() .clone()
.expect("This poem has an empty title."); .expect("This poem has an empty title.");
cx.render(rsx!{ cx.render(rsx!{
p { class: "mx-auto max-w-fit flex justify-center bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4", p { class: "mx-auto max-w-fit flex flex-row justify-center bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
dangerous_inner_html: "{title}", dangerous_inner_html: "{title}&nbsp;",
a { class: "max-h-sm",
href: "/poem/{slug}?set-dark-mode",
match dark_mode {
true => {
rsx! {
img { class: "",
src: "/images/white_square_button.png",
alt: "A white square button that can toggle dark mode.",
}
}
},
false => {
rsx! {
img { class: "",
src: "/images/black_square_button.png",
alt: "A black square button that can toggle dark mode.",
}
}
},
}
}
} }
}) })
} }
@ -226,7 +309,8 @@ pub mod void_app {
.clone() .clone()
.expect("No creation date specified."); .expect("No creation date specified.");
cx.render(rsx! { cx.render(rsx! {
div { class: "font-nerd flex flex-col space-y-4 mx-4 py-4", "{content}{creation_date}" } div { class: "font-nerd flex flex-col space-y-4 mx-4 py-4", "{content}{creation_date} "
}
}) })
} }
@ -247,6 +331,8 @@ pub mod void_app {
} }
fn MakePoem(cx: Scope<PoemData>) -> Element { fn MakePoem(cx: Scope<PoemData>) -> Element {
let slug = String::from(cx.props.slug.clone().expect("Slug prop was not passed."));
let dark_mode = cx.props.dark_mode.clone().expect("Dark mode prop not passed.");
let title = cx.props.title.clone().expect("No title specified."); let title = cx.props.title.clone().expect("No title specified.");
let creation_date = cx let creation_date = cx
.props .props
@ -256,10 +342,9 @@ pub mod void_app {
let content = cx.props.content.clone().expect("No content specified."); let content = cx.props.content.clone().expect("No content specified.");
cx.render(rsx!{ cx.render(rsx!{
div { class: "flex-col space-y-4", div { class: "flex-col space-y-4",
RenderPoemTitle { title: title.clone() } RenderPoemTitle { title: title.clone(), slug: slug, dark_mode: dark_mode }
details { class: "mx-auto max-w-fit space-y-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4", details { class: "group mx-auto max-w-fit space-y-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
summary { class: "flex justify-center p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition", summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-4 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition",
"Open"
} }
RenderPoemElement { content: content.clone(), creation_date: creation_date.clone() } RenderPoemElement { content: content.clone(), creation_date: creation_date.clone() }
} }

View File

@ -8,7 +8,7 @@ module.exports = {
theme: { theme: {
extend: { extend: {
fontFamily: { fontFamily: {
nerd: ["DejaVuSansMono"], nerd: ["OpenDyslexic"],
}, },
colors: { colors: {
"ada-werefox-cyan": { "ada-werefox-cyan": {
@ -105,5 +105,6 @@ module.exports = {
}, },
}, },
}, },
darkMode: 'class',
plugins: [], plugins: [],
}; };