Auto save works

This commit is contained in:
2026-05-10 22:15:03 +03:00
parent 6c53bc115a
commit ee817a8e8c
3 changed files with 79 additions and 21 deletions
+59 -13
View File
@@ -7,6 +7,7 @@ use crate::lang::{WordData, WordGroup};
use crate::word::WordState;
use crate::Page::Word;
use crate::{AppState, NavigatedPage, Page, RootMessage, DEFAULT_SPACING};
use chrono::{DateTime, TimeDelta, Utc};
use iced::alignment::Vertical::Center;
use iced::widget::button::Style;
use iced::widget::button::{danger, text};
@@ -16,8 +17,10 @@ use iced::{Border, Color, Length, Shadow, Task};
use rand::random_range;
use std::collections::HashMap;
use std::fs;
use std::ops::Add;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use DictionaryMessage::Back;
#[derive(Clone)]
@@ -30,6 +33,7 @@ pub struct DictionaryState {
no_typing: bool,
selected_group_index: usize,
reverse_list: bool,
auto_save_queue: HashMap<usize, DateTime<Utc>>,
}
#[derive(Debug, Clone)]
@@ -54,6 +58,7 @@ pub enum DictionaryMessage {
SelectGroup(usize),
DeleteGroup,
ChangeDirection,
TrySave(usize),
}
impl NavigatedPage<DictionaryMessage> for DictionaryState {
@@ -104,8 +109,9 @@ impl DictionaryState {
tag_map: HashMap::new(),
reverse: false,
search: "".to_string(),
no_typing: false,
no_typing: true,
reverse_list: true,
auto_save_queue: HashMap::new(),
};
result.update_tags();
@@ -126,13 +132,20 @@ impl DictionaryState {
}
DictionaryMessage::SetKey(i, v) => {
{
let dict = &mut self.state.lock().unwrap().dictionary;
dict[i].key = v
dict[i].key = v;
}
return self.launch_auto_save_offset(i)
}
DictionaryMessage::SetValue(i, v) => {
{
let dict = &mut self.state.lock().unwrap().dictionary;
dict[i].value = v
}
return self.launch_auto_save_offset(i)
}
DictionaryMessage::SetTags(i, v) => {
{
let dict = &mut self.state.lock().unwrap().dictionary;
@@ -140,6 +153,7 @@ impl DictionaryState {
}
self.update_tags();
return self.launch_auto_save_offset(i)
}
DictionaryMessage::WordAction(i) => {
@@ -147,12 +161,18 @@ impl DictionaryState {
let dict = &mut state.dictionary;
let word = dict.remove(i);
self.include_map.remove(i);
self.auto_save_queue.remove(&i);
delete_word(&word, &state.connection)
}
DictionaryMessage::Include(i, b) => self.include_map[i] = b,
DictionaryMessage::IncludeTag(t, v) => {
let index : u32;
{
let mut state = self.state.lock().unwrap();
index = state.word_groups[self.selected_group_index].id;
}
self.tag_map.insert(t, v);
self.update_words_include()
self.update_words_include(index)
}
DictionaryMessage::ResetTags => {
@@ -165,12 +185,7 @@ impl DictionaryState {
}
DictionaryMessage::SetTyping(b) => self.no_typing = b,
DictionaryMessage::SubmitWord(i) => {
let state = &mut self.state.lock().unwrap();
let connection = &state.connection;
let word = &mut state.dictionary.get(i).unwrap().clone();
update_word(word, &connection);
state.dictionary[i] = word.clone();
self.save_word(i)
}
Back => {}
Test => {}
@@ -203,6 +218,13 @@ impl DictionaryState {
}
DictionaryMessage::SelectGroup(i) => {
self.selected_group_index = i;
let index : u32;
{
let state = self.state.lock().unwrap();
index = state.word_groups[i].id;
}
self.update_words_include(index)
}
DeleteGroup => {
if self.selected_group_index == 0 {
@@ -220,12 +242,36 @@ impl DictionaryState {
}
ChangeDirection => {
self.reverse_list = !self.reverse_list;
},
DictionaryMessage::TrySave(word_index) => {
let now = Utc::now();
if !self.auto_save_queue.contains_key(&word_index) { return Task::none(); }
if self.auto_save_queue[&word_index] <= now {
self.auto_save_queue.remove(&word_index);
self.save_word(word_index);
}
}
}
Task::none()
}
fn save_word(&mut self, i: usize) {
let state = &mut self.state.lock().unwrap();
let connection = &state.connection;
let word = &mut state.dictionary.get(i).unwrap().clone();
update_word(word, &connection);
state.dictionary[i] = word.clone();
}
fn launch_auto_save_offset(&mut self, index: usize) -> Task<RootMessage> {
let save_time = Utc::now().add(TimeDelta::milliseconds(2800));
self.auto_save_queue.insert(index, save_time);
let message = RootMessage::Dictionary(DictionaryMessage::TrySave(index));
Task::perform(async { tokio::time::sleep(Duration::from_secs(3)).await }, |_| message)
}
pub fn view(&self) -> iced::Element<'_, DictionaryMessage> {
container(
row![
@@ -281,14 +327,14 @@ impl DictionaryState {
.push(space().width(10));
line = line.push(
text_input("Ключ", &word.key)
text_input("Слово", &word.key)
.size(20)
.width(Length::Fill)
.on_input(move |string| DictionaryMessage::SetKey(i, string))
.on_submit(DictionaryMessage::SubmitWord(i)),
);
line = line.push(
text_input("Значение", &word.value)
text_input("Перевод", &word.value)
.size(20)
.width(Length::Fill)
.on_input(move |string| DictionaryMessage::SetValue(i, string))
@@ -408,7 +454,7 @@ impl DictionaryState {
}
}
fn update_words_include(&mut self) {
fn update_words_include(&mut self, group_id: u32) {
let include_tags = self
.tag_map
.iter()
@@ -425,7 +471,7 @@ impl DictionaryState {
for i in 0..self.include_map.len() {
let tags = split_with_coma(dict[i].tags.clone());
if tags.iter().all(|t| include_tags.contains(t)) {
if tags.iter().all(|t| include_tags.contains(t)) && dict[i].group_id == group_id {
self.include_map[i] = true;
} else {
self.include_map[i] = false;
+4 -1
View File
@@ -265,6 +265,8 @@ impl CardSetSettings {
let ast = ast.unwrap();
let groups = &state.word_groups;
for word in &state.dictionary {
let mut more = rhai::Map::new();
for iced in &word.additional {
@@ -275,7 +277,8 @@ impl CardSetSettings {
.push_constant("key", word.key.clone())
.push_constant("value", word.value.clone())
.push_constant("tags", word.tags.clone())
.push_constant("more", more);
.push_constant("more", more)
.push_constant("group", groups.iter().find(|g| g.id == word.group_id).cloned().unwrap().name);
let result = engine.eval_ast_with_scope::<bool>(&mut scope, &ast);
if result.is_ok() && result.unwrap() {
+13 -4
View File
@@ -58,10 +58,7 @@ impl WordState {
}
WordMessage::SetAdditional(key, value) => {
match key.as_str() {
"reading" => {
self.word.additional.insert(key, value.clone());
},
_ => todo!()
_ => { self.word.additional.insert(key, value.clone());}
}
},
@@ -77,6 +74,9 @@ impl WordState {
if !self.word.additional.contains_key("reading") {
fast_add = fast_add.push(button("Чтение").style(button::text).on_press(WordMessage::AddAdditional("reading".to_string())));
}
if !self.word.additional.contains_key("description") {
fast_add = fast_add.push(button("Описание").style(button::text).on_press(WordMessage::AddAdditional("description".to_string())));
}
let mut col = iced::widget::column![
button("Назад").on_press(WordMessage::Back),
text!("Ключ"),
@@ -112,6 +112,7 @@ impl WordState {
fn get_view_for_more(&self, value: (&String, &String)) -> Element<'_, WordMessage> {
match value.0.as_str() {
"reading" => self.reading_field(value),
"description" => self.description_field(value),
_ => space().into(),
}
}
@@ -124,6 +125,14 @@ impl WordState {
].spacing(DEFAULT_SPACING)
.into()
}
fn description_field(&self, value: (&String, &String)) -> Element<'_, WordMessage> {
column![
text!("Описание"),
text_input("description", &value.1)
.on_input(|string| WordMessage::SetAdditional("description".to_string(), string))
].spacing(DEFAULT_SPACING)
.into() }
}
#[derive(Debug, Clone)]
pub enum WordMessage {