Compare commits

..

2 Commits

17 changed files with 277 additions and 208 deletions

View File

@ -11,13 +11,17 @@ members = [
] ]
[workspace.dependencies] [workspace.dependencies]
rocket = "=0.5.0-rc.3" rocket = "=0.5.0"
dioxus = "0.3.2" dioxus = "0.5.0-alpha.0"
markdown = "1.0.0-alpha.7" markdown = "1.0.0-alpha.16"
dioxus-ssr = "0.3.0" dioxus-ssr = "0.5.0-alpha.0"
rust-embed = { version = "6.6.1" } rust-embed = { version = "8.3.0" }
once_cell = "1.17.1" once_cell = "1.17.1"
[dependencies] [dependencies]
void-be = { path = "./void-be" } void-be = { path = "./void-be" }
rocket = { workspace = true } rocket = { workspace = true }
[dependencies.dioxus]
version = "0.5.0-alpha.0"
features = ["router"]

File diff suppressed because one or more lines are too long

View File

@ -16,5 +16,5 @@ rocket = { workspace = true }
# Needed to enable handlebar template support # Needed to enable handlebar template support
[dependencies.rocket_dyn_templates] [dependencies.rocket_dyn_templates]
version = "=0.1.0-rc.3" version = "=0.1.0"
features = ["handlebars"] features = ["handlebars"]

View File

