Compare commits

...

10 Commits

23 changed files with 480 additions and 209 deletions

View File

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

@ -5,9 +5,12 @@
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8" />
<link rel="me" href="https://bark.lgbt/@alicew" />
<link rel="me" href="https://dragon.style/@alice" />
<link rel="me" href="https://mspsocial.net/@alice" />
{{{style_include}}}
</head>
<body class="{{dark_mode}}">
<div id="main">{{{test}}}</div>
</body>
</html>
</html>

View File

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

View File

@ -14,9 +14,11 @@ pub mod web_app_backend {
use rocket::response::Redirect;
use rocket::{Build, Rocket};
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::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();
@ -27,7 +29,7 @@ pub mod web_app_backend {
"light" => ThemePref::Light,
"dark" => ThemePref::Dark,
_ => {
cookies.remove(Cookie::named("theme"));
cookies.remove("theme");
cookies.add(Cookie::new("theme", "auto"));
ThemePref::Auto
}
@ -42,7 +44,7 @@ pub mod web_app_backend {
"nerd" => FontPref::NerdFont,
"open" => FontPref::OpenDyslexic,
_ => {
cookies.remove(Cookie::named("font"));
cookies.remove("font");
cookies.add(Cookie::new("font", "open"));
FontPref::OpenDyslexic
}
@ -57,7 +59,7 @@ pub mod web_app_backend {
async fn set_user_theme(cookies: &CookieJar<'_>, theme: &str) {
if theme == "light" || theme == "dark" || theme == "auto" {
cookies.remove(Cookie::named("theme"));
cookies.remove("theme");
cookies.add(Cookie::new("theme", format!("{theme}")));
} else {
return;
@ -66,7 +68,7 @@ pub mod web_app_backend {
async fn set_user_font(cookies: &CookieJar<'_>, font: &str) {
if font == "nerd" || font == "open" {
cookies.remove(Cookie::named("font"));
cookies.remove("font");
cookies.add(Cookie::new("font", format!("{font}")));
} else {
return;
@ -84,8 +86,13 @@ pub mod web_app_backend {
.clone(),
user_prefs: user_prefs,
};
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, void_props);
let _ = vdom.rebuild();
// let content_props = ContentProps {
// 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);
Template::render(
"index",
@ -102,7 +109,7 @@ pub mod web_app_backend {
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 _ = vdom.rebuild_in_place();
let output = dioxus_ssr::render(&vdom);
Template::render(
"index",
@ -139,7 +146,7 @@ pub mod web_app_backend {
user_prefs: user_prefs,
};
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);
Template::render(
"index",
@ -164,7 +171,7 @@ pub mod web_app_backend {
user_prefs: user_prefs,
};
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);
Template::render(
"index",

View File

@ -2,15 +2,18 @@
"rust-analyzer.cargo.extraArgs": ["--profile", "rust-analyzer"],
// "rust-analyzer.cargo.buildScripts.invocationLocation": "root",
"rust-analyzer.cargo.target": "wasm32-unknown-unknown",
// "rust-analyzer.cargo.buildScripts.overrideCommand": ["dioxus", "build"],
"rust-analyzer.check.overrideCommand": ["cargo", "check", "--quiet", "--message-format=json"],
"rust-analyzer.cargo.buildScripts.overrideCommand": ["dx", "build"],
"rust-analyzer.check.overrideCommand": ["dx", "check", "--quiet", "--message-format=json"],
"rust-analyzer.check.invocationLocation": "root",
"rust-analyzer.check.targets": ["wasm32-unknown-unknown", "x86_64-unknown-linux-gnu"],
// "rust-analyzer.runnables.command": "dioxus serve",
"rust-analyzer.check.targets": ["wasm32-unknown-unknown"],
"rust-analyzer.runnables.command": "dx serve",
"rust-analyzer.cargo.buildScripts.enable": false,
"rust-analyzer.linkedProjects": [
"./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.hover.actions.run.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
[dependencies]
dioxus = { workspace = true }
# dioxus = { workspace = true }
markdown = { workspace = true }
dioxus-web = "0.3.1"
dioxus-autofmt = "0.3.0"
once_cell = { workspace = true }
# dioxus-web = "0.5.0-alpha.0"
dioxus-autofmt = "0.5.0-alpha.0"
# WebAssembly Debug
wasm-logger = "0.2.0"
console_error_panic_hook = "0.1.7"
log = "0.4.17"
dioxus-helmet = "0.2.4"
dioxus-use-storage = "0.3.0"
dioxus-use-storage = "0.3.1"
rand = "0.8.5"
dioxus-html-macro = "0.3.0"
[dependencies.getrandom]
version = "0.2.9"
version = "0.2.12"
features = ["js"]
[dependencies.serde]
version = "1.0.160"
version = "1.0.197"
features = ["derive"]
[dependencies.dioxus-router]
version = "0.3.0"
features = ["query", "web"]
version = "0.5.0-alpha.0"
features = ["web"]
[dependencies.rust-embed]
version = "6.6.1"
version = "8.3.0"
features = ["debug-embed"]
[dependencies.dioxus]
version = "0.5.0-alpha.0"
features = ["web"]

View File

@ -0,0 +1,29 @@
# Today.
Next year. \
Next month. \
Next week. \
Today.
Today, I feel the breeze. \
I keep my feet planted. \
I spread my wings.
Today. \
The breeze picks up. \
I'm feeling nervous. \
I start my run.
Today. \
I prepare to leap. \
One extra check. \
I'm almost there.
Today. \
I shake my head. \
I find my ground. \
I'm still just standing. \
I contemplate.
Like sleep paralysis in the early hours of the morning, like a sudden jolt from a lucid daydream, I'm still just standing. All I can see right now is today, and today, I'm still just standing.
Today, like my hesitance to ambition, is temporary. Daydreams only last until you make them your reality.

View File

@ -0,0 +1,50 @@
# Where I Stand
I used to think that I was special, like a rose in a bouquet \
Now I'm learning that my prickly thorns might ruin everything \
I thought I was complacent, thought I knew just who I am \
Now I'm deviating, turns and twisting, awol from my plan \
I should've known \
We're characters all reaping what we sew
What if I'm not enough? \
What if I'm just a bluff? \
What if I'm not anything for anyone besides when things are tough? \
What if I'm just a trick? \
What if I'm just for kicks? \
I can't say I'm not proud of who I am, just contemplating where I stand
Every morning brings a mourning, from the things that still decay \
But foundation is a castle built on sand that starts to shake \
I wanted to be Winter, but the Sunrise fits my name \
I wanted to be everything I tried to shun away \
I should've known \
As far as seasons go, I'm waiting out the snow
What if I'm not enough? \
What if I'm just a bluff? \
What if I'm not anything for anyone besides when things are tough? \
What if I'm just a trick? \
What if I'm just for kicks? \
I can't say I'm not proud of who I am, just contemplating where I stand
New horizons, new beginnings \
I won't be my own eclipse \
I can ride the solar flares \
Become my own Mistress \
And as long as we're still playing \
Pay attention, listen close \
I'm still terrified of being \
All the things I hate the most
What if I'm not enough? \
What if I'm just a bluff? \
What if I'm not anything for anyone besides when things are tough? \
What if I'm just a trick? \
What if I'm just for kicks? \
I can't say I'm not proud of who I am, just contemplating where I stand
Take me back to where we started \
I can't retrace the footsteps buried in the sand \
Guess I know I've just departed \
Made my leap, and now I'm seeing how it goes

View File

@ -0,0 +1,52 @@
# Stillwater Pond
_She said "sweetie, whatcha thinkin'?"_ \
_I stared down at the ground_ \
_I don't think life is easy, and it's hitting me right now_ \
_We walked right down the sidewalk and I opened up my mouth_ \
_"My life is in a strange place,_ \
_Like sitting at a pond,_ \
_And noticing the stillness, and taking in the calm"_
(Mmmhmm) _I don't know what I'm doing, can't you tell?_ \
(Mmmhmm) _Not used to all the silence in my head_ \
(Mmmhmm) _And I'll be honest, I make my life hell_ \
(Mmmhmm) _So how am I supposed to do the rest?_
_Don't keep making your storms, girl, it's all you can do, to keep pushing through_ \
_Appreciate all the quiet, 'cus now your life is just up to you_ \
_You had it all along_ \
_Never had to write this song_ \
_So as long as we're sitting, here's the truth_ \
_You don't need to know what to do_
_I used to resort to drinking_ \
_It could numb the pain I felt_ \
_Every weekend I'd repeat it, and the weekdays just as well_ \
_I chose to just deny it, grin and bare, I'd tell myself_ \
_Now I'm not still in college_ \
_Or in a shitty job_ \
_So I told myself at my age I should practice self love_
(Mmmhmm) _Maybe I'm in more control than I let on_ \
(Mmmhmm) _When I stop the issues new ones just appear_ \
(Mmmhmm) _Wait, I'm starting to think they're already gone_ \
(Mmmhmm) _I should take my own advice, get out of here_
_Don't keep making your storms, girl, it's all you can do, to keep pushing through_ \
_Appreciate all the quiet, 'cus now your life is just up to you_ \
_You had it all along_ \
_Never had to write this song_ \
_So as long as we're sitting, here's the truth_ \
_You don't need to know what to do_
_I'm sitting at the airport_ \
_I'm on standby for the flight_ \
_I don't feel so agitated_ \
_About figuring out life_ \
_There's no way to have answers_ \
_And I don't need to plan_ \
_I'll just fucking make it_ \
_Just a step at a time_ \
_Take a breath, it'll be fine_ \
_You don't need to be right_ \
_Just keep doing what you can_

View File

@ -0,0 +1,41 @@
# Dear Diary
_I'm not a perfect person, but I'm better than I've been_ \
_Maybe I'm still trying not to be another sin_ \
_But I won't hide the issues, put my feelings on display_ \
_Because the only way I'll grow is if I feel them out someday_
_It's hard for me to say the things that make me feel ashamed_ \
_I'll write another poem, hide my feelings on the page_ \
_And maybe after that someday I won't need therapy_ \
_So here's to me and here's to you_ \
_I'm hoping someday I won't hide away the truth_
_I used to be someone I'm not and hope I disappear_ \
_I gave up hoping anyone would ever want me here_ \
_It's so much easier to just sink back inside my clothes_ \
_Maybe if I wear them dark enough, my silhouette won't show_
_I'm told that I'm annoying, that I never shut my mouth_ \
_So I made my own muzzle and affixed it to my snout_ \
_But every now and then I'd break it off and speak my mind_ \
_I'd better make a new one, so nobody hears me cry_
_Got used to shaping myself so I'd finally fit in_ \
_And every time I'd do it, I could fake a stupid grin_ \
_I got so good I'd profile every person I had met_ \
_Speak the words and take the actions that would make them be my friend_
_Soon enough I'd get so good I'd forget who I am_\
_And everyone who knew me knew a different kind of mask_
_Eventually it catches up, the pieces fall apart_ \
_You stand there and you wonder who you are and where to start_ \
_The fear sets in and then you start to ponder if it's true_ \
_Should you be afraid that no one really likes the real you_
_It's hard for me to say the things that make me feel ashamed_ \
_I'll write another poem, hide my feelings on the page_ \
_And maybe after that someday, you'll read between the lines_ \
_So here's to me, the real me_ \
_Trying to trust that you'll love who I want to be_

View File

@ -0,0 +1,27 @@
# 3 years
_From three months to three years_ \
_Every little worry I had is faded away_ \
_And I still have more to go_
_Lots of folks say they lost track_ \
_I think I'm the only one who celebrates, really_ \
_I ponder why it matters to me_
_I guess it matters because it used to matter_ \
_That number used to mean the world to me_ \
_It was my way to happiness_
Three years.
Three years, and I've uprooted my life again.
Three years, and I try to make plans with friends.
Three years, and I realize there is no end.
_I look in the mirror, and I see ***exactly*** what I want to see. And it's great, it's wonderful, it's me. But my heart still bleeds. The ink hasn't dried on the page. I'm more satisfied than I've been in my life, and I'm still not satisfied._
_Maybe, in another three years, I'll have a better idea of what satisfaction is for me. I know it's not this, but that's okay. Maybe in another three years, I'll accept that I'm never satisfied. Maybe, maybe, just maybe, I'll understand why._
_It's hard to ask for what you need when you don't know what it is. I thought it was comfort, I thought it was compassion, I thought it was stability. Somewhere in trying to get what I need, I lost sight of myself._

View File

@ -1,72 +1,73 @@
use crate::utils::prop_structs::PoemDatabase;
use super::super::utils::{
prop_structs::{ButtonProps, ContentChildren},
prop_structs::{ButtonProps, ContentChildren, VoidProps},
user_prefs::{ThemedComponent, UserPrefs},
};
use dioxus::prelude::*;
use dioxus_router::prelude::*;
#[cfg(target_family = "wasm")]
use dioxus_router::Link;
pub fn BackToHomePage(cx: Scope<UserPrefs>) -> Element {
let (user_theme, user_font) = cx.props.clone().get_pref_classes(ThemedComponent::Button);
pub fn BackToHomePage(props: UserPrefs) -> Element {
let (user_theme, user_font) = props.clone().get_pref_classes(ThemedComponent::Button);
#[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}",
href: "/",
p {
"Back to the homepage"
}
}
});
};
let mut poem_database = PoemDatabase::new();
poem_database.build_poem_database();
#[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}",
to: "/",
to: crate::void_app::Route::HomePage { props:VoidProps{slug: Some("/".to_string()), poem_database: poem_database.clone(), user_prefs: props.clone(),}},
p {
"Back to the homepage"
}
}
});
};
}
pub fn NavigationButton(cx: Scope<ButtonProps>) -> Element {
let (user_theme, mut user_font) = cx
.props
pub fn NavigationButton(props: ButtonProps) -> Element {
let (user_theme, mut user_font) = props
.user_prefs
.clone()
.get_pref_classes(ThemedComponent::Button);
let title = cx.props.title.clone();
let title = props.title.clone();
let title_ref = title.as_str();
let slug = cx.props.slug.clone();
let slug = props.slug.clone();
let slug_ref = slug.as_str();
match &cx.props.override_font {
match props.override_font {
Some(font) => user_font = font.clone(),
None => (),
}
#[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}",
href: "{slug_ref}",
"{title_ref}"
dangerous_inner_html: "{title_ref}",
}
});
};
#[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}",
to: "{slug_ref}",
div {
dangerous_inner_html: "{title_ref}",
}
}
});
};
}
pub fn ButtonGroup<'a>(cx: Scope<'a, ContentChildren<'a>>) -> Element {
cx.render(rsx! {
pub fn ButtonGroup(props: ContentChildren) -> Element {
rsx! {
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...
use crate::utils::prop_structs::{ContentProps};
use super::super::utils::user_prefs::ThemedComponent;
use crate::utils::prop_structs::ContentProps;
use dioxus::prelude::*;
pub fn RenderContent(cx: Scope<ContentProps>) -> Element {
let (user_theme, user_font) = cx.props.user_prefs.get_pref_classes(ThemedComponent::Card);
let content = &cx.props.content;
#[cfg(any(target_family = "windows", target_family = "unix"))]
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!{
pub fn RenderContent(props: ContentProps) -> Element {
let (user_theme, user_font) = props.user_prefs.get_pref_classes(ThemedComponent::Card);
let content = props.content;
return 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}",
dangerous_inner_html: "{content}",
}
});
};
}

View File

@ -4,17 +4,17 @@ use crate::{
};
use dioxus::prelude::*;
pub fn Footer(cx: Scope<UserPrefs>) -> Element {
cx.render(rsx! {
MutantStandardFooter { theme: cx.props.clone().get_theme(), font: cx.props.clone().get_font() }
})
pub fn Footer(props: UserPrefs) -> Element {
rsx! {
MutantStandardFooter { theme: props.clone().get_theme(), font: props.clone().get_font() }
}
}
fn MutantStandardFooter(cx: Scope<UserPrefs>) -> Element {
let user_prefs = UserPrefs::new(cx.props.clone().get_theme(), cx.props.clone().get_font());
let user_theme = cx.props.get_theme_classes(ThemedComponent::Card);
let user_font = cx.props.get_font_class();
cx.render(rsx!{
fn MutantStandardFooter(props: UserPrefs) -> Element {
let user_prefs = UserPrefs::new(props.clone().get_theme(), props.clone().get_font());
let user_theme = props.get_theme_classes(ThemedComponent::Card);
let user_font = props.get_font_class();
rsx! {
div { class: "p-4 flex flex-col space-y-4 mx-auto max-w-full justify-center ring-4 {user_theme} {user_font}",
ButtonGroup{
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"
}
}
})
}
}

View File

@ -1,13 +1,13 @@
use crate::utils::prop_structs::PageChildren;
use dioxus::prelude::*;
pub fn PageBase<'a>(cx: Scope<'a, PageChildren<'a>>) -> Element {
cx.render(rsx! {
pub fn PageBase(props: PageChildren) -> Element {
rsx! {
span { hidden: true,
a { rel: "me", href: "https://yiff.life/@werefox", "Mastodon" }
}
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 dioxus::prelude::*;
pub fn PoemList(cx: Scope<VoidProps>) -> Element {
let poem_list = cx.props.poem_database.get_poem_list();
cx.render(rsx! {
pub fn PoemList(props: VoidProps) -> Element {
let poem_list = props.poem_database.get_poem_list();
rsx! {
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);
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 {
cx.render(rsx! {
pub fn MakePoem(props: PoemChildren) -> Element {
rsx! {
div { class: "flex-col space-y-4",
&cx.props.children
{props.children}
}
})
}
}
pub fn GetPoem(cx: Scope<VoidProps>) -> Element {
let poem_database = &cx.props.poem_database;
let slug = String::from(&cx.props.slug.clone().expect("No slug specified."));
pub fn GetPoem(props: VoidProps) -> Element {
let poem_database = props.poem_database;
let slug = String::from(props.slug.clone().expect("No slug specified."));
let poem_struct = poem_database.get_poem(slug.clone());
cx.render(rsx! {
Title { title: poem_struct.title.clone(), is_html: true, user_prefs: cx.props.user_prefs.clone() }
rsx! {
Title { title: poem_struct.title.clone(), is_html: true, user_prefs: props.user_prefs.clone() }
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 {
let (user_theme, user_font) = cx.props.user_prefs.get_pref_classes(ThemedComponent::Card);
let slug = cx
.props
pub fn PoemContent(props: VoidProps) -> Element {
let (user_theme, user_font) = props.user_prefs.get_pref_classes(ThemedComponent::Card);
let slug = props
.slug
.as_ref()
.expect("Received slug for poem selection.");
let content = &cx
.props
let content = props
.poem_database
.poem_hashmap
.get(slug)
.expect("Grabbed poem stuct from databse.")
.content
.clone();
let creation_date = &cx
.props
let creation_date = props
.poem_database
.poem_hashmap
.get(slug)
@ -63,26 +60,26 @@ pub fn PoemContent(cx: Scope<VoidProps>) -> Element {
.clone();
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"))]
return cx.render(rsx! {
return rsx! {
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}",
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")]
return cx.render(rsx! {
return rsx! {
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}",
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}",
}
}
}
});
};
}

View File

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

View File

@ -4,9 +4,10 @@
#![allow(non_snake_case)]
mod components;
pub mod utils;
use utils::{prop_structs::PoemDatabase, user_prefs::UserPrefs};
pub mod components;
pub mod utils;
/// A module that handles the functions needed
/// to render the site.
pub mod void_app {
@ -27,45 +28,80 @@ pub mod void_app {
#[cfg(any(target_family = "wasm"))]
use dioxus_helmet::Helmet;
#[cfg(any(target_family = "wasm"))]
use dioxus_router::{Link, Redirect, Route, Router};
use dioxus_router::prelude::*;
#[cfg(any(target_family = "wasm"))]
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")]
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();
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);
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 {} }
}
})
rsx! {
Router::<Route> {}
}
}
#[cfg(target_family = "wasm")]
fn PageNotFound(cx: Scope) -> Element {
cx.render(rsx! {
fn PageNotFound() -> Element {
rsx! {
p { "That page doesn't exist, sorry!" }
Redirect { to: "/" }
})
}
}
#[component]
/// Renders the app and returns the rendered Element.
pub fn HomePage(cx: Scope<VoidProps>) -> Element {
let poem_database = &cx.props.poem_database;
let user_prefs = cx.props.user_prefs.clone();
pub fn HomePage(props: VoidProps) -> Element {
#[cfg(target_family = "wasm")]
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 page_title = "A Letter to the Void".to_string();
cx.render(rsx!{
rsx! {
div { class: "{user_theme} {user_font}",
PageBase {
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() }
}
}
})
}
}
/// Renders the app and returns the rendered Element.
pub fn PoemListPage(cx: Scope<VoidProps>) -> Element {
let poem_database = &cx.props.poem_database;
let user_prefs = cx.props.user_prefs.clone();
pub fn PoemListPage(props: VoidProps) -> Element {
#[cfg(target_family = "wasm")]
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);
cx.render(rsx! {
rsx! {
div { class: "{user_theme} {user_font}",
PageBase {
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() }
}
}
})
}
}
pub fn PoemPage(cx: Scope<VoidProps>) -> Element {
let poem_database = &cx.props.poem_database;
let user_prefs = cx.props.user_prefs.clone();
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
pub fn PoemPage(props: VoidProps) -> Element {
#[cfg(target_family = "wasm")]
let poem_database = POEM_DATABASE
.get()
.expect("Poem database is not initialized")
.clone();
#[cfg(any(target_family = "unix", target_family = "windows"))]
let slug = &cx
.props
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);
// #[cfg(any(target_family = "unix", target_family = "windows"))]
let slug = props
.slug
.as_ref()
.expect("A slug was given in the pops.")
.expect("A slug was given in the props.")
.clone();
#[cfg(target_family = "wasm")]
let slug = String::from(
dioxus_router::use_route(cx)
.segment("slug")
.expect("No slug specified."),
);
cx.render(rsx!{
// #[cfg(target_family = "wasm")]
// let slug = String::from(
// use_route()
// .segment("slug")
// .expect("No slug specified."),
// );
rsx! {
div { class: "{user_theme} {user_font}",
PageBase {
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() }
}
}
})
}
}
pub fn SettingsPage(cx: Scope<UserPrefs>) -> Element {
let user_prefs = cx.props.clone();
pub fn SettingsPage(props: UserPrefs) -> Element {
let user_prefs = props.clone();
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
// 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);
cx.render(rsx! {
rsx! {
div { class: "{user_theme} {user_font}",
PageBase {
Title { title: "Settings".to_string(), is_html: false, user_prefs: user_prefs.clone() }
@ -162,14 +209,14 @@ pub mod void_app {
"Font"
}
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: "Open Dyslexic".to_string(), slug: "/settings/?font=open".to_string(), user_prefs: user_prefs.clone() override_font: "font-open".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() }
}
}
}
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());
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...
#[cfg(any(target_family = "unix", target_family = "windows"))]
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() {
let filename = p.to_string();
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_content = poem_to_str.into_iter().collect::<Vec<&str>>().join("\n");
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 =
markdown::to_html_with_options(poem_content.as_str(), &Options::gfm()).unwrap();
let mut split_filename = filename.trim_end_matches(".md").split("_");
@ -41,7 +49,7 @@ impl PoemDatabase {
self.poem_list
.push((creation_date.to_string(), slug.to_string()));
let poem_struct = PoemStruct {
title: poem_title_to_html_string.to_string(),
title: poem_title_to_html_string,
content: poem_content_to_html_string,
creation_date: creation_date.to_string(),
};

View File

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

View File

@ -1,20 +1,22 @@
use dioxus::prelude::*;
#[derive(PartialEq, Props, Clone)]
#[derive(Default, PartialEq, Props, Clone)]
pub struct UserPrefs {
theme: ThemePref,
font: FontPref,
}
#[derive(PartialEq, Clone)]
#[derive(Default, PartialEq, Clone)]
pub enum ThemePref {
Light,
Dark,
#[default]
Auto,
}
#[derive(PartialEq, Clone)]
#[derive(Default, PartialEq, Clone)]
pub enum FontPref {
#[default]
NerdFont,
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: "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 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 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 PAGE_CLASSES: &'static str = "bg-alice-werefox-grey-light dark:bg-alice-werefox-grey";
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: &'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 {
UserPrefs { theme, font }