From fcfa53052adda745aa11ca65cf3e2f2b171697b8 Mon Sep 17 00:00:00 2001 From: Wynd Date: Mon, 16 Jun 2025 16:25:13 +0300 Subject: [PATCH] Better result centering, better desktop/mobile separation for when to load local files vs when to bundle them, added @media queries for true hover --- Cargo.toml | 3 ++- assets/main.css | 56 ++++++++++++++++++++++++++++++------------------- src/main.rs | 37 +++++++++++++++++++++++++------- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2d5977e..73f7170 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,10 @@ include_dir = { version = "0.7" } [features] default = ["desktop"] +bundled = [] web = ["dioxus/web"] desktop = ["dioxus/desktop"] -mobile = ["dioxus/mobile"] +mobile = ["dioxus/mobile", "bundled"] [profile] diff --git a/assets/main.css b/assets/main.css index 7f745a7..b53302d 100644 --- a/assets/main.css +++ b/assets/main.css @@ -48,26 +48,32 @@ body { display: none; position: absolute; width: 100%; - font-size: 40vw; - margin: auto; - text-align: center; - line-height: 1; - opacity: 0; + height: 80%; + justify-content: center; + align-items: center; user-select: none; + opacity: 0; + cursor: default; &.visible { - display: block; + display: flex; animation: 200ms fade-in forwards; } - &.correct { - color: var(--correct); - text-shadow: var(--correct-shadow) 0px 0px 30px; - } + > div { + position: relative; + text-align: center; + font-size: 40vw; - &.wrong { - color: var(--fail); - text-shadow: var(--fail-shadow) 0px 0px 30px; + &.correct { + color: var(--correct); + text-shadow: var(--correct-shadow) 0px 0px 30px; + } + + &.wrong { + color: var(--fail); + text-shadow: var(--fail-shadow) 0px 0px 30px; + } } } @@ -120,8 +126,10 @@ form { box-shadow: 0px 0px 13px -5px var(--selection-shadow); } - &:hover:not(.selected) { - border: solid 1px var(--hoveer); + @media (hover: hover) { + &:hover:not(.selected) { + border: solid 1px var(--hover); + } } > input[type="checkbox"] { @@ -134,9 +142,11 @@ form { flex-grow: 1; } - &:hover, - > *:hover { - cursor: pointer; + @media (hover: hover) { + &:hover, + > *:hover { + cursor: pointer; + } } } @@ -148,10 +158,12 @@ form { color: white; font-size: 42px; - &:hover { - font-size: 48px; - color: var(--selection); - cursor: pointer; + @media (hover: hover) { + &:hover { + font-size: 48px; + color: var(--selection); + cursor: pointer; + } } &:focus { diff --git a/src/main.rs b/src/main.rs index 88de015..e26431a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ -use std::{sync::OnceLock, time::Duration}; +use std::{fs, sync::OnceLock, time::Duration}; #[cfg(feature = "desktop")] use dioxus::desktop::{Config, LogicalSize, WindowBuilder}; use dioxus::prelude::*; +#[cfg(feature = "bundled")] use include_dir::{Dir, include_dir}; use models::{Question, Questions}; use rand::seq::SliceRandom; @@ -11,7 +12,10 @@ use std::env; mod models; +#[cfg(feature = "bundled")] const QUESTIONS_DIR: Dir = include_dir!("./questions"); +#[cfg(feature = "desktop")] +const DEFAULT_DIR: &str = "./questions"; const MAIN_CSS: Asset = asset!("/assets/main.css"); pub static QUESTIONS: OnceLock = OnceLock::new(); @@ -21,10 +25,13 @@ fn get_questions() -> Questions { .get_or_init(|| { let mut questions = Questions::default(); - for entry in QUESTIONS_DIR.files() { - if let Some(content) = entry.contents_utf8() { - if let Ok(other_questions) = toml::from_str(content) { - questions += other_questions; + #[cfg(feature = "bundled")] + { + for file in QUESTIONS_DIR.files() { + if let Some(content) = file.contents_utf8() { + if let Ok(other_questions) = toml::from_str(content) { + questions += other_questions; + } } } } @@ -49,6 +56,16 @@ fn get_questions() -> Questions { questions += other_questions; } + } else if questions.is_empty() { + if let Ok(dir) = fs::read_dir(DEFAULT_DIR) { + for file in dir.flatten() { + if let Ok(questions_str) = std::fs::read_to_string(file.path()) { + if let Ok(other_questions) = toml::from_str(&questions_str) { + questions += other_questions; + } + } + } + } } } @@ -278,6 +295,7 @@ pub fn AnswerCheckbox(current: Signal, id: usize) -> Element { } } +#[allow(clippy::redundant_closure)] #[component] pub fn ResultPopup(is_correct: Signal, is_wrong: Signal) -> Element { let is_correct = use_memo(move || is_correct()); @@ -288,9 +306,12 @@ pub fn ResultPopup(is_correct: Signal, is_wrong: Signal) -> Element div { id: "result", class: if is_visible() { "visible" }, - class: if is_correct() { "correct" }, - class: if is_wrong() { "wrong" }, - if is_correct() { "✓" } else { "X" } + + div { + class: if is_correct() { "correct" }, + class: if is_wrong() { "wrong" }, + if is_correct() { "✓" } else { "X" } + } } } }