Implemented user settings feature at a basic level, need to fix CSS for components.
This commit is contained in:
		
							parent
							
								
									9d46693ba8
								
							
						
					
					
						commit
						b78e2c2d57
					
				
					 24 changed files with 402 additions and 185 deletions
				
			
		
							
								
								
									
										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 a new issue