diff --git a/.gitignore b/.gitignore index 6594348..4411927 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ # These are backup files generated by rustfmt **/*.rs.bk -questions.toml +questions*.toml diff --git a/Cargo.toml b/Cargo.toml index dc4bc97..696766e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "flashcards" version = "0.1.0" authors = ["Wynd "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/Dioxus.toml b/Dioxus.toml index 860b161..e7a7724 100644 --- a/Dioxus.toml +++ b/Dioxus.toml @@ -14,8 +14,12 @@ style = [] # Additional JavaScript files script = [] -[web.resource.dev] + [web.resource.dev] -# Javascript code file -# serve: [dev-server] only -script = [] + # Javascript code file + # serve: [dev-server] only + script = [] + +[bundle] +identifier = "xyz.pixelatedw.flashcards" +publisher = "PixelatedW" diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..c5794a6 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.85" diff --git a/src/main.rs b/src/main.rs index 6b5fef1..c983eed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{sync::LazyLock, time::Duration}; +use std::{env, sync::OnceLock, time::Duration}; use dioxus::{ desktop::{Config, LogicalSize, WindowBuilder}, @@ -9,16 +9,48 @@ use rand::seq::SliceRandom; mod models; +const DEFAULT_FILE: &str = "questions.toml"; const MAIN_CSS: Asset = asset!("/assets/main.css"); -pub static QUESTIONS: LazyLock = LazyLock::new(|| { - let questions_str = std::fs::read_to_string("questions.toml").unwrap(); - let questions: Questions = toml::from_str(&questions_str).unwrap(); - questions -}); +pub static QUESTIONS: OnceLock = OnceLock::new(); -fn get_questions() -> Vec { - let mut questions = QUESTIONS.questions.clone(); +fn get_questions() -> Questions { + QUESTIONS + .get_or_init(|| { + let args: Vec = env::args().collect(); + let file_name = args.get(1).map(|x| x.as_str()).unwrap_or(DEFAULT_FILE); + + let questions_str = std::fs::read_to_string(file_name) + .unwrap_or_else(|_| panic!("Could not read from file {file_name}")); + let mut questions: Questions = + toml::from_str(&questions_str).expect("Could not decode the given file as TOML"); + + if args.len() > 2 { + for i in 2..args.len() { + let file_name = args.get(i).map(|x| x.as_str()); + let Some(file_name) = file_name else { + continue; + }; + + let Ok(questions_str) = std::fs::read_to_string(file_name) else { + continue; + }; + + let Ok(other_questions) = toml::from_str(&questions_str) else { + continue; + }; + + questions += other_questions; + } + } + + questions + }) + .clone() +} + +fn get_rand_questions() -> Vec { + let mut questions = get_questions().questions; let mut rng = rand::rng(); // Randomize the answers @@ -55,7 +87,7 @@ fn App() -> Element { #[component] pub fn QuestionForm() -> Element { - let mut questions = use_signal(get_questions); + let mut questions = use_signal(get_rand_questions); let mut current = use_signal(move || questions.remove(0)); let total_correct = use_memo(move || { @@ -82,7 +114,7 @@ pub fn QuestionForm() -> Element { correctly_checked.saturating_sub(incorrectly_checked) }); - let total_questions = QUESTIONS.len(); + let total_questions = get_questions().len(); let current_question = use_memo(move || questions().len()); let left_questions = use_memo(move || total_questions - current_question()); let mut correct_questions = use_signal(|| 0); @@ -116,7 +148,7 @@ pub fn QuestionForm() -> Element { *wrong_questions_lock += 1; } } else { - questions.set(get_questions()); + questions.set(get_rand_questions()); current.set(questions.remove(0)); *correct_questions_lock = 0; diff --git a/src/models.rs b/src/models.rs index 86fda1f..127aec6 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,12 +1,18 @@ -use std::ops::{Deref, DerefMut}; +use std::ops::{AddAssign, Deref, DerefMut}; use serde::Deserialize; -#[derive(Debug, Deserialize)] +#[derive(Debug, Clone, Deserialize)] pub struct Questions { pub questions: Vec, } +impl AddAssign for Questions { + fn add_assign(&mut self, rhs: Self) { + self.extend(rhs.questions) + } +} + impl Deref for Questions { type Target = Vec;