From 07024e1421e809962e1817d11e70f33bcdaa400e Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Fri, 17 Apr 2026 12:38:05 +0300 Subject: [PATCH] Words extension --- src/dictionary.rs | 37 +++++++++++++---- src/main.rs | 31 ++++++++++---- src/repetitions.rs | 10 +---- src/word.rs | 100 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 24 deletions(-) create mode 100644 src/word.rs diff --git a/src/dictionary.rs b/src/dictionary.rs index db9495e..d2e29bb 100644 --- a/src/dictionary.rs +++ b/src/dictionary.rs @@ -2,6 +2,8 @@ use crate::data_provider::words::{delete_word, update_word}; use crate::dictionary::DictionaryMessage::Test; use crate::dictionary_test::DictionaryQuizState; use crate::lang::DictionaryElement; +use crate::word::WordState; +use crate::Page::Word; use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; use iced::alignment::Vertical::Center; use iced::widget::button::Style; @@ -30,7 +32,7 @@ pub enum DictionaryMessage { SetKey(usize, String), SetValue(usize, String), SubmitWord(usize), - Remove(usize), + WordAction(usize), NewWord, Include(usize, bool), IncludeTag(String, bool), @@ -63,6 +65,17 @@ impl NavigatedPage for DictionaryState { ))); } } + if let DictionaryMessage::WordAction(index) = message { + let word : DictionaryElement; + { + let state = self.state.lock().unwrap(); + let dict = &state.dictionary; + word = dict[*index].clone(); + } + if word.id != 0 { + return Some(Word(WordState::new(word, *index, self.state.clone()))); + } + } None } } @@ -109,7 +122,7 @@ impl DictionaryState { self.update_tags(); } - DictionaryMessage::Remove(i) => { + DictionaryMessage::WordAction(i) => { let state = &mut self.state.lock().unwrap(); let dict = &mut state.dictionary; let word = dict.remove(i); @@ -207,19 +220,25 @@ impl DictionaryState { .on_submit(DictionaryMessage::SubmitWord(i)), ); - line = line - .push( - button("-") - .on_press_with(move || DictionaryMessage::Remove(i)) + let line_button = || { + if word.id == 0 { + return button("-") + .on_press_with(move || DictionaryMessage::WordAction(i)) .style(|_x, _status| Style { background: None, text_color: Color::BLACK, border: Border::default(), shadow: Shadow::default(), snap: false, - }), - ) - .push(space().width(10)); + }); + } + + button("") + .on_press_with(move || DictionaryMessage::WordAction(i)) + .width(15) + }; + + line = line.push(line_button()).push(space().width(10)); col = col.push(line); i += 1; diff --git a/src/main.rs b/src/main.rs index f7cb432..1114532 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,8 @@ mod repetitions; mod selector; mod writing; mod data_provider; +mod word; + use crate::data_provider::card_sets::load_sets; use crate::data_provider::words::{create_db, load_words}; use crate::dictionary::{app_data_dir, DictionaryMessage, DictionaryState}; @@ -19,17 +21,18 @@ use crate::randomizer::randomizer::{RandomizerMessage, RandomizerState}; use crate::repetition::{RepetitionMessage, RepetitionState}; use crate::repetitions::{CardSetSettings, RepetitionsMessage, RepetitionsState}; use crate::selector::*; +use crate::word::{WordMessage, WordState}; use crate::writing::{WritingMessage, WritingState}; use crate::Page::{ - Dictionary, DictionaryQuiz, Quiz, Randomizer, Repetition, Repetitions, Selector, Writing, + Dictionary, DictionaryQuiz, Quiz, Randomizer, Repetition, Repetitions, Selector, Word, Writing }; +use crate::RootMessage::Keyboard; +use iced::keyboard::Event; use iced::widget::text; use iced::{keyboard, Element, Subscription}; use iced::{Font, Task}; use rusqlite::Connection; use std::sync::{Arc, Mutex}; -use iced::keyboard::Event; -use crate::RootMessage::Keyboard; const DEFAULT_SPACING: f32 = 10.0; @@ -56,7 +59,8 @@ pub enum RootMessage { Randomizer(RandomizerMessage), Repetitions(RepetitionsMessage), Repetition(RepetitionMessage), - Keyboard(keyboard::Event), + Word(WordMessage), + Keyboard(Event), } enum Page { @@ -68,6 +72,7 @@ enum Page { Randomizer(RandomizerState), Repetitions(RepetitionsState), Repetition(RepetitionState), + Word(WordState), PreviousPage, } @@ -117,7 +122,8 @@ impl ScreenState { DictionaryQuiz, Randomizer, Repetitions, - Repetition + Repetition, + Word ); Task::none() } @@ -131,7 +137,8 @@ impl ScreenState { DictionaryQuiz, Randomizer, Repetitions, - Repetition + Repetition, + Word ) } @@ -196,4 +203,14 @@ trait NavigatedPage { pub trait KeyPressedPage { fn press(&mut self, message: &keyboard::Event); -} \ No newline at end of file +} + +/*pub fn danger_button(x: &Theme, status: Status) -> Style{ + Style { + background: Some(Color(x.palette().danger)), + text_color: x.palette().text, + border: Border::default().rounded(2), + shadow: Default::default(), + snap: false, + } +}*/ \ No newline at end of file diff --git a/src/repetitions.rs b/src/repetitions.rs index 99449d1..5ad0516 100644 --- a/src/repetitions.rs +++ b/src/repetitions.rs @@ -3,9 +3,9 @@ use crate::lang::DictionaryElement; use crate::repetition::RepetitionState; use crate::Page::{PreviousPage, Repetition}; use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use iced::widget::button::danger; pub use iced::widget::button::{Catalog, Style}; use iced::widget::{button, column, container, row, scrollable, space, text, text_input, Column}; -use iced::Background::Color; use iced::{Border, Center, Element, Fill, Left, Length, Shadow, Task, Theme}; use rhai::{Engine, Scope}; use std::sync::{Arc, Mutex}; @@ -165,13 +165,7 @@ impl RepetitionsState { row![ button("Сохранить").on_press(RepetitionsMessage::Save), button("Удалить") - .style(|x: &Theme, _status| Style { - background: Some(Color(x.palette().danger)), - text_color: x.palette().text, - border: Border::default().rounded(2), - shadow: Default::default(), - snap: false, - }) + .style(danger) .on_press(RepetitionsMessage::DeleteSet) ] .spacing(DEFAULT_SPACING), diff --git a/src/word.rs b/src/word.rs new file mode 100644 index 0000000..542813a --- /dev/null +++ b/src/word.rs @@ -0,0 +1,100 @@ +use crate::lang::DictionaryElement; +use crate::Page::PreviousPage; +use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; +use iced::widget::button::danger; +use iced::widget::{button, column, container, row, text, text_input}; +use iced::{Element, Fill, Task}; +use std::sync::{Arc, Mutex}; +use crate::data_provider::words::{delete_word, update_word}; + +#[derive(Clone)] +pub struct WordState { + state: Arc>, + index: usize, + word: DictionaryElement, +} + +impl NavigatedPage for WordState { + fn navigate(&self, message: &WordMessage) -> Option { + if let WordMessage::Back = message { + Some(PreviousPage) + } else { + None + } + } +} + +impl WordState { + pub(crate) fn new( + word: DictionaryElement, + index: usize, + state: Arc>, + ) -> WordState { + WordState { state, index, word } + } +} + +impl WordState { + pub fn update(&mut self, message: WordMessage) -> Task { + match message { + WordMessage::Back => {}, + WordMessage::Save => { + let mut state = self.state.lock().unwrap(); + state.dictionary[self.index] = self.word.clone(); + update_word(&mut self.word, &state.connection) + } + WordMessage::Delete => { + let mut state = self.state.lock().unwrap(); + state.dictionary.remove(self.index); + delete_word(&self.word, &state.connection); + return Task::done(RootMessage::Word(WordMessage::Back)) + } + WordMessage::SetTags(n) => self.word.tags = n, + WordMessage::SetKey(n) => { + self.word.key = n; + } + WordMessage::SetValue(n) => { + self.word.value = n; + } + } + Task::none() + } + + pub fn view(&self) -> Element<'_, WordMessage> { + container( + column![ + iced::widget::column![ + button("Назад").on_press(WordMessage::Back), + text!("Ключ"), + text_input("key", &self.word.key).on_input(WordMessage::SetKey), + text!("Значение"), + text_input("value", &self.word.value).on_input(WordMessage::SetValue), + text!("Теги"), + text_input("tags", &self.word.tags).on_input(WordMessage::SetTags), + ] + .spacing(DEFAULT_SPACING) + .width(Fill) + .height(Fill), + row![ + button("Сохранить").on_press(WordMessage::Save), + button("Удалить") + .style(danger) + .on_press(WordMessage::Delete), + ] + .spacing(DEFAULT_SPACING) + ] + .spacing(DEFAULT_SPACING), + ) + .padding(DEFAULT_SPACING) + .into() + } +} +#[derive(Debug, Clone)] +pub enum WordMessage { + Save, + Back, + Delete, + SetTags(String), + SetKey(String), + SetValue(String), +}