@ -14,9 +14,11 @@ pub mod web_app_backend {
use rocket::response::Redirect; 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::utils::prop_structs::{PoemDatabase, VoidProps}; use void_fe::utils::prop_structs::{PoemDatabase, VoidProps, ContentProps};
use void_fe::utils::user_prefs::*; use void_fe::utils::user_prefs::*;
use void_fe::void_app::{self, VirtualDom}; use void_fe::void_app::{self, VirtualDom};
pub use void_fe::components::void_content::RenderContent;
use void_fe::utils::helpers::get_homepage_paragraph;
static POEM_DATABASE: OnceCell<PoemDatabase> = OnceCell::new(); static POEM_DATABASE: OnceCell<PoemDatabase> = OnceCell::new();
@ -27,7 +29,7 @@ pub mod web_app_backend {
"light" => ThemePref::Light, "light" => ThemePref::Light,
"dark" => ThemePref::Dark, "dark" => ThemePref::Dark,
_ => { _ => {
cookies.remove(Cookie::named("theme")); cookies.remove("theme");
cookies.add(Cookie::new("theme", "auto")); cookies.add(Cookie::new("theme", "auto"));
ThemePref::Auto ThemePref::Auto
} }
@ -42,7 +44,7 @@ pub mod web_app_backend {
"nerd" => FontPref::NerdFont, "nerd" => FontPref::NerdFont,
"open" => FontPref::OpenDyslexic, "open" => FontPref::OpenDyslexic,
_ => { _ => {
cookies.remove(Cookie::named("font")); cookies.remove("font");
cookies.add(Cookie::new("font", "open")); cookies.add(Cookie::new("font", "open"));
FontPref::OpenDyslexic FontPref::OpenDyslexic
} }
@ -57,7 +59,7 @@ pub mod web_app_backend {
async fn set_user_theme(cookies: &CookieJar<'_>, theme: &str) { async fn set_user_theme(cookies: &CookieJar<'_>, theme: &str) {
if theme == "light" || theme == "dark" || theme == "auto" { if theme == "light" || theme == "dark" || theme == "auto" {
cookies.remove(Cookie::named("theme")); cookies.remove("theme");
cookies.add(Cookie::new("theme", format!("{theme}"))); cookies.add(Cookie::new("theme", format!("{theme}")));
} else { } else {
return; return;
@ -66,7 +68,7 @@ pub mod web_app_backend {
async fn set_user_font(cookies: &CookieJar<'_>, font: &str) { async fn set_user_font(cookies: &CookieJar<'_>, font: &str) {
if font == "nerd" || font == "open" { if font == "nerd" || font == "open" {
cookies.remove(Cookie::named("font")); cookies.remove("font");
cookies.add(Cookie::new("font", format!("{font}"))); cookies.add(Cookie::new("font", format!("{font}")));
} else { } else {
return; return;
@ -84,8 +86,13 @@ pub mod web_app_backend {
.clone(), .clone(),
user_prefs: user_prefs, user_prefs: user_prefs,
}; };
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, void_props); // let content_props = ContentProps {
let _ = vdom.rebuild(); // content: get_homepage_paragraph(),
// user_prefs: user_prefs
// };
// let mut vdom = VirtualDom::new_with_props(void_app::HomePage, void_props);
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, void_fe::void_app::HomePageProps { props: void_props });
let _ = vdom.rebuild_in_place();
let output = dioxus_ssr::render(&vdom); let output = dioxus_ssr::render(&vdom);
Template::render( Template::render(
"index", "index",
@ -102,7 +109,7 @@ pub mod web_app_backend {
async fn settings(cookies: &CookieJar<'_>) -> Template { async fn settings(cookies: &CookieJar<'_>) -> Template {
let user_prefs = get_user_prefs(cookies).await; let user_prefs = get_user_prefs(cookies).await;
let mut vdom = VirtualDom::new_with_props(void_app::SettingsPage, user_prefs); let mut vdom = VirtualDom::new_with_props(void_app::SettingsPage, user_prefs);
let _ = vdom.rebuild(); let _ = vdom.rebuild_in_place();
let output = dioxus_ssr::render(&vdom); let output = dioxus_ssr::render(&vdom);
Template::render( Template::render(
"index", "index",
@ -139,7 +146,7 @@ pub mod web_app_backend {
user_prefs: user_prefs, user_prefs: user_prefs,
}; };
let mut vdom = VirtualDom::new_with_props(void_app::PoemListPage, void_props); let mut vdom = VirtualDom::new_with_props(void_app::PoemListPage, void_props);
let _ = vdom.rebuild(); let _ = vdom.rebuild_in_place();
let output = dioxus_ssr::render(&vdom); let output = dioxus_ssr::render(&vdom);
Template::render( Template::render(
"index", "index",
@ -164,7 +171,7 @@ pub mod web_app_backend {
user_prefs: user_prefs, user_prefs: user_prefs,
}; };
let mut vdom = VirtualDom::new_with_props(void_app::PoemPage, void_props); let mut vdom = VirtualDom::new_with_props(void_app::PoemPage, void_props);
let _ = vdom.rebuild(); let _ = vdom.rebuild_in_place();
let output = dioxus_ssr::render(&vdom); let output = dioxus_ssr::render(&vdom);
Template::render( Template::render(
"index", "index",

View File

@ -2,15 +2,18 @@
"rust-analyzer.cargo.extraArgs": ["--profile", "rust-analyzer"], "rust-analyzer.cargo.extraArgs": ["--profile", "rust-analyzer"],
// "rust-analyzer.cargo.buildScripts.invocationLocation": "root", // "rust-analyzer.cargo.buildScripts.invocationLocation": "root",
"rust-analyzer.cargo.target": "wasm32-unknown-unknown", "rust-analyzer.cargo.target": "wasm32-unknown-unknown",
// "rust-analyzer.cargo.buildScripts.overrideCommand": ["dioxus", "build"], "rust-analyzer.cargo.buildScripts.overrideCommand": ["dx", "build"],
"rust-analyzer.check.overrideCommand": ["cargo", "check", "--quiet", "--message-format=json"], "rust-analyzer.check.overrideCommand": ["dx", "check", "--quiet", "--message-format=json"],
"rust-analyzer.check.invocationLocation": "root", "rust-analyzer.check.invocationLocation": "root",
"rust-analyzer.check.targets": ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"], "rust-analyzer.check.targets": ["wasm32-unknown-unknown"],
// "rust-analyzer.runnables.command": "dioxus serve", "rust-analyzer.runnables.command": "dx serve",
"rust-analyzer.cargo.buildScripts.enable": false, "rust-analyzer.cargo.buildScripts.enable": false,
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"./Cargo.toml" "./Cargo.toml"
], ],
"rust-analyzer.diagnostics.disabled": ["unresolved-proc-macro"],
// "rust-analyzer.procMacro.enable": true,
// "rust-analyzer.procMacro.attributes.enable": true,
"rust-analyzer.showUnlinkedFileNotification": false, "rust-analyzer.showUnlinkedFileNotification": false,
"rust-analyzer.hover.actions.run.enable": true, "rust-analyzer.hover.actions.run.enable": true,
"rust-analyzer.hover.actions.debug.enable": true, "rust-analyzer.hover.actions.debug.enable": true,

View File

@ -7,30 +7,36 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
dioxus = { workspace = true } # dioxus = { workspace = true }
markdown = { workspace = true } markdown = { workspace = true }
dioxus-web = "0.3.1" once_cell = { workspace = true }
dioxus-autofmt = "0.3.0" # dioxus-web = "0.5.0-alpha.0"
dioxus-autofmt = "0.5.0-alpha.0"
# WebAssembly Debug # WebAssembly Debug
wasm-logger = "0.2.0" wasm-logger = "0.2.0"
console_error_panic_hook = "0.1.7" console_error_panic_hook = "0.1.7"
log = "0.4.17" log = "0.4.17"
dioxus-helmet = "0.2.4" dioxus-helmet = "0.2.4"
dioxus-use-storage = "0.3.0" dioxus-use-storage = "0.3.1"
rand = "0.8.5" rand = "0.8.5"
dioxus-html-macro = "0.3.0"
[dependencies.getrandom] [dependencies.getrandom]
version = "0.2.9" version = "0.2.12"
features = ["js"] features = ["js"]
[dependencies.serde] [dependencies.serde]
version = "1.0.160" version = "1.0.197"
features = ["derive"] features = ["derive"]
[dependencies.dioxus-router] [dependencies.dioxus-router]
version = "0.3.0" version = "0.5.0-alpha.0"
features = ["query", "web"] features = ["web"]
[dependencies.rust-embed] [dependencies.rust-embed]
version = "6.6.1" version = "8.3.0"
features = ["debug-embed"] features = ["debug-embed"]
[dependencies.dioxus]
version = "0.5.0-alpha.0"
features = ["web"]

View File

@ -1,72 +1,73 @@
use crate::utils::prop_structs::PoemDatabase;
use super::super::utils::{ use super::super::utils::{
prop_structs::{ButtonProps, ContentChildren}, prop_structs::{ButtonProps, ContentChildren, VoidProps},
user_prefs::{ThemedComponent, UserPrefs}, user_prefs::{ThemedComponent, UserPrefs},
}; };
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_router::prelude::*;
#[cfg(target_family = "wasm")] pub fn BackToHomePage(props: UserPrefs) -> Element {
use dioxus_router::Link; let (user_theme, user_font) = props.clone().get_pref_classes(ThemedComponent::Button);
pub fn BackToHomePage(cx: Scope<UserPrefs>) -> Element {
let (user_theme, user_font) = cx.props.clone().get_pref_classes(ThemedComponent::Button);
#[cfg(any(target_family = "windows", target_family = "unix"))] #[cfg(any(target_family = "windows", target_family = "unix"))]
return cx.render(rsx!{ return rsx! {
a { class: "flex justify-center p-4 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}", a { class: "flex justify-center p-4 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}",
href: "/", href: "/",
p { p {
"Back to the homepage" "Back to the homepage"
} }
} }
}); };
let mut poem_database = PoemDatabase::new();
poem_database.build_poem_database();
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
return cx.render(rsx!{ return render! {
Link { class: "flex justify-center p-4 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}", Link { class: "flex justify-center p-4 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}",
to: "/", to: crate::void_app::Route::HomePage { props:VoidProps{slug: Some("/".to_string()), poem_database: poem_database.clone(), user_prefs: props.clone(),}},
p { p {
"Back to the homepage" "Back to the homepage"
} }
} }
}); };
} }
pub fn NavigationButton(cx: Scope<ButtonProps>) -> Element { pub fn NavigationButton(props: ButtonProps) -> Element {
let (user_theme, mut user_font) = cx let (user_theme, mut user_font) = props
.props
.user_prefs .user_prefs
.clone() .clone()
.get_pref_classes(ThemedComponent::Button); .get_pref_classes(ThemedComponent::Button);
let title = cx.props.title.clone(); let title = props.title.clone();
let title_ref = title.as_str(); let title_ref = title.as_str();
let slug = cx.props.slug.clone(); let slug = props.slug.clone();
let slug_ref = slug.as_str(); let slug_ref = slug.as_str();
match &cx.props.override_font { match props.override_font {
Some(font) => user_font = font.clone(), Some(font) => user_font = font.clone(),
None => (), None => (),
} }
#[cfg(any(target_family = "windows", target_family = "unix"))] #[cfg(any(target_family = "windows", target_family = "unix"))]
return cx.render(rsx!{ return rsx! {
a { class: "flex basis-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}", a { class: "flex basis-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}",
href: "{slug_ref}", href: "{slug_ref}",
"{title_ref}" dangerous_inner_html: "{title_ref}",
} }
}); };
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
return cx.render(rsx!{ return rsx! {
Link { class: "flex basis-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}", Link { class: "flex basis-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 hover:animate-yip transition {user_theme} {user_font}",
to: "{slug_ref}", to: "{slug_ref}",
div { div {
dangerous_inner_html: "{title_ref}", dangerous_inner_html: "{title_ref}",
} }
} }
}); };
} }
pub fn ButtonGroup<'a>(cx: Scope<'a, ContentChildren<'a>>) -> Element { pub fn ButtonGroup(props: ContentChildren) -> Element {
cx.render(rsx! { rsx! {
div { class: "flex md:flex-row md:space-y-0 flex-col space-y-4", div { class: "flex md:flex-row md:space-y-0 flex-col space-y-4",
&cx.props.children {props.children}
} }
}) }
} }

View File

@ -1,21 +1,14 @@
// Might wanna move stuff form `void_poem.rs` into here... // Might wanna move stuff form `void_poem.rs` into here...
use crate::utils::prop_structs::{ContentProps};
use super::super::utils::user_prefs::ThemedComponent; use super::super::utils::user_prefs::ThemedComponent;
use crate::utils::prop_structs::ContentProps;
use dioxus::prelude::*; use dioxus::prelude::*;
pub fn RenderContent(cx: Scope<ContentProps>) -> Element { pub fn RenderContent(props: ContentProps) -> Element {
let (user_theme, user_font) = cx.props.user_prefs.get_pref_classes(ThemedComponent::Card); let (user_theme, user_font) = props.user_prefs.get_pref_classes(ThemedComponent::Card);
let content = &cx.props.content; let content = props.content;
#[cfg(any(target_family = "windows", target_family = "unix"))] return rsx! {
return cx.render(rsx!{
div { class: "flex p-4 md:pl-8 md:pr-8 ml-4 mr-4 text-md text-center ring-4 {user_theme} {user_font}",
"{content}",
}
});
#[cfg(target_family = "wasm")]
return cx.render(rsx!{
div { class: "flex p-4 md:pl-8 md:pr-8 ml-4 mr-4 text-md text-center ring-4 {user_theme} {user_font}", div { class: "flex p-4 md:pl-8 md:pr-8 ml-4 mr-4 text-md text-center ring-4 {user_theme} {user_font}",
dangerous_inner_html: "{content}", dangerous_inner_html: "{content}",
} }
}); };
} }

View File

@ -4,17 +4,17 @@ use crate::{
}; };
use dioxus::prelude::*; use dioxus::prelude::*;
pub fn Footer(cx: Scope<UserPrefs>) -> Element { pub fn Footer(props: UserPrefs) -> Element {
cx.render(rsx! { rsx! {
MutantStandardFooter { theme: cx.props.clone().get_theme(), font: cx.props.clone().get_font() } MutantStandardFooter { theme: props.clone().get_theme(), font: props.clone().get_font() }
}) }
} }
fn MutantStandardFooter(cx: Scope<UserPrefs>) -> Element { fn MutantStandardFooter(props: UserPrefs) -> Element {
let user_prefs = UserPrefs::new(cx.props.clone().get_theme(), cx.props.clone().get_font()); let user_prefs = UserPrefs::new(props.clone().get_theme(), props.clone().get_font());
let user_theme = cx.props.get_theme_classes(ThemedComponent::Card); let user_theme = props.get_theme_classes(ThemedComponent::Card);
let user_font = cx.props.get_font_class(); let user_font = props.get_font_class();
cx.render(rsx!{ rsx! {
div { class: "p-4 flex flex-col space-y-4 mx-auto max-w-full justify-center ring-4 {user_theme} {user_font}", div { class: "p-4 flex flex-col space-y-4 mx-auto max-w-full justify-center ring-4 {user_theme} {user_font}",
ButtonGroup{ ButtonGroup{
NavigationButton { title: "⚙️ Settings".to_string(), slug: "/settings".to_string(), user_prefs: user_prefs.clone() } NavigationButton { title: "⚙️ Settings".to_string(), slug: "/settings".to_string(), user_prefs: user_prefs.clone() }
@ -24,5 +24,5 @@ fn MutantStandardFooter(cx: Scope<UserPrefs>) -> Element {
"This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License" "This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License"
} }
} }
}) }
} }

View File

@ -1,13 +1,13 @@
use crate::utils::prop_structs::PageChildren; use crate::utils::prop_structs::PageChildren;
use dioxus::prelude::*; use dioxus::prelude::*;
pub fn PageBase<'a>(cx: Scope<'a, PageChildren<'a>>) -> Element { pub fn PageBase(props: PageChildren) -> Element {
cx.render(rsx! { rsx! {
span { hidden: true, span { hidden: true,
a { rel: "me", href: "https://yiff.life/@werefox", "Mastodon" } a { rel: "me", href: "https://yiff.life/@werefox", "Mastodon" }
} }
div { class: "min-h-screen", div { class: "min-h-screen",
div { class: "container space-y-4 pt-4 pb-4 max-w-3xl", &cx.props.children } div { class: "container space-y-4 pt-4 pb-4 max-w-3xl", {props.children} }
} }
}) }
} }

View File

@ -4,57 +4,54 @@ use crate::utils::prop_structs::VoidProps;
use crate::utils::{prop_structs::PoemChildren, user_prefs::ThemedComponent}; use crate::utils::{prop_structs::PoemChildren, user_prefs::ThemedComponent};
use dioxus::prelude::*; use dioxus::prelude::*;
pub fn PoemList(cx: Scope<VoidProps>) -> Element { pub fn PoemList(props: VoidProps) -> Element {
let poem_list = cx.props.poem_database.get_poem_list(); let poem_list = props.poem_database.get_poem_list();
cx.render(rsx! { rsx! {
ul { class: "flex flex-col space-y-4", ul { class: "flex flex-col space-y-4",
poem_list.into_iter().map(|p| { {poem_list.into_iter().map(|p| {
let slug = format!("/poems/{}", p.0); let slug = format!("/poems/{}", p.0);
rsx!{ rsx!{
NavigationButton { title: p.1, slug: slug, user_prefs: cx.props.user_prefs.clone() } NavigationButton { title: p.1, slug: slug, user_prefs: props.user_prefs.clone() }
} }
}) })}
} }
}) }
} }
pub fn MakePoem<'a>(cx: Scope<'a, PoemChildren<'a>>) -> Element { pub fn MakePoem(props: PoemChildren) -> Element {
cx.render(rsx! { rsx! {
div { class: "flex-col space-y-4", div { class: "flex-col space-y-4",
&cx.props.children {props.children}
} }
}) }
} }
pub fn GetPoem(cx: Scope<VoidProps>) -> Element { pub fn GetPoem(props: VoidProps) -> Element {
let poem_database = &cx.props.poem_database; let poem_database = props.poem_database;
let slug = String::from(&cx.props.slug.clone().expect("No slug specified.")); let slug = String::from(props.slug.clone().expect("No slug specified."));
let poem_struct = poem_database.get_poem(slug.clone()); let poem_struct = poem_database.get_poem(slug.clone());
cx.render(rsx! { rsx! {
Title { title: poem_struct.title.clone(), is_html: true, user_prefs: cx.props.user_prefs.clone() } Title { title: poem_struct.title.clone(), is_html: true, user_prefs: props.user_prefs.clone() }
MakePoem{ MakePoem{
PoemContent { slug: slug, poem_database: poem_database.clone(), user_prefs: cx.props.user_prefs.clone() } PoemContent { slug: slug, poem_database: poem_database.clone(), user_prefs: props.user_prefs.clone() }
} }
}) }
} }
pub fn PoemContent(cx: Scope<VoidProps>) -> Element { pub fn PoemContent(props: VoidProps) -> Element {
let (user_theme, user_font) = cx.props.user_prefs.get_pref_classes(ThemedComponent::Card); let (user_theme, user_font) = props.user_prefs.get_pref_classes(ThemedComponent::Card);
let slug = cx let slug = props
.props
.slug .slug
.as_ref() .as_ref()
.expect("Received slug for poem selection."); .expect("Received slug for poem selection.");
let content = &cx let content = props
.props
.poem_database .poem_database
.poem_hashmap .poem_hashmap
.get(slug) .get(slug)
.expect("Grabbed poem stuct from databse.") .expect("Grabbed poem stuct from databse.")
.content .content
.clone(); .clone();
let creation_date = &cx let creation_date = props
.props
.poem_database .poem_database
.poem_hashmap .poem_hashmap
.get(slug) .get(slug)
@ -63,26 +60,26 @@ pub fn PoemContent(cx: Scope<VoidProps>) -> Element {
.clone(); .clone();
let publish_string = "\u{003C}br\u{003E}\u{003C}br\u{003E}\u{003C}br\u{003E}Published: "; let publish_string = "\u{003C}br\u{003E}\u{003C}br\u{003E}\u{003C}br\u{003E}Published: ";
#[cfg(any(target_family = "unix", target_family = "windows"))] #[cfg(any(target_family = "unix", target_family = "windows"))]
return cx.render(rsx! { return rsx! {
div { class: "flex p-2 mx-auto max-w-full justify-center", div { class: "flex p-2 mx-auto max-w-full justify-center",
details { class: "group p-4 max-w-fit space-y-4 ring-4 {user_theme} {user_font}", details { class: "group p-4 max-w-fit space-y-4 ring-4 {user_theme} {user_font}",
summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 hover:animate-yip transition ring-2 {user_theme} {user_font}", summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 hover:animate-yip transition ring-2 {user_theme} {user_font}",
} }
div { class: "flex flex-col space-y-4 py-4 ml-4 mr-4", "{content}{publish_string}{creation_date}" div { class: "flex flex-col space-y-4 py-4 ml-4 mr-4", dangerous_inner_html: "{content}{publish_string}{creation_date}"
} }
} }
} }
}); };
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
return cx.render(rsx! { return rsx! {
div { class: "flex p-2 mx-auto max-w-full justify-center", div { class: "flex p-2 mx-auto max-w-full justify-center",
details { class: "group p-4 max-w-fit space-y-4 ring-4 {user_theme} {user_font}", details { class: "group p-4 max-w-fit space-y-4 ring-4 {user_theme} {user_font}",
summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 hover:animate-yip transition ring-2 {user_theme} {user_font}", summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 hover:animate-yip transition ring-2 {user_theme} {user_font}",
} }
div { class: "flex flex-col space-y-4 py-4 ml-4 mr-4", div { class: "flex flex-col space-y-4 py-4 ml-4 mr-4",
dangerous_inner_html: "{content}{publish_string}{creation_date}", dangerous_inner_html: "{content}{publish_string}{creation_date}",
} }
} }
} }
}); };
} }

View File

@ -2,40 +2,40 @@ use crate::utils::prop_structs::TitleProps;
use super::super::utils::user_prefs::ThemedComponent; use super::super::utils::user_prefs::ThemedComponent;
use dioxus::prelude::*; use dioxus::prelude::*;
pub fn Title(cx: Scope<TitleProps>) -> Element { pub fn Title(props: TitleProps) -> Element {
let user_prefs = cx.props.user_prefs.clone(); let user_prefs = props.user_prefs.clone();
let title_classes = user_prefs.get_theme_classes(ThemedComponent::Card); let title_classes = user_prefs.get_theme_classes(ThemedComponent::Card);
let title = cx.props.title.clone(); let title = props.title.clone();
let is_html = cx.props.is_html; let is_html = props.is_html;
cx.render(rsx!{ rsx!{
div { class: "p-4 ring-4 {title_classes}", div { class: "p-4 ring-4 {title_classes}",
span { class: "flex flex-row mx-auto max-w-full justify-center text-xl text-center", span { class: "flex flex-row mx-auto max-w-full justify-center text-xl text-center",
TitleHtml { title: title, is_html: is_html, user_prefs: user_prefs } TitleHtml { title: title, is_html: is_html, user_prefs: user_prefs }
} }
} }
}) }
} }
fn TitleHtml(cx: Scope<TitleProps>) -> Element { fn TitleHtml(props: TitleProps) -> Element {
let title = cx.props.title.clone(); let title = props.title.clone();
if cx.props.is_html { if props.is_html {
#[cfg(any(target_family = "unix", target_family = "windows"))] #[cfg(any(target_family = "unix", target_family = "windows"))]
return cx.render(rsx! { return rsx! {
span { class: "flex flex-row align-middle mx-auto max-w-full justify-center", span { class: "flex flex-row align-middle mx-auto max-w-full justify-center",
"{title}&nbsp;" dangerous_inner_html: "{title}&nbsp;"
} }
}); };
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
return cx.render(rsx! { return rsx! {
span { class: "flex flex-row align-middle mx-auto max-w-full justify-center", span { class: "flex flex-row align-middle mx-auto max-w-full justify-center",
div { dangerous_inner_html: "{title}", } div { dangerous_inner_html: "{title}", }
} }
}); };
} else { } else {
return cx.render(rsx! { return rsx! {
span { span {
"{title}" "{title}"
} }
}); };
} }
} }

View File

@ -4,9 +4,10 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
mod components; use utils::{prop_structs::PoemDatabase, user_prefs::UserPrefs};
pub mod utils;
pub mod components;
pub mod utils;
/// A module that handles the functions needed /// A module that handles the functions needed
/// to render the site. /// to render the site.
pub mod void_app { pub mod void_app {
@ -27,45 +28,80 @@ pub mod void_app {
#[cfg(any(target_family = "wasm"))] #[cfg(any(target_family = "wasm"))]
use dioxus_helmet::Helmet; use dioxus_helmet::Helmet;
#[cfg(any(target_family = "wasm"))] #[cfg(any(target_family = "wasm"))]
use dioxus_router::{Link, Redirect, Route, Router}; use dioxus_router::prelude::*;
#[cfg(any(target_family = "wasm"))] #[cfg(any(target_family = "wasm"))]
use dioxus_use_storage::use_local_storage; use dioxus_use_storage::use_local_storage;
#[cfg(any(target_family = "wasm"))]
use once_cell::sync::OnceCell;
#[cfg(any(target_family = "wasm"))]
static POEM_DATABASE: OnceCell<PoemDatabase> = OnceCell::new();
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
pub fn DioxusApp(cx: Scope) -> Element { #[derive(Routable, PartialEq, Clone)]
pub enum Route {
#[route("/")]
// #[redirect("/")]//, || Route::HomePage {slug: "/".to_string(), poem_database: poem_database.clone(), user_prefs: user_prefs.clone(),})]
HomePage { props: VoidProps },
#[route("/poems")]
PoemListPage {
slug: String,
poem_database: PoemDatabase,
user_prefs: UserPrefs,
},
#[route("/poems/:slug")]
PoemPage {
slug: String,
poem_database: PoemDatabase,
user_prefs: UserPrefs,
},
#[route("/settings")]
SettingsPage { theme: ThemePref, font: FontPref },
// #[route("/settings/dark")]
// SettingsPage { theme: String, font: String },
// #[route("/settings/font")]
// SettingsPage { theme: String, font: String },
#[route("")]
PageNotFound {},
}
#[cfg(target_family = "wasm")]
pub fn DioxusApp() -> Element {
// let mut poem_database = PoemDatabase::new();
// poem_database.build_poem_database();
// let user_prefs = UserPrefs::new(ThemePref::Auto, FontPref::OpenDyslexic);
let mut poem_database = PoemDatabase::new(); let mut poem_database = PoemDatabase::new();
poem_database.build_poem_database(); poem_database.build_poem_database();
POEM_DATABASE
.set(poem_database)
.expect("Could not initialize poem database.");
let user_prefs = UserPrefs::new(ThemePref::Auto, FontPref::OpenDyslexic); rsx! {
Router::<Route> {}
cx.render(rsx! { }
Router {
Route { to: "/", HomePage { slug: "/".to_string(), poem_database: poem_database.clone(), user_prefs: user_prefs.clone(), } }
Route { to: "/poems", PoemListPage { slug: "/poems".to_string(), poem_database: poem_database.clone(), user_prefs: user_prefs.clone(), } }
Route { to: "/poems/:slug", PoemPage { slug: "".to_string(), poem_database: poem_database.clone(), user_prefs: user_prefs.clone(), } }
Route { to: "/settings", SettingsPage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() } }
Route { to: "/settings/dark", SettingsPage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() } }
Route { to: "/settings/font", SettingsPage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() } }
Route { to: "", PageNotFound {} }
}
})
} }
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
fn PageNotFound(cx: Scope) -> Element { fn PageNotFound() -> Element {
cx.render(rsx! { rsx! {
p { "That page doesn't exist, sorry!" } p { "That page doesn't exist, sorry!" }
Redirect { to: "/" } }
})
} }
#[component]
/// Renders the app and returns the rendered Element. /// Renders the app and returns the rendered Element.
pub fn HomePage(cx: Scope<VoidProps>) -> Element { pub fn HomePage(props: VoidProps) -> Element {
let poem_database = &cx.props.poem_database; #[cfg(target_family = "wasm")]
let user_prefs = cx.props.user_prefs.clone(); let poem_database = POEM_DATABASE
.get()
.expect("Poem database is not initialized")
.clone();
#[cfg(any(target_family = "unix", target_family = "windows"))]
let poem_database = props.poem_database.clone();
let user_prefs = props.user_prefs.clone();
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page); let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
let page_title = "A Letter to the Void".to_string(); let page_title = "A Letter to the Void".to_string();
cx.render(rsx!{ rsx! {
div { class: "{user_theme} {user_font}", div { class: "{user_theme} {user_font}",
PageBase { PageBase {
Title { title: page_title, is_html: false, user_prefs: user_prefs.clone() } Title { title: page_title, is_html: false, user_prefs: user_prefs.clone() }
@ -79,15 +115,21 @@ pub mod void_app {
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() } Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
} }
} }
}) }
} }
/// Renders the app and returns the rendered Element. /// Renders the app and returns the rendered Element.
pub fn PoemListPage(cx: Scope<VoidProps>) -> Element { pub fn PoemListPage(props: VoidProps) -> Element {
let poem_database = &cx.props.poem_database; #[cfg(target_family = "wasm")]
let user_prefs = cx.props.user_prefs.clone(); let poem_database = POEM_DATABASE
.get()
.expect("Poem database is not initialized")
.clone();
#[cfg(any(target_family = "unix", target_family = "windows"))]
let poem_database = props.poem_database.clone();
let user_prefs = props.user_prefs.clone();
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page); let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
cx.render(rsx! { rsx! {
div { class: "{user_theme} {user_font}", div { class: "{user_theme} {user_font}",
PageBase { PageBase {
Title { title: "A Letter to the Void".to_string(), is_html: false, user_prefs: user_prefs.clone() } Title { title: "A Letter to the Void".to_string(), is_html: false, user_prefs: user_prefs.clone() }
@ -97,27 +139,32 @@ pub mod void_app {
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() } Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
} }
} }
}) }
} }
pub fn PoemPage(cx: Scope<VoidProps>) -> Element { pub fn PoemPage(props: VoidProps) -> Element {
let poem_database = &cx.props.poem_database; #[cfg(target_family = "wasm")]
let user_prefs = cx.props.user_prefs.clone(); let poem_database = POEM_DATABASE
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page); .get()
.expect("Poem database is not initialized")
.clone();
#[cfg(any(target_family = "unix", target_family = "windows"))] #[cfg(any(target_family = "unix", target_family = "windows"))]
let slug = &cx let poem_database = props.poem_database.clone();
.props let user_prefs = props.user_prefs.clone();
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
// #[cfg(any(target_family = "unix", target_family = "windows"))]
let slug = props
.slug .slug
.as_ref() .as_ref()
.expect("A slug was given in the pops.") .expect("A slug was given in the props.")
.clone(); .clone();
#[cfg(target_family = "wasm")] // #[cfg(target_family = "wasm")]
let slug = String::from( // let slug = String::from(
dioxus_router::use_route(cx) // use_route()
.segment("slug") // .segment("slug")
.expect("No slug specified."), // .expect("No slug specified."),
); // );
cx.render(rsx!{ rsx! {
div { class: "{user_theme} {user_font}", div { class: "{user_theme} {user_font}",
PageBase { PageBase {
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() } BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
@ -133,15 +180,15 @@ pub mod void_app {
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() } Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
} }
} }
}) }
} }
pub fn SettingsPage(cx: Scope<UserPrefs>) -> Element { pub fn SettingsPage(props: UserPrefs) -> Element {
let user_prefs = cx.props.clone(); let user_prefs = props.clone();
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page); let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
// Get rid of this and create a general card component with children. // Get rid of this and create a general card component with children.
let (user_theme_card, user_font_card) = user_prefs.get_pref_classes(ThemedComponent::Card); let (user_theme_card, user_font_card) = user_prefs.get_pref_classes(ThemedComponent::Card);
cx.render(rsx! { rsx! {
div { class: "{user_theme} {user_font}", div { class: "{user_theme} {user_font}",
PageBase { PageBase {
Title { title: "Settings".to_string(), is_html: false, user_prefs: user_prefs.clone() } Title { title: "Settings".to_string(), is_html: false, user_prefs: user_prefs.clone() }
@ -162,14 +209,14 @@ pub mod void_app {
"Font" "Font"
} }
ButtonGroup { ButtonGroup {
NavigationButton { title: "Nerd Font".to_string(), slug: "/settings/?font=nerd".to_string(), user_prefs: user_prefs.clone() override_font: "font-nerd".to_string() } NavigationButton { title: "Nerd Font".to_string(), slug: "/settings/?font=nerd".to_string(), user_prefs: user_prefs.clone(), override_font: "font-nerd".to_string() }
NavigationButton { title: "Open Dyslexic".to_string(), slug: "/settings/?font=open".to_string(), user_prefs: user_prefs.clone() override_font: "font-open".to_string() } NavigationButton { title: "Open Dyslexic".to_string(), slug: "/settings/?font=open".to_string(), user_prefs: user_prefs.clone(), override_font: "font-open".to_string() }
} }
} }
} }
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() } BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
} }
} }
}) }
} }
} }

