Words extension

This commit is contained in:
2026-04-17 12:38:05 +03:00
parent 1c4bdf372d
commit 07024e1421
4 changed files with 154 additions and 24 deletions
+28 -9
View File
@@ -2,6 +2,8 @@ use crate::data_provider::words::{delete_word, update_word};
use crate::dictionary::DictionaryMessage::Test; use crate::dictionary::DictionaryMessage::Test;
use crate::dictionary_test::DictionaryQuizState; use crate::dictionary_test::DictionaryQuizState;
use crate::lang::DictionaryElement; use crate::lang::DictionaryElement;
use crate::word::WordState;
use crate::Page::Word;
use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING};
use iced::alignment::Vertical::Center; use iced::alignment::Vertical::Center;
use iced::widget::button::Style; use iced::widget::button::Style;
@@ -30,7 +32,7 @@ pub enum DictionaryMessage {
SetKey(usize, String), SetKey(usize, String),
SetValue(usize, String), SetValue(usize, String),
SubmitWord(usize), SubmitWord(usize),
Remove(usize), WordAction(usize),
NewWord, NewWord,
Include(usize, bool), Include(usize, bool),
IncludeTag(String, bool), IncludeTag(String, bool),
@@ -63,6 +65,17 @@ impl NavigatedPage<DictionaryMessage> 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 None
} }
} }
@@ -109,7 +122,7 @@ impl DictionaryState {
self.update_tags(); self.update_tags();
} }
DictionaryMessage::Remove(i) => { DictionaryMessage::WordAction(i) => {
let state = &mut self.state.lock().unwrap(); let state = &mut self.state.lock().unwrap();
let dict = &mut state.dictionary; let dict = &mut state.dictionary;
let word = dict.remove(i); let word = dict.remove(i);
@@ -207,19 +220,25 @@ impl DictionaryState {
.on_submit(DictionaryMessage::SubmitWord(i)), .on_submit(DictionaryMessage::SubmitWord(i)),
); );
line = line let line_button = || {
.push( if word.id == 0 {
button("-") return button("-")
.on_press_with(move || DictionaryMessage::Remove(i)) .on_press_with(move || DictionaryMessage::WordAction(i))
.style(|_x, _status| Style { .style(|_x, _status| Style {
background: None, background: None,
text_color: Color::BLACK, text_color: Color::BLACK,
border: Border::default(), border: Border::default(),
shadow: Shadow::default(), shadow: Shadow::default(),
snap: false, 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); col = col.push(line);
i += 1; i += 1;
+24 -7
View File
@@ -9,6 +9,8 @@ mod repetitions;
mod selector; mod selector;
mod writing; mod writing;
mod data_provider; mod data_provider;
mod word;
use crate::data_provider::card_sets::load_sets; use crate::data_provider::card_sets::load_sets;
use crate::data_provider::words::{create_db, load_words}; use crate::data_provider::words::{create_db, load_words};
use crate::dictionary::{app_data_dir, DictionaryMessage, DictionaryState}; 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::repetition::{RepetitionMessage, RepetitionState};
use crate::repetitions::{CardSetSettings, RepetitionsMessage, RepetitionsState}; use crate::repetitions::{CardSetSettings, RepetitionsMessage, RepetitionsState};
use crate::selector::*; use crate::selector::*;
use crate::word::{WordMessage, WordState};
use crate::writing::{WritingMessage, WritingState}; use crate::writing::{WritingMessage, WritingState};
use crate::Page::{ 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::widget::text;
use iced::{keyboard, Element, Subscription}; use iced::{keyboard, Element, Subscription};
use iced::{Font, Task}; use iced::{Font, Task};
use rusqlite::Connection; use rusqlite::Connection;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use iced::keyboard::Event;
use crate::RootMessage::Keyboard;
const DEFAULT_SPACING: f32 = 10.0; const DEFAULT_SPACING: f32 = 10.0;
@@ -56,7 +59,8 @@ pub enum RootMessage {
Randomizer(RandomizerMessage), Randomizer(RandomizerMessage),
Repetitions(RepetitionsMessage), Repetitions(RepetitionsMessage),
Repetition(RepetitionMessage), Repetition(RepetitionMessage),
Keyboard(keyboard::Event), Word(WordMessage),
Keyboard(Event),
} }
enum Page { enum Page {
@@ -68,6 +72,7 @@ enum Page {
Randomizer(RandomizerState), Randomizer(RandomizerState),
Repetitions(RepetitionsState), Repetitions(RepetitionsState),
Repetition(RepetitionState), Repetition(RepetitionState),
Word(WordState),
PreviousPage, PreviousPage,
} }
@@ -117,7 +122,8 @@ impl ScreenState {
DictionaryQuiz, DictionaryQuiz,
Randomizer, Randomizer,
Repetitions, Repetitions,
Repetition Repetition,
Word
); );
Task::none() Task::none()
} }
@@ -131,7 +137,8 @@ impl ScreenState {
DictionaryQuiz, DictionaryQuiz,
Randomizer, Randomizer,
Repetitions, Repetitions,
Repetition Repetition,
Word
) )
} }
@@ -196,4 +203,14 @@ trait NavigatedPage<T> {
pub trait KeyPressedPage { pub trait KeyPressedPage {
fn press(&mut self, message: &keyboard::Event); fn press(&mut self, message: &keyboard::Event);
} }
/*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,
}
}*/
+2 -8
View File
@@ -3,9 +3,9 @@ use crate::lang::DictionaryElement;
use crate::repetition::RepetitionState; use crate::repetition::RepetitionState;
use crate::Page::{PreviousPage, Repetition}; use crate::Page::{PreviousPage, Repetition};
use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING}; use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING};
use iced::widget::button::danger;
pub use iced::widget::button::{Catalog, Style}; pub use iced::widget::button::{Catalog, Style};
use iced::widget::{button, column, container, row, scrollable, space, text, text_input, Column}; 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 iced::{Border, Center, Element, Fill, Left, Length, Shadow, Task, Theme};
use rhai::{Engine, Scope}; use rhai::{Engine, Scope};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@@ -165,13 +165,7 @@ impl RepetitionsState {
row![ row![
button("Сохранить").on_press(RepetitionsMessage::Save), button("Сохранить").on_press(RepetitionsMessage::Save),
button("Удалить") button("Удалить")
.style(|x: &Theme, _status| Style { .style(danger)
background: Some(Color(x.palette().danger)),
text_color: x.palette().text,
border: Border::default().rounded(2),
shadow: Default::default(),
snap: false,
})
.on_press(RepetitionsMessage::DeleteSet) .on_press(RepetitionsMessage::DeleteSet)
] ]
.spacing(DEFAULT_SPACING), .spacing(DEFAULT_SPACING),
+100
View File
@@ -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<Mutex<AppState>>,
index: usize,
word: DictionaryElement,
}
impl NavigatedPage<WordMessage> for WordState {
fn navigate(&self, message: &WordMessage) -> Option<Page> {
if let WordMessage::Back = message {
Some(PreviousPage)
} else {
None
}
}
}
impl WordState {
pub(crate) fn new(
word: DictionaryElement,
index: usize,
state: Arc<Mutex<AppState>>,
) -> WordState {
WordState { state, index, word }
}
}
impl WordState {
pub fn update(&mut self, message: WordMessage) -> Task<RootMessage> {
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),
}