Implemented user settings feature at a basic level, need to fix CSS for components.
This commit is contained in:
parent
9d46693ba8
commit
b78e2c2d57
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"rust-analyzer.linkedProjects": [
|
||||||
|
"./void-fe/Cargo.toml",
|
||||||
|
"./void-fe/Cargo.toml"
|
||||||
|
]
|
||||||
|
}
|
BIN
public/fonts/DejaVuSansMono.ttf
Normal file
BIN
public/fonts/DejaVuSansMono.ttf
Normal file
Binary file not shown.
2
public/styles/tailwind.min.css
vendored
2
public/styles/tailwind.min.css
vendored
File diff suppressed because one or more lines are too long
76
rustfmt.toml
Normal file
76
rustfmt.toml
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
max_width = 100
|
||||||
|
hard_tabs = false
|
||||||
|
tab_spaces = 4
|
||||||
|
newline_style = "Auto"
|
||||||
|
indent_style = "Block"
|
||||||
|
use_small_heuristics = "Default"
|
||||||
|
fn_call_width = 60
|
||||||
|
attr_fn_like_width = 70
|
||||||
|
struct_lit_width = 18
|
||||||
|
struct_variant_width = 35
|
||||||
|
array_width = 60
|
||||||
|
chain_width = 60
|
||||||
|
single_line_if_else_max_width = 50
|
||||||
|
wrap_comments = false
|
||||||
|
format_code_in_doc_comments = false
|
||||||
|
doc_comment_code_block_width = 100
|
||||||
|
comment_width = 80
|
||||||
|
normalize_comments = false
|
||||||
|
normalize_doc_attributes = false
|
||||||
|
format_strings = false
|
||||||
|
format_macro_matchers = false
|
||||||
|
format_macro_bodies = true
|
||||||
|
hex_literal_case = "Preserve"
|
||||||
|
empty_item_single_line = true
|
||||||
|
struct_lit_single_line = true
|
||||||
|
fn_single_line = false
|
||||||
|
where_single_line = false
|
||||||
|
imports_indent = "Block"
|
||||||
|
imports_layout = "Mixed"
|
||||||
|
imports_granularity = "Preserve"
|
||||||
|
group_imports = "Preserve"
|
||||||
|
reorder_imports = true
|
||||||
|
reorder_modules = true
|
||||||
|
reorder_impl_items = false
|
||||||
|
type_punctuation_density = "Wide"
|
||||||
|
space_before_colon = false
|
||||||
|
space_after_colon = true
|
||||||
|
spaces_around_ranges = false
|
||||||
|
binop_separator = "Front"
|
||||||
|
remove_nested_parens = true
|
||||||
|
combine_control_expr = true
|
||||||
|
short_array_element_width_threshold = 10
|
||||||
|
overflow_delimited_expr = false
|
||||||
|
struct_field_align_threshold = 0
|
||||||
|
enum_discrim_align_threshold = 0
|
||||||
|
match_arm_blocks = true
|
||||||
|
match_arm_leading_pipes = "Never"
|
||||||
|
force_multiline_blocks = false
|
||||||
|
# fn_params_layout = "Tall"
|
||||||
|
brace_style = "SameLineWhere"
|
||||||
|
control_brace_style = "AlwaysSameLine"
|
||||||
|
trailing_semicolon = true
|
||||||
|
trailing_comma = "Vertical"
|
||||||
|
match_block_trailing_comma = false
|
||||||
|
blank_lines_upper_bound = 1
|
||||||
|
blank_lines_lower_bound = 0
|
||||||
|
edition = "2021"
|
||||||
|
version = "One"
|
||||||
|
inline_attribute_width = 0
|
||||||
|
format_generated_files = true
|
||||||
|
merge_derives = true
|
||||||
|
use_try_shorthand = false
|
||||||
|
use_field_init_shorthand = false
|
||||||
|
force_explicit_abi = true
|
||||||
|
condense_wildcard_suffixes = false
|
||||||
|
color = "Auto"
|
||||||
|
# required_version = "1.5.1"
|
||||||
|
unstable_features = true
|
||||||
|
disable_all_formatting = false
|
||||||
|
skip_children = false
|
||||||
|
hide_parse_errors = false
|
||||||
|
error_on_line_overflow = false
|
||||||
|
error_on_unformatted = false
|
||||||
|
ignore = []
|
||||||
|
emit_mode = "Files"
|
||||||
|
make_backup = false
|
@ -4,4 +4,4 @@ use void_be::web_app_backend;
|
|||||||
async fn main() -> Result<(), rocket::Error> {
|
async fn main() -> Result<(), rocket::Error> {
|
||||||
let _rocket = web_app_backend::build_rocket().await.launch().await;
|
let _rocket = web_app_backend::build_rocket().await.launch().await;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -13,30 +13,68 @@ 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::PoemRequest;
|
||||||
use void_fe::void_app::{self, VirtualDom};
|
use void_fe::void_app::{self, VirtualDom};
|
||||||
use void_fe::utils::prop_structs::{DarkModeProps, PoemRequest};
|
|
||||||
|
use void_fe::utils::user_prefs::*;
|
||||||
|
|
||||||
|
async fn get_user_prefs(cookies: &CookieJar<'_>) -> UserPrefs {
|
||||||
|
let user_theme = match cookies.get("theme") {
|
||||||
|
Some(c) => match c.value() {
|
||||||
|
"auto" => ThemePref::Auto,
|
||||||
|
"light" => ThemePref::Light,
|
||||||
|
"dark" => ThemePref::Dark,
|
||||||
|
_ => {
|
||||||
|
cookies.remove(Cookie::named("theme"));
|
||||||
|
cookies.add(Cookie::new("theme", "auto"));
|
||||||
|
ThemePref::Auto
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
cookies.add(Cookie::new("theme", "auto"));
|
||||||
|
ThemePref::Auto
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let user_font = match cookies.get("font") {
|
||||||
|
Some(c) => match c.value() {
|
||||||
|
"nerd" => FontPref::NerdFont,
|
||||||
|
"open" => FontPref::OpenDyslexic,
|
||||||
|
_ => {
|
||||||
|
cookies.remove(Cookie::named("font"));
|
||||||
|
cookies.add(Cookie::new("font", "open"));
|
||||||
|
FontPref::OpenDyslexic
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
cookies.add(Cookie::new("font", "open"));
|
||||||
|
FontPref::OpenDyslexic
|
||||||
|
}
|
||||||
|
};
|
||||||
|
UserPrefs::new(user_theme, user_font)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_user_theme(cookies: &CookieJar<'_>, theme: &str) {
|
||||||
|
if theme == "light" || theme == "dark" || theme == "auto" {
|
||||||
|
cookies.remove(Cookie::named("theme"));
|
||||||
|
cookies.add(Cookie::new("theme", format!("{theme}")));
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_user_font(cookies: &CookieJar<'_>, font: &str) {
|
||||||
|
if font == "nerd" || font == "open" {
|
||||||
|
cookies.remove(Cookie::named("font"));
|
||||||
|
cookies.add(Cookie::new("font", format!("{font}")));
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(cookies: &CookieJar<'_>) -> Template {
|
async fn index(cookies: &CookieJar<'_>) -> Template {
|
||||||
let dark_mode = match cookies.get("dark-mode") {
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
Some(c) => {
|
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, user_prefs);
|
||||||
if c.value() == "true" {
|
|
||||||
true
|
|
||||||
} else if c.value() == "false" {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => false,
|
|
||||||
};
|
|
||||||
let mut vdom = VirtualDom::new_with_props(
|
|
||||||
void_app::HomePage,
|
|
||||||
DarkModeProps {
|
|
||||||
slug: Some("/".to_string()),
|
|
||||||
dark_mode,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
let output = dioxus_ssr::render(&vdom);
|
let output = dioxus_ssr::render(&vdom);
|
||||||
Template::render(
|
Template::render(
|
||||||
@ -45,45 +83,44 @@ pub mod web_app_backend {
|
|||||||
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 {
|
dark_mode: "",
|
||||||
true => "dark",
|
|
||||||
false => ""
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/?dark_mode&<callback>")]
|
#[get("/", rank = 3)]
|
||||||
async fn dark_mode(cookies: &CookieJar<'_>, callback: &str) -> Redirect {
|
async fn settings(cookies: &CookieJar<'_>) -> Template {
|
||||||
match cookies.get("dark-mode") {
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
Some(_) => cookies.remove(Cookie::named("dark-mode")),
|
let mut vdom = VirtualDom::new_with_props(void_app::SettingsPage, user_prefs);
|
||||||
None => cookies.add(Cookie::new("dark-mode", "true")),
|
let _ = vdom.rebuild();
|
||||||
};
|
let output = dioxus_ssr::render(&vdom);
|
||||||
let callback_uri = format!("{callback}");
|
Template::render(
|
||||||
Redirect::to(callback_uri)
|
"index",
|
||||||
|
context! {
|
||||||
|
app_title: "Settings",
|
||||||
|
style_include: "<link href=/styles/tailwind.min.css rel=stylesheet />",
|
||||||
|
test: &output,
|
||||||
|
dark_mode: ""
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/?<theme>", rank = 2)]
|
||||||
|
async fn theme(cookies: &CookieJar<'_>, theme: &str) -> Redirect {
|
||||||
|
set_user_theme(cookies, theme).await;
|
||||||
|
Redirect::to("/settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/?<font>")]
|
||||||
|
async fn font(cookies: &CookieJar<'_>, font: &str) -> Redirect {
|
||||||
|
set_user_font(cookies, font).await;
|
||||||
|
Redirect::to("/settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn poem_list(cookies: &CookieJar<'_>) -> Template {
|
async fn poem_list(cookies: &CookieJar<'_>) -> Template {
|
||||||
let dark_mode = match cookies.get("dark-mode") {
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
Some(c) => {
|
let mut vdom = VirtualDom::new_with_props(void_app::PoemListPage, user_prefs);
|
||||||
if c.value() == "true" {
|
|
||||||
true
|
|
||||||
} else if c.value() == "false" {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => false,
|
|
||||||
};
|
|
||||||
let mut vdom = VirtualDom::new_with_props(
|
|
||||||
void_app::PoemListPage,
|
|
||||||
DarkModeProps {
|
|
||||||
slug: Some(String::from("/poems")),
|
|
||||||
dark_mode,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
let output = dioxus_ssr::render(&vdom);
|
let output = dioxus_ssr::render(&vdom);
|
||||||
Template::render(
|
Template::render(
|
||||||
@ -92,33 +129,19 @@ pub mod web_app_backend {
|
|||||||
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 {
|
dark_mode: "",
|
||||||
true => "dark",
|
|
||||||
false => ""
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/<entry>")]
|
#[get("/<entry>")]
|
||||||
async fn poem(cookies: &CookieJar<'_>, entry: &str) -> Template {
|
async fn poem(cookies: &CookieJar<'_>, entry: &str) -> Template {
|
||||||
let dark_mode = match cookies.get("dark-mode") {
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
Some(c) => {
|
|
||||||
if c.value() == "true" {
|
|
||||||
true
|
|
||||||
} else if c.value() == "false" {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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: format!("{entry}"),
|
slug: format!("{entry}"),
|
||||||
dark_mode: Some(dark_mode),
|
user_prefs,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
@ -129,10 +152,7 @@ pub mod web_app_backend {
|
|||||||
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 {
|
dark_mode: "",
|
||||||
true => "dark",
|
|
||||||
false => ""
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -144,7 +164,8 @@ pub mod web_app_backend {
|
|||||||
.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("/poems", routes![poem_list, poem])
|
.mount("/poems", routes![poem_list, poem])
|
||||||
.mount("/", routes![dark_mode, index])
|
.mount("/settings", routes![settings, theme, font])
|
||||||
|
.mount("/", routes![index])
|
||||||
.attach(Template::fairing())
|
.attach(Template::fairing())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,23 +20,29 @@ title = "A Letter to the Void"
|
|||||||
|
|
||||||
[web.watcher]
|
[web.watcher]
|
||||||
|
|
||||||
# when watcher trigger, regenerate the `index.html`
|
# when watcher triggers, regenerate the `index.html`
|
||||||
reload_html = true
|
reload_html = true
|
||||||
|
|
||||||
# which files or dirs will be watcher monitoring
|
# which files or dirs will be watcher monitoring
|
||||||
watch_path = ["src", "data", "../public", "tailwind.config.js", "Dioxus.toml", "Cargo.toml", "build.rs"]
|
watch_path = ["src", "data", "../public", "tailwind.config.js", "Dioxus.toml", "Cargo.toml", "build.rs"]
|
||||||
|
|
||||||
|
# implement redirect on 404
|
||||||
|
index_on_404 = true
|
||||||
|
|
||||||
# include `assets` in web platform
|
# include `assets` in web platform
|
||||||
[web.resource]
|
[web.resource]
|
||||||
|
|
||||||
# CSS style file
|
# CSS style file
|
||||||
style = ["styles/tailwind.min.css"]
|
style = ["/styles/tailwind.min.css"]
|
||||||
|
|
||||||
# Javascript code file
|
# Javascript code file
|
||||||
script = []
|
script = []
|
||||||
|
|
||||||
[web.resource.dev]
|
[web.resource.dev]
|
||||||
|
|
||||||
|
# CSS style file
|
||||||
|
style = ["/styles/tailwind.min.css"]
|
||||||
|
|
||||||
# Javascript code file
|
# Javascript code file
|
||||||
# serve: [dev-server] only
|
# serve: [dev-server] only
|
||||||
script = []
|
script = []
|
||||||
|
@ -17,4 +17,4 @@ fn main() {
|
|||||||
// for f in std::fs::read_dir("../data/poems").unwrap() {
|
// for f in std::fs::read_dir("../data/poems").unwrap() {
|
||||||
// content.push(std::fs::read_to_string(f.unwrap().path()).unwrap());
|
// content.push(std::fs::read_to_string(f.unwrap().path()).unwrap());
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
7
void-fe/data/other/homepage.md
Normal file
7
void-fe/data/other/homepage.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
Welcome, and I hope you enjoy your stay!\
|
||||||
|
"A Letter to the Void" is a passion project of mine in which I wrote poems about my past life experiences, present, and hopes for the future throughout my transition.\
|
||||||
|
The topics range from my feelings through transitioning (of course), past abuse, mental health exploration, and an overall journey to grow and become a better creature.\
|
||||||
|
I hope you enjoy the time you spend here, and sincerely, thank you.\
|
||||||
|
\
|
||||||
|
🖤 Alice Icehart Werefox
|
@ -1,4 +1,6 @@
|
|||||||
pub mod void_poem;
|
pub mod void_buttons;
|
||||||
pub mod void_footer;
|
pub mod void_footer;
|
||||||
|
pub mod void_page;
|
||||||
|
pub mod void_poem;
|
||||||
pub mod void_title;
|
pub mod void_title;
|
||||||
pub mod void_buttons;
|
pub mod void_content;
|
@ -1,5 +1,5 @@
|
|||||||
|
use crate::utils::prop_structs::{ButtonProps, ContentChildren};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use crate::utils::prop_structs::ButtonProps;
|
|
||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
use dioxus_router::Link;
|
use dioxus_router::Link;
|
||||||
@ -7,8 +7,7 @@ use dioxus_router::Link;
|
|||||||
pub fn BackToHomePage(cx: Scope) -> Element {
|
pub fn BackToHomePage(cx: Scope) -> Element {
|
||||||
#[cfg(any(target_family = "windows", target_family = "unix"))]
|
#[cfg(any(target_family = "windows", target_family = "unix"))]
|
||||||
return cx.render(rsx!{
|
return cx.render(rsx!{
|
||||||
a { class: "flex justify-center p-4 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-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",
|
a {href: "/",
|
||||||
href: "/",
|
|
||||||
p {
|
p {
|
||||||
"Back to the homepage"
|
"Back to the homepage"
|
||||||
}
|
}
|
||||||
@ -16,8 +15,7 @@ pub fn BackToHomePage(cx: Scope) -> Element {
|
|||||||
});
|
});
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
return cx.render(rsx!{
|
return cx.render(rsx!{
|
||||||
Link { class: "flex justify-center p-4 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-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",
|
Link { to: "/",
|
||||||
to: "/",
|
|
||||||
p {
|
p {
|
||||||
"Back to the homepage"
|
"Back to the homepage"
|
||||||
}
|
}
|
||||||
@ -32,18 +30,24 @@ pub fn NavigationButton(cx: Scope<ButtonProps>) -> Element {
|
|||||||
let slug_ref = slug.as_str();
|
let slug_ref = slug.as_str();
|
||||||
#[cfg(any(target_family = "windows", target_family = "unix"))]
|
#[cfg(any(target_family = "windows", target_family = "unix"))]
|
||||||
return cx.render(rsx!{
|
return cx.render(rsx!{
|
||||||
a { class: "flex mx-auto max-w-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-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",
|
a { href: "{slug_ref}",
|
||||||
href: "{slug_ref}",
|
|
||||||
"{title_ref}"
|
"{title_ref}"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
return cx.render(rsx!{
|
return cx.render(rsx!{
|
||||||
Link { class: "flex mx-auto max-w-full justify-center p-4 ml-2 mr-2 text-xl text-center ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-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",
|
Link { 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 {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div { class: "grid md:grid-flow-col grid-flow-row gap-y-4",
|
||||||
|
&cx.props.children
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
19
void-fe/src/components/void_content.rs
Normal file
19
void-fe/src/components/void_content.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Might wanna move stuff form `void_poem.rs` into here...
|
||||||
|
use crate::utils::prop_structs::{ContentProps};
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
pub fn RenderContent(cx: Scope<ContentProps>) -> Element {
|
||||||
|
let content = &cx.props.content;
|
||||||
|
#[cfg(any(target_family = "windows", target_family = "unix"))]
|
||||||
|
return cx.render(rsx!{
|
||||||
|
div { class: "flex p-4 ml-2 mr-2 ring-4",
|
||||||
|
"{content}",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#[cfg(target_family = "wasm")]
|
||||||
|
return cx.render(rsx!{
|
||||||
|
div { class: "flex p-4 ml-2 mr-2 ring-4",
|
||||||
|
dangerous_inner_html: "{content}",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -1,15 +1,19 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use crate::components::void_buttons::NavigationButton;
|
||||||
|
|
||||||
pub fn Footer(cx: Scope) -> Element {
|
pub fn Footer(cx: Scope) -> Element {
|
||||||
cx.render(rsx!{
|
cx.render(rsx! {
|
||||||
MutantStandardFooter {}
|
MutantStandardFooter {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn MutantStandardFooter(cx: Scope) -> Element {
|
fn MutantStandardFooter(cx: Scope) -> Element {
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
div { class: "flex p-4 mx-auto max-w-full justify-center text-md text-center 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-grey-dark dark:text-alice-werefox-grey-light",
|
div {
|
||||||
"This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License"
|
NavigationButton { title: "⚙️".to_string(), slug: "/settings".to_string() }
|
||||||
|
div {
|
||||||
|
"This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
13
void-fe/src/components/void_page.rs
Normal file
13
void-fe/src/components/void_page.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use crate::utils::prop_structs::PageChildren;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
pub fn PageBase<'a>(cx: Scope<'a, PageChildren<'a>>) -> Element {
|
||||||
|
cx.render(rsx!{
|
||||||
|
// div { class: "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 let button_classes hover:text-alice-werefox-blue-dark hover:ring-alice-werefox-blue dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue hover:animate-yip transition", hidden: true }
|
||||||
|
div {
|
||||||
|
div { class: "container space-y-4 mx-auto p-4",
|
||||||
|
&cx.props.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
use dioxus::prelude::*;
|
|
||||||
use crate::utils::helpers;
|
|
||||||
use crate::utils::prop_structs::{PoemChildren, PoemData};
|
|
||||||
use crate::components::void_buttons::*;
|
use crate::components::void_buttons::*;
|
||||||
use crate::components::void_title::*;
|
use crate::components::void_title::*;
|
||||||
|
use crate::utils::helpers;
|
||||||
|
use crate::utils::prop_structs::{PoemChildren, PoemData};
|
||||||
|
use super::super::utils::user_prefs::*;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
pub fn PoemList(cx: Scope) -> Element {
|
pub fn PoemList(cx: Scope) -> Element {
|
||||||
let poem_list = helpers::get_poem_list();
|
let poem_list = helpers::get_poem_list();
|
||||||
@ -30,7 +31,7 @@ pub fn GetPoem(cx: Scope<PoemData>) -> Element {
|
|||||||
let slug = String::from(cx.props.slug.clone().expect("No slug specified."));
|
let slug = String::from(cx.props.slug.clone().expect("No slug specified."));
|
||||||
let (title, content, creation_date) = helpers::get_poem(slug.clone());
|
let (title, content, creation_date) = helpers::get_poem(slug.clone());
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
Title { title: title, is_html: true }
|
Title { title: title, is_html: true, user_prefs: UserPrefs::new(ThemePref::Auto, FontPref::OpenDyslexic)}
|
||||||
MakePoem{
|
MakePoem{
|
||||||
PoemContent { content: content, creation_date: creation_date }
|
PoemContent { content: content, creation_date: creation_date }
|
||||||
}
|
}
|
||||||
@ -47,8 +48,8 @@ pub fn PoemContent(cx: Scope<PoemData>) -> Element {
|
|||||||
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
||||||
return cx.render(rsx! {
|
return cx.render(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 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-4 ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light",
|
details { class: "group p-4 max-w-fit space-y-4",
|
||||||
summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-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-2 ring-2",
|
||||||
}
|
}
|
||||||
div { class: "font-nerd flex flex-col space-y-4 py-4", "{content}{creation_date}"
|
div { class: "font-nerd flex flex-col space-y-4 py-4", "{content}{creation_date}"
|
||||||
}
|
}
|
||||||
@ -58,8 +59,8 @@ pub fn PoemContent(cx: Scope<PoemData>) -> Element {
|
|||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
return cx.render(rsx! {
|
return cx.render(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 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-4 ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-light",
|
details { class: "group p-4 max-w-fit space-y-4",
|
||||||
summary { class: "group-open:before:content-['Close'] before:content-['Open'] flex justify-center p-2 ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-grey-dark dark:text-alice-werefox-grey-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-2 ring-2",
|
||||||
}
|
}
|
||||||
div { class: "font-nerd flex flex-col space-y-4 py-4",
|
div { class: "font-nerd flex flex-col space-y-4 py-4",
|
||||||
dangerous_inner_html: "{content}{creation_date}",
|
dangerous_inner_html: "{content}{creation_date}",
|
||||||
@ -67,4 +68,4 @@ pub fn PoemContent(cx: Scope<PoemData>) -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
use dioxus::prelude::*;
|
|
||||||
use crate::utils::prop_structs::TitleProps;
|
use crate::utils::prop_structs::TitleProps;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
pub fn Title(cx: Scope<TitleProps>) -> Element {
|
pub fn Title(cx: Scope<TitleProps>) -> Element {
|
||||||
|
let user_prefs = cx.props.user_prefs.clone();
|
||||||
let title = cx.props.title.clone();
|
let title = cx.props.title.clone();
|
||||||
let is_html = cx.props.is_html;
|
let is_html = cx.props.is_html;
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
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-grey-dark dark:text-alice-werefox-grey-light",
|
div { class: "p-4 ring-4",
|
||||||
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 }
|
TitleHtml { title: title, is_html: is_html, user_prefs: user_prefs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -17,22 +18,22 @@ fn TitleHtml(cx: Scope<TitleProps>) -> Element {
|
|||||||
let title = cx.props.title.clone();
|
let title = cx.props.title.clone();
|
||||||
if cx.props.is_html {
|
if cx.props.is_html {
|
||||||
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
||||||
return cx.render(rsx!{
|
return cx.render(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} "
|
"{title} "
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
return cx.render(rsx!{
|
return cx.render(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 cx.render(rsx! {
|
||||||
span {
|
span {
|
||||||
"{title}"
|
"{title}"
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,3 +6,8 @@
|
|||||||
font-family: "OpenDyslexic";
|
font-family: "OpenDyslexic";
|
||||||
src: url("/fonts/OpenDyslexic-Regular.otf");
|
src: url("/fonts/OpenDyslexic-Regular.otf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "DejaVuSansMono";
|
||||||
|
src: url("/fonts/DejaVuSansMono.ttf");
|
||||||
|
}
|
||||||
|
@ -4,50 +4,50 @@
|
|||||||
|
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
|
||||||
mod components;
|
mod components;
|
||||||
pub mod utils;
|
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 {
|
||||||
|
|
||||||
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
|
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
|
||||||
pub use dioxus::prelude::*;
|
pub use dioxus::prelude::*;
|
||||||
use rust_embed::RustEmbed;
|
|
||||||
|
|
||||||
use crate::components::void_buttons::*;
|
use crate::components::void_buttons::*;
|
||||||
|
use crate::components::void_content::*;
|
||||||
use crate::components::void_footer::*;
|
use crate::components::void_footer::*;
|
||||||
|
use crate::components::void_page::PageBase;
|
||||||
use crate::components::void_poem::*;
|
use crate::components::void_poem::*;
|
||||||
use crate::components::void_title::*;
|
use crate::components::void_title::*;
|
||||||
use crate::utils::helpers;
|
use crate::utils::helpers;
|
||||||
use crate::utils::prop_structs::*;
|
use crate::utils::prop_structs::*;
|
||||||
|
use crate::utils::user_prefs::*;
|
||||||
|
|
||||||
#[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, Route, Router, Redirect};
|
use dioxus_router::{Link, Redirect, Route, Router};
|
||||||
#[cfg(any(target_family = "wasm"))]
|
#[cfg(any(target_family = "wasm"))]
|
||||||
use dioxus_use_storage::use_local_storage;
|
use dioxus_use_storage::use_local_storage;
|
||||||
|
|
||||||
|
|
||||||
#[derive(RustEmbed)]
|
|
||||||
#[folder = "data/poems"]
|
|
||||||
pub struct Poems;
|
|
||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
pub fn DioxusApp(cx: Scope) -> Element {
|
pub fn DioxusApp(cx: Scope) -> Element {
|
||||||
// use dioxus_router::Redirect;
|
// use dioxus_router::Redirect;
|
||||||
|
|
||||||
|
let user_prefs = UserPrefs::new(ThemePref::Auto, FontPref::OpenDyslexic);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
|
div { class: "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 let button_classes hover:text-alice-werefox-blue-dark hover:ring-alice-werefox-blue dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue hover:animate-yip transition" }
|
||||||
Router {
|
Router {
|
||||||
Route { to: "/", self::HomePage { dark_mode: true, } }
|
Route { to: "/",
|
||||||
Route { to: "/poems",
|
self::HomePage { user_prefs }
|
||||||
PoemListPage { slug: "".to_string(), dark_mode: true, }
|
|
||||||
}
|
|
||||||
Route { to: "/poems/:slug",
|
|
||||||
PoemPage { slug: "".to_string(), dark_mode: true, }
|
|
||||||
}
|
}
|
||||||
|
Route { to: "/poems", PoemListPage { user_prefs } }
|
||||||
|
Route { to: "/poems/:slug", PoemPage { slug: "".to_string(), user_prefs } }
|
||||||
|
Route { to: "/settings", SettingsPage { user_prefs } }
|
||||||
|
Route { to: "/settings/dark", SettingsPage { user_prefs } }
|
||||||
|
Route { to: "/settings/font", SettingsPage { user_prefs } }
|
||||||
Route { to: "", PageNotFound {} }
|
Route { to: "", PageNotFound {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -61,35 +61,22 @@ 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<DarkModeProps>) -> Element {
|
pub fn HomePage(cx: Scope<UserPrefs>) -> Element {
|
||||||
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
let user_prefs = cx.props.clone();
|
||||||
let slug = cx.props.slug.clone().expect("Slug for dark mode redirect.");
|
let (user_theme, user_font) = user_prefs.get_prefs(false);
|
||||||
#[cfg(target_family = "wasm")]
|
|
||||||
let slug = "".to_string();
|
|
||||||
let title = "A Letter to the Void".to_string();
|
let title = "A Letter to the Void".to_string();
|
||||||
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: "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 let button_classes hover:text-alice-werefox-blue-dark hover:ring-alice-werefox-blue dark:hover:text-alice-werefox-blue-light dark:hover:ring-alice-werefox-blue hover:animate-yip transition", hidden: true }
|
||||||
div { class: "container space-y-4 mx-auto p-4",
|
div { class: "{user_theme} {user_font}",
|
||||||
Title { title: title, is_html: false }
|
PageBase {
|
||||||
div { class: "flex p-4 ml-2 mr-2 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-grey-dark dark:text-alice-werefox-grey-light",
|
Title { title: title, is_html: false, user_prefs: user_prefs }
|
||||||
p { class: "text-lg text-center",
|
RenderContent { content: helpers::get_homepage_paragraph() }
|
||||||
"Welcome, and I hope you enjoy your stay!"
|
ButtonGroup {
|
||||||
br {}
|
NavigationButton { title: "See Latest Entry".to_string(), slug: helpers::get_latest_entry("".to_string()) }
|
||||||
"\"A Letter to the Void\" is a passion project of mine in which I wrote poems about my past life experiences, present, and hopes for the future throughout my transition."
|
NavigationButton { title: "See Oldest Entry".to_string(), slug: helpers::get_oldest_entry("".to_string()) }
|
||||||
br {}
|
NavigationButton { title: "See All Entries".to_string(), slug: "/poems".to_string() }
|
||||||
"The topics range from my feelings through transitioning (of course), past abuse, mental health exploration, and an overall journey to grow and become a better creature."
|
|
||||||
br {}
|
|
||||||
"I hope you enjoy the time you spend here, and sincerely, thank you."
|
|
||||||
br {}
|
|
||||||
br {}
|
|
||||||
"🖤 Alice Icehart Werefox"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
NavigationButton { title: "See Latest Entry".to_string(), slug: helpers::get_latest_entry(slug.clone()) }
|
|
||||||
NavigationButton { title: "See Oldest Entry".to_string(), slug: helpers::get_oldest_entry(slug.clone()) }
|
|
||||||
NavigationButton { title: "See All Entries".to_string(), slug: "/poems".to_string() }
|
|
||||||
Footer {}
|
Footer {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,11 +84,13 @@ pub mod void_app {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Renders the app and returns the rendered Element.
|
/// Renders the app and returns the rendered Element.
|
||||||
pub fn PoemListPage(cx: Scope<DarkModeProps>) -> Element {
|
pub fn PoemListPage(cx: Scope<UserPrefs>) -> Element {
|
||||||
cx.render(rsx!{
|
let user_prefs = cx.props.clone();
|
||||||
div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
|
let (user_theme, user_font) = user_prefs.get_prefs(false);
|
||||||
div { class: "container space-y-4 mx-auto p-4",
|
cx.render(rsx! {
|
||||||
Title { title: "A Letter to the Void".to_string(), is_html: false }
|
div { class: "{user_theme} {user_font}",
|
||||||
|
PageBase {
|
||||||
|
Title { title: "A Letter to the Void".to_string(), is_html: false, user_prefs: user_prefs }
|
||||||
BackToHomePage {}
|
BackToHomePage {}
|
||||||
PoemList {}
|
PoemList {}
|
||||||
BackToHomePage {}
|
BackToHomePage {}
|
||||||
@ -112,6 +101,8 @@ pub mod void_app {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn PoemPage(cx: Scope<PoemRequest>) -> Element {
|
pub fn PoemPage(cx: Scope<PoemRequest>) -> Element {
|
||||||
|
let user_prefs = cx.props.user_prefs.clone();
|
||||||
|
let (user_theme, user_font) = user_prefs.get_prefs(false);
|
||||||
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
||||||
let slug = cx.props.slug.clone();
|
let slug = cx.props.slug.clone();
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
@ -120,17 +111,12 @@ 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: "{user_theme} {user_font}",
|
||||||
div { class: "container space-y-4 mx-auto p-4",
|
PageBase {
|
||||||
BackToHomePage {}
|
BackToHomePage {}
|
||||||
GetPoem { slug: slug.clone(), dark_mode: dark_mode }
|
GetPoem { slug: slug.clone() }
|
||||||
div { class: "grid md:grid-cols-4 md:grid-rows-1 grid-cols-1 grid-rows-4 gap-y-4",
|
ButtonGroup {
|
||||||
NavigationButton { title: "Oldest".to_string(), slug: helpers::get_oldest_entry(slug.clone()) }
|
NavigationButton { title: "Oldest".to_string(), slug: helpers::get_oldest_entry(slug.clone()) }
|
||||||
NavigationButton { title: "Previous".to_string(), slug: helpers::get_previous_entry(slug.clone()) }
|
NavigationButton { title: "Previous".to_string(), slug: helpers::get_previous_entry(slug.clone()) }
|
||||||
NavigationButton { title: "Next".to_string(), slug: helpers::get_next_entry(slug.clone()) }
|
NavigationButton { title: "Next".to_string(), slug: helpers::get_next_entry(slug.clone()) }
|
||||||
@ -142,4 +128,33 @@ pub mod void_app {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn SettingsPage(cx: Scope<UserPrefs>) -> Element {
|
||||||
|
let user_prefs = cx.props.clone();
|
||||||
|
let (user_theme, user_font) = user_prefs.get_prefs(false);
|
||||||
|
cx.render(rsx! {
|
||||||
|
div { class: "{user_theme} {user_font}",
|
||||||
|
PageBase {
|
||||||
|
Title { title: "Settings".to_string(), is_html: false, user_prefs: user_prefs }
|
||||||
|
BackToHomePage {}
|
||||||
|
div { class: "grid grid-flow-row space-y-4",
|
||||||
|
ButtonGroup {
|
||||||
|
NavigationButton { title: "Light".to_string(), slug: "/settings/?theme=light".to_string() }
|
||||||
|
NavigationButton { title: "Dark".to_string(), slug: "/settings/?theme=dark".to_string() }
|
||||||
|
NavigationButton { title: "Auto".to_string(), slug: "/settings/?theme=auto".to_string() }
|
||||||
|
}
|
||||||
|
ButtonGroup {
|
||||||
|
span { class: "font-nerd",
|
||||||
|
NavigationButton { title: "Nerd Font".to_string(), slug: "/settings/?font=nerd".to_string() }
|
||||||
|
}
|
||||||
|
span { class: "font-open",
|
||||||
|
NavigationButton { title: "Open Dyslexic".to_string(), slug: "/settings/?font=open".to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BackToHomePage {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
use console_error_panic_hook;
|
use console_error_panic_hook;
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod prop_structs;
|
pub mod prop_structs;
|
||||||
pub mod user_prefs;
|
pub mod user_prefs;
|
||||||
|
@ -1,6 +1,21 @@
|
|||||||
use std::collections::VecDeque;
|
use rust_embed::RustEmbed;
|
||||||
use crate::void_app::Poems;
|
|
||||||
use markdown::Options;
|
use markdown::Options;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "data/other"]
|
||||||
|
struct OtherData;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "data/poems"]
|
||||||
|
struct Poems;
|
||||||
|
|
||||||
|
pub fn get_homepage_paragraph() -> String {
|
||||||
|
let homepage_paragraph_content = OtherData::get("homepage.md").expect("Found homepage paragraph.");
|
||||||
|
let homepage_paragraph_to_string = std::str::from_utf8(homepage_paragraph_content.data.as_ref()).expect("Homepage file is valid UTF-8");
|
||||||
|
let test = markdown::to_html_with_options(homepage_paragraph_to_string, &Options::gfm()).unwrap();
|
||||||
|
test
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_poem(slug: String) -> (String, String, String) {
|
pub fn get_poem(slug: String) -> (String, String, String) {
|
||||||
let filename = String::from(String::from(slug.clone()) + ".md");
|
let filename = String::from(String::from(slug.clone()) + ".md");
|
||||||
@ -16,7 +31,11 @@ pub fn get_poem(slug: String) -> (String, String, String) {
|
|||||||
markdown::to_html_with_options(poem_title, &Options::gfm()).unwrap();
|
markdown::to_html_with_options(poem_title, &Options::gfm()).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();
|
||||||
(poem_title_to_html_string, poem_content_to_html_string, creation_date)
|
(
|
||||||
|
poem_title_to_html_string,
|
||||||
|
poem_content_to_html_string,
|
||||||
|
creation_date,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_poem_list() -> Vec<(String, String)> {
|
pub fn get_poem_list() -> Vec<(String, String)> {
|
||||||
@ -94,4 +113,4 @@ pub fn get_next_entry(current: String) -> String {
|
|||||||
Some(entry) => format!("/poems/{entry}"),
|
Some(entry) => format!("/poems/{entry}"),
|
||||||
None => format!("/poems/{current}"),
|
None => format!("/poems/{current}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
use crate::void_app::{Element, Props};
|
use crate::void_app::{Element, Props};
|
||||||
|
|
||||||
|
use super::user_prefs::UserPrefs;
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
pub struct PoemRequest {
|
pub struct PoemRequest {
|
||||||
pub slug: String,
|
pub slug: String,
|
||||||
pub dark_mode: Option<bool>,
|
pub user_prefs: UserPrefs,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
|
||||||
pub struct DarkModeProps {
|
|
||||||
pub dark_mode: bool,
|
|
||||||
pub slug: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
pub struct TitleProps {
|
pub struct TitleProps {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub is_html: bool,
|
pub is_html: bool,
|
||||||
|
pub user_prefs: UserPrefs,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Props)]
|
||||||
|
pub struct ContentProps {
|
||||||
|
pub content: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
@ -33,7 +35,18 @@ pub struct PoemData {
|
|||||||
pub dark_mode: Option<bool>,
|
pub dark_mode: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These next three should all just be one prop.
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
pub struct PoemChildren<'a> {
|
pub struct PoemChildren<'a> {
|
||||||
pub children: Element<'a>,
|
pub children: Element<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Props)]
|
||||||
|
pub struct PageChildren<'a> {
|
||||||
|
pub children: Element<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Props)]
|
||||||
|
pub struct ContentChildren<'a> {
|
||||||
|
pub children: Element<'a>,
|
||||||
|
}
|
@ -1,24 +1,29 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Props, Clone)]
|
||||||
pub struct UserPrefs {
|
pub struct UserPrefs {
|
||||||
theme: ThemePref,
|
theme: ThemePref,
|
||||||
font: FontPref,
|
font: FontPref,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
pub enum ThemePref {
|
pub enum ThemePref {
|
||||||
Light,
|
Light,
|
||||||
Dark,
|
Dark,
|
||||||
Auto,
|
Auto,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
pub enum FontPref {
|
pub enum FontPref {
|
||||||
NerdFont,
|
NerdFont,
|
||||||
OpenDyslexic,
|
OpenDyslexic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserPrefs {
|
impl UserPrefs {
|
||||||
pub fn new() -> UserPrefs {
|
pub fn new(theme: ThemePref, font: FontPref) -> UserPrefs {
|
||||||
UserPrefs {
|
UserPrefs {
|
||||||
theme: ThemePref::Auto,
|
theme,
|
||||||
font: FontPref::OpenDyslexic,
|
font,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,8 +41,8 @@ impl UserPrefs {
|
|||||||
|
|
||||||
pub fn get_font(&self) -> String {
|
pub fn get_font(&self) -> String {
|
||||||
match &self.font {
|
match &self.font {
|
||||||
FontPref::OpenDyslexic => "...".to_string(),
|
FontPref::OpenDyslexic => "font-open".to_string(),
|
||||||
FontPref::NerdFont => "...".to_string(),
|
FontPref::NerdFont => "font-nerd".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,10 +82,10 @@ impl UserPrefs {
|
|||||||
}
|
}
|
||||||
fn auto_theme_classes(is_button: bool) -> String {
|
fn auto_theme_classes(is_button: bool) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{}{}",
|
"{} {}",
|
||||||
Self::light_theme_classes(is_button)
|
Self::light_theme_classes(is_button)
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.map(|c| if c == "transition" { "" } else { c })
|
.map(|c| if c == "transition" { "".to_string() } else { format!("{c} ") })
|
||||||
.collect::<String>(),
|
.collect::<String>(),
|
||||||
Self::dark_theme_classes(is_button)
|
Self::dark_theme_classes(is_button)
|
||||||
.split(" ")
|
.split(" ")
|
||||||
|
@ -8,7 +8,8 @@ module.exports = {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
nerd: ["OpenDyslexic"],
|
nerd: ["DejaVuSansMono"],
|
||||||
|
open: ["OpenDyslexic"],
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
"ada-werefox-cyan": {
|
"ada-werefox-cyan": {
|
||||||
|
Loading…
Reference in New Issue
Block a user