View File

@ -18,5 +18,5 @@ fn main() {
wasm_logger::init(wasm_logger::Config::default()); wasm_logger::init(wasm_logger::Config::default());
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
dioxus_web::launch(void_app::DioxusApp); dioxus::prelude::launch(void_app::DioxusApp);
} }

View File

@ -23,6 +23,14 @@ impl PoemDatabase {
// There's no need to actually make a database yet, but maybe in the future... // There's no need to actually make a database yet, but maybe in the future...
#[cfg(any(target_family = "unix", target_family = "windows"))] #[cfg(any(target_family = "unix", target_family = "windows"))]
pub async fn build_poem_database(&mut self) { pub async fn build_poem_database(&mut self) {
use dioxus::dioxus_core::Component;
use markdown::CompileOptions;
let markdown_options = &mut Options::gfm();
markdown_options.compile = CompileOptions {
allow_dangerous_html: true,
..CompileOptions::default()
};
for p in Poems::iter() { for p in Poems::iter() {
let filename = p.to_string(); let filename = p.to_string();
let poem_content = Poems::get(&filename).expect("Found poem {filename:?}"); let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
@ -32,7 +40,7 @@ impl PoemDatabase {
let poem_title = poem_to_str.next().expect("No title specified."); let poem_title = poem_to_str.next().expect("No title specified.");
let poem_content = poem_to_str.into_iter().collect::<Vec<&str>>().join("\n"); let poem_content = poem_to_str.into_iter().collect::<Vec<&str>>().join("\n");
let poem_title_to_html_string = let poem_title_to_html_string =
markdown::to_html_with_options(poem_title, &Options::gfm()).unwrap(); markdown::to_html_with_options(poem_title, markdown_options).unwrap();
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();
let mut split_filename = filename.trim_end_matches(".md").split("_"); let mut split_filename = filename.trim_end_matches(".md").split("_");
@ -41,7 +49,7 @@ impl PoemDatabase {
self.poem_list self.poem_list
.push((creation_date.to_string(), slug.to_string())); .push((creation_date.to_string(), slug.to_string()));
let poem_struct = PoemStruct { let poem_struct = PoemStruct {
title: poem_title_to_html_string.to_string(), title: poem_title_to_html_string,
content: poem_content_to_html_string, content: poem_content_to_html_string,
creation_date: creation_date.to_string(), creation_date: creation_date.to_string(),
}; };

View File

@ -1,27 +1,28 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::void_app::{Element, Props}; // use crate::void_app::{Element, Props};
use super::user_prefs::UserPrefs; use super::user_prefs::UserPrefs;
use dioxus::prelude::*;
#[derive(PartialEq, Props)] #[derive(PartialEq, Props, Clone)]
pub struct PoemRequest { pub struct PoemRequest {
pub slug: String, pub slug: String,
pub user_prefs: UserPrefs, pub user_prefs: UserPrefs,
} }
#[derive(PartialEq, Props)] #[derive(PartialEq, Props, Clone)]
pub struct TitleProps { pub struct TitleProps {
pub title: String, pub title: String,
pub is_html: bool, pub is_html: bool,
pub user_prefs: UserPrefs, pub user_prefs: UserPrefs,
} }
#[derive(PartialEq, Props)] #[derive(PartialEq, Props, Clone)]
pub struct ContentProps { pub struct ContentProps {
pub content: String, pub content: String,
pub user_prefs: UserPrefs, pub user_prefs: UserPrefs,
} }
#[derive(PartialEq, Props)] #[derive(PartialEq, Props, Clone)]
pub struct ButtonProps { pub struct ButtonProps {
pub title: String, pub title: String,
pub slug: String, pub slug: String,
@ -29,14 +30,14 @@ pub struct ButtonProps {
pub override_font: Option<String>, pub override_font: Option<String>,
} }
#[derive(PartialEq, Props)] #[derive(Default, PartialEq, Props, Clone)]
pub struct VoidProps { pub struct VoidProps {
pub slug: Option<String>, pub slug: Option<String>,
pub poem_database: PoemDatabase, pub poem_database: PoemDatabase,
pub user_prefs: UserPrefs, pub user_prefs: UserPrefs,
} }
#[derive(PartialEq, Props, Clone, Debug)] #[derive(Default, PartialEq, Props, Clone, Debug)]
pub struct PoemDatabase { pub struct PoemDatabase {
pub poem_list: Vec<(String, String)>, pub poem_list: Vec<(String, String)>,
pub poem_hashmap: HashMap<String, PoemStruct>, pub poem_hashmap: HashMap<String, PoemStruct>,
@ -50,17 +51,17 @@ pub struct PoemStruct {
} }
// These next three should all just be one prop. // These next three should all just be one prop.
#[derive(Props)] #[derive(PartialEq, Props, Clone)]
pub struct PoemChildren<'a> { pub struct PoemChildren {
pub children: Element<'a>, pub children: Element,
} }
#[derive(Props)] #[derive(PartialEq, Props, Clone)]
pub struct PageChildren<'a> { pub struct PageChildren {
pub children: Element<'a>, pub children: Element,
} }
#[derive(Props)] #[derive(PartialEq, Props, Clone)]
pub struct ContentChildren<'a> { pub struct ContentChildren {
pub children: Element<'a>, pub children: Element,
} }

View File

@ -1,20 +1,22 @@
use dioxus::prelude::*; use dioxus::prelude::*;
#[derive(PartialEq, Props, Clone)] #[derive(Default, PartialEq, Props, Clone)]
pub struct UserPrefs { pub struct UserPrefs {
theme: ThemePref, theme: ThemePref,
font: FontPref, font: FontPref,
} }
#[derive(PartialEq, Clone)] #[derive(Default, PartialEq, Clone)]
pub enum ThemePref { pub enum ThemePref {
Light, Light,
Dark, Dark,
#[default]
Auto, Auto,
} }
#[derive(PartialEq, Clone)] #[derive(Default, PartialEq, Clone)]
pub enum FontPref { pub enum FontPref {
#[default]
NerdFont, NerdFont,
OpenDyslexic, OpenDyslexic,
} }
@ -41,9 +43,9 @@ impl UserPrefs {
// class: "dark:text-alice-werefox-grey-light dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue" // class: "dark:text-alice-werefox-grey-light dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue"
// class: "text-alice-werefox-grey-light hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue" // class: "text-alice-werefox-grey-light hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue"
const PAGE_CLASSES: &str = "bg-alice-werefox-grey-light dark:bg-alice-werefox-grey"; const PAGE_CLASSES: &'static str = "bg-alice-werefox-grey-light dark:bg-alice-werefox-grey";
const CARD_CLASSES: &str = "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light"; const CARD_CLASSES: &'static str = "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light";
const BUTTON_CLASSES: &str = "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark hover:text-alice-werefox-blue-dark hover:ring-alice-werefox-blue dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue"; const BUTTON_CLASSES: &'static str = "bg-alice-werefox-grey-lightest ring-alice-werefox-red-dark text-alice-werefox-grey-dark hover:text-alice-werefox-blue-dark hover:ring-alice-werefox-blue dark:bg-alice-werefox-grey-dark dark:ring-alice-werefox-red dark:text-alice-werefox-grey-light dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue";
pub fn new(theme: ThemePref, font: FontPref) -> UserPrefs { pub fn new(theme: ThemePref, font: FontPref) -> UserPrefs {
UserPrefs { theme, font } UserPrefs { theme, font }