diff --git a/Cargo.lock b/Cargo.lock index 707cc22..8323173 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,6 +24,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aes" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58" +dependencies = [ + "cipher", + "cpubits", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.12" @@ -386,6 +397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", + "zeroize", ] [[package]] @@ -457,6 +469,15 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "bzip2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" +dependencies = [ + "libbz2-rs-sys", +] + [[package]] name = "calloop" version = "0.13.0" @@ -595,6 +616,16 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "4.6.1" @@ -668,6 +699,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "codespan-reporting" version = "0.12.0" @@ -730,6 +767,12 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + [[package]] name = "core-foundation" version = "0.9.4" @@ -868,6 +911,12 @@ dependencies = [ "windows 0.62.2", ] +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" version = "0.3.0" @@ -980,6 +1029,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b29fccfdaeb0f9bd90da5759b1d0eaa2f6cfcfe90960124cfc83141ed4e111fd" +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + [[package]] name = "cursor-icon" version = "1.2.0" @@ -998,6 +1056,18 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" +[[package]] +name = "deflate64" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + [[package]] name = "digest" version = "0.11.2" @@ -1007,6 +1077,8 @@ dependencies = [ "block-buffer", "const-oid", "crypto-common", + "ctutils", + "zeroize", ] [[package]] @@ -1244,6 +1316,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", + "zlib-rs", ] [[package]] @@ -1717,6 +1790,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "hmac" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "1.4.0" @@ -2175,6 +2257,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inout" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" +dependencies = [ + "hybrid-array", +] + [[package]] name = "ipnet" version = "2.12.0" @@ -2225,6 +2316,7 @@ dependencies = [ "serde_json", "sha2", "tokio", + "zip", "zstd", ] @@ -2369,6 +2461,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +[[package]] +name = "libbz2-rs-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c" + [[package]] name = "libc" version = "0.2.189" @@ -2479,6 +2577,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lzma-rust2" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca93e534d1142d1d0dcca6d25fe302508a5dfb40b302802904577725ea0b695b" +dependencies = [ + "sha2", +] + [[package]] name = "mach2" version = "0.5.0" @@ -2664,6 +2771,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + [[package]] name = "num-derive" version = "0.4.2" @@ -3280,6 +3393,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pbkdf2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629" +dependencies = [ + "digest", + "hmac", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -3420,6 +3543,18 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppmd-rust" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24" + [[package]] name = "presser" version = "0.3.1" @@ -4162,6 +4297,17 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "sha1" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.11.0" @@ -4743,6 +4889,26 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "js-sys", + "num-conv", + "powerfmt", + "serde_core", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -4997,6 +5163,12 @@ dependencies = [ "core_maths", ] +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typenum" version = "1.20.0" @@ -6437,12 +6609,57 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "zip" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" +dependencies = [ + "aes", + "bzip2", + "constant_time_eq", + "crc32fast", + "deflate64", + "flate2", + "getrandom 0.4.1", + "hmac", + "indexmap", + "lzma-rust2", + "memchr", + "pbkdf2", + "ppmd-rust", + "sha1", + "time", + "typed-path", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zlib-rs" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12" + [[package]] name = "zmij" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7" +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index f688391..0d5a784 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ sha2 = "0.11.0" tokio = { version = "1.53.1", features = ["rt", "rt-multi-thread", "macros"] } hex = "0.4.3" zstd = "0.13.3" +zip = "8.6.0" [dev-dependencies] criterion = "0.8.2" diff --git a/src/dictionary.rs b/src/dictionary.rs index df92c94..88f4be2 100644 --- a/src/dictionary.rs +++ b/src/dictionary.rs @@ -102,30 +102,8 @@ impl NavigatedPage for DictionaryState { fn navigated(&mut self) { } -} -impl DictionaryState { - pub fn new(state: Arc>) -> Self { - let len = state.lock().unwrap().dictionary.len(); - - let mut result = DictionaryState { - include_map: vec![false; len], - selected_group_index: 0, - state, - tag_map: HashMap::new(), - reverse: false, - search: "".to_string(), - no_typing: true, - reverse_list: true, - auto_save_queue: HashMap::new(), - }; - - result.update_tags(); - - result - } - - pub fn update(&mut self, message: DictionaryMessage) -> Task { + fn update(&mut self, message: DictionaryMessage) -> Task { match message { NewWord => { let mut state = self.state.lock().unwrap(); @@ -271,6 +249,45 @@ impl DictionaryState { Task::none() } + + fn view(&self) -> iced::Element<'_, DictionaryMessage> { + back_overlay( + row![ + iced::widget::column![ + self.groups_panel(), + row![horizontal().width(8), self.words_list(),], + button("Добавить слово").style(jl_button).on_press(NewWord), + ] + .spacing(5), + self.filters(), + ] + .spacing(DEFAULT_SPACING) + .into(), + Back, + ) + } +} + +impl DictionaryState { + pub fn new(state: Arc>) -> Self { + let len = state.lock().unwrap().dictionary.len(); + + let mut result = DictionaryState { + include_map: vec![false; len], + selected_group_index: 0, + state, + tag_map: HashMap::new(), + reverse: false, + search: "".to_string(), + no_typing: true, + reverse_list: true, + auto_save_queue: HashMap::new(), + }; + + result.update_tags(); + + result + } fn save_word(&mut self, i: usize) { let state = &mut self.state.lock().unwrap(); @@ -291,22 +308,7 @@ impl DictionaryState { ) } - pub fn view(&self) -> iced::Element<'_, DictionaryMessage> { - back_overlay( - row![ - iced::widget::column![ - self.groups_panel(), - row![horizontal().width(8), self.words_list(),], - button("Добавить слово").style(jl_button).on_press(NewWord), - ] - .spacing(5), - self.filters(), - ] - .spacing(DEFAULT_SPACING) - .into(), - Back, - ) - } + fn words_list(&self) -> iced::Element<'_, DictionaryMessage> { let time = Instant::now(); diff --git a/src/dictionary_test.rs b/src/dictionary_test.rs index 2f37da6..9409bcf 100644 --- a/src/dictionary_test.rs +++ b/src/dictionary_test.rs @@ -44,25 +44,8 @@ impl NavigatedPage for DictionaryQuizState { fn navigated(&mut self) { } -} -impl DictionaryQuizState { - pub fn new(words: Vec, reverse: bool, no_typing: bool) -> DictionaryQuizState { - DictionaryQuizState { - words, - current_set: Vec::new(), - answer: "".to_string(), - view: "---".to_string(), - correct: "".to_string(), - score: Default::default(), - is_help: false, - reverse, - laps: 0, - no_typing, - } - } - - pub fn update(&mut self, message: DictionaryQuizMessage) -> Task { + fn update(&mut self, message: DictionaryQuizMessage) -> Task { match message { Back => {} AnswerChanged(c) => self.answer = c.clone(), @@ -72,7 +55,7 @@ impl DictionaryQuizState { Task::none() } - pub fn view(&self) -> Element<'_, DictionaryQuizMessage> { + fn view(&self) -> Element<'_, DictionaryQuizMessage> { container( iced::widget::column![ self.laps(), @@ -112,13 +95,32 @@ impl DictionaryQuizState { ] .spacing(DEFAULT_SPACING), ] - .spacing(DEFAULT_SPACING) - .align_x(alignment::Horizontal::Center), + .spacing(DEFAULT_SPACING) + .align_x(alignment::Horizontal::Center), ) - .center_y(Fill) - .center_x(Fill) - .into() + .center_y(Fill) + .center_x(Fill) + .into() } +} + +impl DictionaryQuizState { + pub fn new(words: Vec, reverse: bool, no_typing: bool) -> DictionaryQuizState { + DictionaryQuizState { + words, + current_set: Vec::new(), + answer: "".to_string(), + view: "---".to_string(), + correct: "".to_string(), + score: Default::default(), + is_help: false, + reverse, + laps: 0, + no_typing, + } + } + + fn submit(&mut self) { if self.view == "---" { self.show_next(); diff --git a/src/history.rs b/src/history.rs index 35279d4..8ee2126 100644 --- a/src/history.rs +++ b/src/history.rs @@ -25,6 +25,25 @@ impl NavigatedPage for HistoryState { } fn navigated(&mut self) { } + fn update(&mut self, _: HistoryMessage) -> Task { + Task::none() + } + + fn view(&self) -> Element<'_, HistoryMessage> { + back_overlay( + iced::widget::row![ + horizontal().width(FillPortion(1)), + scrollable(self.history_lines().padding(DEFAULT_SPACING)) + .height(Fill) + .width(FillPortion(5)), + horizontal().width(FillPortion(1)) + ] + .height(Fill) + .width(Fill) + .into(), + Back, + ) + } } impl HistoryState { @@ -49,25 +68,7 @@ impl HistoryState { } } - pub fn update(&mut self, _: HistoryMessage) -> Task { - Task::none() - } - pub fn view(&self) -> Element<'_, HistoryMessage> { - back_overlay( - iced::widget::row![ - horizontal().width(FillPortion(1)), - scrollable(self.history_lines().padding(DEFAULT_SPACING)) - .height(Fill) - .width(FillPortion(5)), - horizontal().width(FillPortion(1)) - ] - .height(Fill) - .width(Fill) - .into(), - Back, - ) - } fn history_lines(&self) -> Column<'_, HistoryMessage> { let mut column = Column::new(); diff --git a/src/import.rs b/src/import.rs new file mode 100644 index 0000000..b0043ca --- /dev/null +++ b/src/import.rs @@ -0,0 +1,28 @@ +use iced::{Element, Task}; +use crate::navigation::{NavigatedPage, Page, RootMessage}; + +struct ImportState {} +enum ImportMessage { + Back +} + +impl NavigatedPage for ImportState { + fn navigate(&self, message: &ImportMessage) -> Option { + if let ImportMessage::Back = message { + return Some(Page::PreviousPage) + } + None + } + + fn navigated(&mut self) { + } + + fn update(&mut self, message: ImportMessage) -> Task { + todo!() + } + + fn view(&self) -> Element<'_, ImportMessage> { + todo!() + } +} + diff --git a/src/main.rs b/src/main.rs index 9f9c81f..0bb5868 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ mod sync; mod word; mod writing; mod repetition_settings; +pub mod import; use crate::data_provider::card_sets::load_sets; use crate::data_provider::settings::get_setting; diff --git a/src/navigation.rs b/src/navigation.rs index ad14252..e9d2ff0 100644 --- a/src/navigation.rs +++ b/src/navigation.rs @@ -320,6 +320,8 @@ macro_rules! state_navigate_handle { pub trait NavigatedPage { fn navigate(&self, message: &T) -> Option; fn navigated(&mut self); + fn update(&mut self, message: T) -> Task; + fn view(&self) -> Element<'_, T>; } pub trait KeyPressedPage { diff --git a/src/quiz.rs b/src/quiz.rs index 2fedca5..904f244 100644 --- a/src/quiz.rs +++ b/src/quiz.rs @@ -30,34 +30,8 @@ impl NavigatedPage for QuizState { fn navigated(&mut self) { } -} -impl QuizState { - pub(crate) fn new() -> QuizState { - QuizState { - kana: "ぁ".to_string(), - correct_roman: "a".to_string(), - is_help: false, - current_roman: "".to_string(), - set: KanaSet::hiragana(), - queue: Vec::new(), - score: Score { - total: 0, - correct: 0, - fail: 0, - }, - } - } -} - -impl Default for QuizState { - fn default() -> Self { - QuizState::new() - } -} - -impl QuizState { - pub fn update(&mut self, message: QuizMessage) -> Task { + fn update(&mut self, message: QuizMessage) -> Task { match message { ContentChanged(content) => { if content.contains("`") { @@ -86,24 +60,9 @@ impl QuizState { Task::none() } - fn update_showed(&mut self) { - self.current_roman = String::new(); - let queue = &mut self.queue; - if queue.is_empty() { - for pair in self.set.list() { - queue.push(pair); - } - queue.shuffle(&mut rand::rng()); - } - - let pair = self.queue.pop().unwrap(); - self.kana = pair.0; - self.correct_roman = pair.1; - } - - pub fn view(&self) -> Element<'_, QuizMessage> { + fn view(&self) -> Element<'_, QuizMessage> { container( iced::widget::column![ row![ @@ -137,12 +96,55 @@ impl QuizState { .spacing(DEFAULT_SPACING), button("Закончить").style(jl_button).on_press(Back), ] - .spacing(DEFAULT_SPACING) - .align_x(alignment::Horizontal::Center), + .spacing(DEFAULT_SPACING) + .align_x(alignment::Horizontal::Center), ) - .center_y(Fill) - .center_x(Fill) - .into() + .center_y(Fill) + .center_x(Fill) + .into() + } +} + +impl QuizState { + pub(crate) fn new() -> QuizState { + QuizState { + kana: "ぁ".to_string(), + correct_roman: "a".to_string(), + is_help: false, + current_roman: "".to_string(), + set: KanaSet::hiragana(), + queue: Vec::new(), + score: Score { + total: 0, + correct: 0, + fail: 0, + }, + } + } +} + +impl Default for QuizState { + fn default() -> Self { + QuizState::new() + } +} + +impl QuizState { + fn update_showed(&mut self) { + self.current_roman = String::new(); + let queue = &mut self.queue; + + if queue.is_empty() { + for pair in self.set.list() { + queue.push(pair); + } + + queue.shuffle(&mut rand::rng()); + } + + let pair = self.queue.pop().unwrap(); + self.kana = pair.0; + self.correct_roman = pair.1; } } #[derive(Debug, Clone)] diff --git a/src/randomizer.rs b/src/randomizer.rs index 5c7d42c..a2df0d4 100644 --- a/src/randomizer.rs +++ b/src/randomizer.rs @@ -29,23 +29,7 @@ impl NavigatedPage for RandomizerState { fn navigated(&mut self) { } -} - -impl Default for RandomizerState { - fn default() -> Self { - Self::new() - } -} - -impl RandomizerState { - pub fn new() -> RandomizerState { - RandomizerState { - text: Default::default(), - list: vec![], - } - } - - pub fn update(&mut self, message: RandomizerMessage) -> Task { + fn update(&mut self, message: RandomizerMessage) -> Task { match message { Edit(action) => { self.text.perform(action); @@ -65,7 +49,7 @@ impl RandomizerState { Task::none() } - pub fn view(&self) -> iced::Element<'_, RandomizerMessage> { + fn view(&self) -> iced::Element<'_, RandomizerMessage> { back_overlay( iced::widget::column![ text_editor(&self.text) @@ -75,9 +59,25 @@ impl RandomizerState { .placeholder("Каждый элемент с новой строки"), button("Перемешать").style(jl_button).on_press(Start), ] - .spacing(HALF_SPACING) - .into(), + .spacing(HALF_SPACING) + .into(), Back, ) + }} + +impl Default for RandomizerState { + fn default() -> Self { + Self::new() } } + +impl RandomizerState { + pub fn new() -> RandomizerState { + RandomizerState { + text: Default::default(), + list: vec![], + } + } + + +} diff --git a/src/repetition.rs b/src/repetition.rs index 52c9b97..022db20 100644 --- a/src/repetition.rs +++ b/src/repetition.rs @@ -39,30 +39,7 @@ impl NavigatedPage for RepetitionState { fn navigated(&mut self) { } -} - -impl RepetitionState { - pub(crate) fn new(set: CardSetSettings, state: Arc>) -> RepetitionState { - let mut card_set = CardSet::new(&set, state.clone()); - let (word, stat) = card_set.next(); - let sink_handle = rodio::DeviceSinkBuilder::open_default_sink().unwrap(); - - RepetitionState { - state, - settings: set, - set: card_set, - current_word: word, - current_statistic: stat, - open: false, - can_play: true, - sink: Arc::new(sink_handle), - opened: HashSet::new(), - } - } -} - -impl RepetitionState { - pub fn update(&mut self, message: RepetitionMessage) -> Task { + fn update(&mut self, message: RepetitionMessage) -> Task { match message { RepetitionMessage::Back => {} RepetitionMessage::Next => return self.next(), @@ -87,6 +64,60 @@ impl RepetitionState { Task::none() } + fn view(&self) -> Element<'_, RepetitionMessage> { + back_overlay( + column![ + container(self.draw_forward()) + .width(Fill) + .height(Fill) + .align_x(Center) + .align_y(alignment::Vertical::Center), + rule::horizontal(2), + container(self.draw_backward()) + .width(Fill) + .height(Fill) + .align_x(Center) + .align_y(alignment::Vertical::Center), + container(self.answer_bar()) + .width(Fill) + .align_x(Center) + .height(80), + text!( + "Затронуто слов {}, {}%", + self.opened.len(), + (self.opened.len() as f32 / self.set.len() as f32 * 10000.0).round() / 100.0 + ) + ] + .height(Fill) + .width(Fill) + .into(), + RepetitionMessage::Back, + ) + } +} + +impl RepetitionState { + pub(crate) fn new(set: CardSetSettings, state: Arc>) -> RepetitionState { + let mut card_set = CardSet::new(&set, state.clone()); + let (word, stat) = card_set.next(); + let sink_handle = rodio::DeviceSinkBuilder::open_default_sink().unwrap(); + + RepetitionState { + state, + settings: set, + set: card_set, + current_word: word, + current_statistic: stat, + open: false, + can_play: true, + sink: Arc::new(sink_handle), + opened: HashSet::new(), + } + } +} + +impl RepetitionState { + fn next(&mut self) -> Task { if self.open { @@ -137,36 +168,7 @@ impl RepetitionState { state.activity.insert(id, vec![(now, 1)]); } } - pub fn view(&self) -> Element<'_, RepetitionMessage> { - back_overlay( - column![ - container(self.draw_forward()) - .width(Fill) - .height(Fill) - .align_x(Center) - .align_y(alignment::Vertical::Center), - rule::horizontal(2), - container(self.draw_backward()) - .width(Fill) - .height(Fill) - .align_x(Center) - .align_y(alignment::Vertical::Center), - container(self.answer_bar()) - .width(Fill) - .align_x(Center) - .height(80), - text!( - "Затронуто слов {}, {}%", - self.opened.len(), - (self.opened.len() as f32 / self.set.len() as f32 * 10000.0).round() / 100.0 - ) - ] - .height(Fill) - .width(Fill) - .into(), - RepetitionMessage::Back, - ) - } + fn draw_forward(&self) -> Element<'_, RepetitionMessage> { self.draw_card_view(self.settings.forward.as_str()) diff --git a/src/repetition_settings.rs b/src/repetition_settings.rs index 571c929..bf53d98 100644 --- a/src/repetition_settings.rs +++ b/src/repetition_settings.rs @@ -47,10 +47,7 @@ impl NavigatedPage for RepetitionSettingsState { fn navigated(&mut self) { } -} - -impl RepetitionSettingsState { - pub fn update(&mut self, message: RepetitionSettingsMessage) -> Task { + fn update(&mut self, message: RepetitionSettingsMessage) -> Task { match message { Back => {} Save => { @@ -93,7 +90,7 @@ impl RepetitionSettingsState { Task::none() } - pub fn view(&self) -> Element<'_, RepetitionSettingsMessage> { + fn view(&self) -> Element<'_, RepetitionSettingsMessage> { back_overlay( iced::widget::column![ scrollable( @@ -145,11 +142,15 @@ impl RepetitionSettingsState { ] .spacing(DEFAULT_SPACING), ] - .spacing(DEFAULT_SPACING) - .into(), + .spacing(DEFAULT_SPACING) + .into(), Back, ) } +} + +impl RepetitionSettingsState { + fn count_view(&self, set: &CardSetSettings) -> Element<'_, RepetitionSettingsMessage> { if let Some(count) = set.count { diff --git a/src/repetitions.rs b/src/repetitions.rs index beafc11..c354d42 100644 --- a/src/repetitions.rs +++ b/src/repetitions.rs @@ -59,21 +59,7 @@ impl NavigatedPage for RepetitionsState { fn navigated(&mut self) { self.selected_set = None; } -} - -impl RepetitionsState { - pub(crate) fn new(state: Arc>) -> RepetitionsState { - let count = state.lock().unwrap().card_sets.len(); - RepetitionsState { - selected_set: None, - correct_filters: vec![true; count], - state, - } - } -} - -impl RepetitionsState { - pub fn update(&mut self, message: RepetitionsMessage) -> Task { + fn update(&mut self, message: RepetitionsMessage) -> Task { let mut state = self.state.lock().unwrap(); match message { Next => {} @@ -139,7 +125,7 @@ impl RepetitionsState { Task::none() } - pub fn view(&self) -> Element<'_, RepetitionsMessage> { + fn view(&self) -> Element<'_, RepetitionsMessage> { back_overlay( row![ column![ @@ -153,15 +139,30 @@ impl RepetitionsState { .width(Length::FillPortion(1)), self.selected_set_view(), ] - .align_y(Center) - .spacing(DEFAULT_SPACING) - .width(Fill) - .height(Fill) - .into(), + .align_y(Center) + .spacing(DEFAULT_SPACING) + .width(Fill) + .height(Fill) + .into(), Back, ) } +} + +impl RepetitionsState { + pub(crate) fn new(state: Arc>) -> RepetitionsState { + let count = state.lock().unwrap().card_sets.len(); + RepetitionsState { + selected_set: None, + correct_filters: vec![true; count], + state, + } + } +} + +impl RepetitionsState { + fn launch_delete_button(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> { if set.id != 0 { return row![ diff --git a/src/selector.rs b/src/selector.rs index 99c86f4..115e9d7 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -64,17 +64,7 @@ impl NavigatedPage for SelectorState { fn navigated(&mut self) { } -} - -impl SelectorState { - pub fn new(state: Arc>) -> Self { - Self { - set: Default::default(), - is_writing: false, - state, - } - } - pub fn update(&mut self, message: SelectorMessage) -> Task { + fn update(&mut self, message: SelectorMessage) -> Task { match message { SelectorMessage::Change => match self.set.chars_type { KanaType::Katakana => self.set = KanaSet::hiragana(), @@ -86,19 +76,7 @@ impl SelectorState { } Task::none() } - - fn nav_style(theme: &Theme, status: Status) -> Style { - let mut basic = button::text(theme, status); - basic.background = if status == Status::Hovered { - Some(Background::Color(Color::WHITE.scale_alpha(0.1))) - } else { - None - }; - basic.border.radius = BUTTON_RADIUS.into(); - basic - } - - pub fn view(&self) -> Element<'_, SelectorMessage> { + fn view(&self) -> Element<'_, SelectorMessage> { container( iced::widget::column![ row![ @@ -127,11 +105,35 @@ impl SelectorState { .on_press(SelectorMessage::Goto) .style(cta_button), ] - .spacing(DEFAULT_SPACING), + .spacing(DEFAULT_SPACING), ) - .padding(10) - .into() + .padding(10) + .into() } +} + +impl SelectorState { + pub fn new(state: Arc>) -> Self { + Self { + set: Default::default(), + is_writing: false, + state, + } + } + + + fn nav_style(theme: &Theme, status: Status) -> Style { + let mut basic = button::text(theme, status); + basic.background = if status == Status::Hovered { + Some(Background::Color(Color::WHITE.scale_alpha(0.1))) + } else { + None + }; + basic.border.radius = BUTTON_RADIUS.into(); + basic + } + + fn rows_selector(&self) -> Element<'_, SelectorMessage> { let mut row = Row::new(); diff --git a/src/sync.rs b/src/sync.rs index ee92c97..c6509db 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -49,23 +49,7 @@ impl NavigatedPage for SyncState { } fn navigated(&mut self) {} -} - -impl SyncState { - pub fn new(state: Arc>) -> SyncState { - let auto_fetch; - { - auto_fetch = state.lock().unwrap().sync_data.auto_web_fetch; - } - Self { - auto_fetch, - state, - frozen: false, - progress: 0.0, - } - } - - pub fn update(&mut self, message: SyncMessage) -> Task { + fn update(&mut self, message: SyncMessage) -> Task { match message { Back => {} CopyKey => { @@ -158,7 +142,7 @@ impl SyncState { Task::none() } - pub fn view(&self) -> Element<'_, SyncMessage> { + fn view(&self) -> Element<'_, SyncMessage> { back_overlay( row![space().width(Fill), self.sync_column(), space().width(Fill)] .spacing(DEFAULT_SPACING) @@ -167,6 +151,23 @@ impl SyncState { Back, ) } +} + +impl SyncState { + pub fn new(state: Arc>) -> SyncState { + let auto_fetch; + { + auto_fetch = state.lock().unwrap().sync_data.auto_web_fetch; + } + Self { + auto_fetch, + state, + frozen: false, + progress: 0.0, + } + } + + fn sync_column(&self) -> Element<'_, SyncMessage> { let network_view: Element<'_, SyncMessage> = if self.frozen { diff --git a/src/word.rs b/src/word.rs index d3dd5ab..1dd9c9e 100644 --- a/src/word.rs +++ b/src/word.rs @@ -28,16 +28,7 @@ impl NavigatedPage for WordState { fn navigated(&mut self) { } -} - -impl WordState { - pub(crate) fn new(word: WordData, index: usize, state: Arc>) -> WordState { - WordState { state, index, word } - } -} - -impl WordState { - pub fn update(&mut self, message: WordMessage) -> Task { + fn update(&mut self, message: WordMessage) -> Task { match message { Back => {} Save => { @@ -74,7 +65,7 @@ impl WordState { Task::none() } - pub fn view(&self) -> Element<'_, WordMessage> { + fn view(&self) -> Element<'_, WordMessage> { let mut fast_add = row![]; if !self.word.additional.contains_key("reading") { fast_add = fast_add.push( @@ -132,12 +123,22 @@ impl WordState { ] .spacing(DEFAULT_SPACING) ] - .spacing(DEFAULT_SPACING) - .into(), + .spacing(DEFAULT_SPACING) + .into(), Back, ) } +} + +impl WordState { + pub(crate) fn new(word: WordData, index: usize, state: Arc>) -> WordState { + WordState { state, index, word } + } +} + +impl WordState { + fn get_view_for_more(&self, value: (&String, &String)) -> Element<'_, WordMessage> { match value.0.as_str() { "reading" => self.reading_field(value), diff --git a/src/writing.rs b/src/writing.rs index b88d58a..050a887 100644 --- a/src/writing.rs +++ b/src/writing.rs @@ -29,6 +29,41 @@ impl NavigatedPage for WritingState { fn navigated(&mut self) { } + fn update(&mut self, message: WritingMessage) -> Task { + match message { + WritingMessage::Back => todo!(), + WritingMessage::Next => self.next(), + WritingMessage::SwitchShowMode(b) => self.show_all = b, + } + Task::none() + } + fn view(&self) -> Element<'_, WritingMessage> { + container( + iced::widget::column![ + checkbox(self.show_all) + .label("Показывать все сразу") + .on_toggle(WritingMessage::SwitchShowMode), + text!("{}", self.roman_total).size(34), + text!("{}", self.kana).size(48), + self.answers(), + row![ + button(text!("{}", self.next_text)) + .style(jl_button) + .on_press(WritingMessage::Next), + button("Закончить") + .style(jl_button) + .on_press(WritingMessage::Back), + ] + .spacing(DEFAULT_SPACING) + ] + .spacing(DEFAULT_SPACING) + .align_x(alignment::Horizontal::Center), + ) + .center_x(Fill) + .center_y(Fill) + .padding(10) + .into() + } } impl WritingState { @@ -48,14 +83,7 @@ impl WritingState { } impl WritingState { - pub fn update(&mut self, message: WritingMessage) -> Task { - match message { - WritingMessage::Back => todo!(), - WritingMessage::Next => self.next(), - WritingMessage::SwitchShowMode(b) => self.show_all = b, - } - Task::none() - } + fn next(&mut self) { if self.set.is_empty() { @@ -85,33 +113,7 @@ impl WritingState { } } - pub fn view(&self) -> Element<'_, WritingMessage> { - container( - iced::widget::column![ - checkbox(self.show_all) - .label("Показывать все сразу") - .on_toggle(WritingMessage::SwitchShowMode), - text!("{}", self.roman_total).size(34), - text!("{}", self.kana).size(48), - self.answers(), - row![ - button(text!("{}", self.next_text)) - .style(jl_button) - .on_press(WritingMessage::Next), - button("Закончить") - .style(jl_button) - .on_press(WritingMessage::Back), - ] - .spacing(DEFAULT_SPACING) - ] - .spacing(DEFAULT_SPACING) - .align_x(alignment::Horizontal::Center), - ) - .center_x(Fill) - .center_y(Fill) - .padding(10) - .into() - } + fn answers(&self) -> Element<'_, WritingMessage> { if self.set.is_empty() {