From 22c05250aac23124a13c61a3fe590ba99a280bf9 Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Fri, 4 Sep 2026 22:34:36 +0300 Subject: [PATCH] Repetition settings remake --- src/data/repositories.rs | 18 +++++- src/pages/repetition_settings.rs | 95 +++++++++++++++++++------------- 2 files changed, 73 insertions(+), 40 deletions(-) diff --git a/src/data/repositories.rs b/src/data/repositories.rs index 8d28a30..f455dc1 100644 --- a/src/data/repositories.rs +++ b/src/data/repositories.rs @@ -1,5 +1,5 @@ use crate::data::Id; -use crate::data::entities::{EntityData, EntityHandle}; +use crate::data::entities::{CardState, EntityData, EntityHandle}; use crate::data_provider::sqlite::SqliteConnection; use crate::helpers::into_result; use crate::notification::{MaybeError, NotificationData}; @@ -22,6 +22,8 @@ where fn get_static(&self, handle: EntityHandle) -> Option; fn get_ref_static(&self, handle: EntityHandle) -> Option<&T>; fn get_mut_static(&mut self, handle: EntityHandle) -> Option<&mut T>; + fn set(&mut self, handle: &mut EntityHandle, value: T); + fn set_static(&mut self, handle: EntityHandle, value: T); fn handle_by_id(&self, id: Id) -> EntityHandle; fn create(&mut self, new: T) -> EntityHandle; fn create_now(&mut self, new: T) -> Result, NotificationData>; @@ -411,6 +413,20 @@ impl> Repository for DataRepositoryIn self.get_mut(&mut handle) } + fn set(&mut self, handle: &mut EntityHandle, value: T) { + let slice = if handle.real() { + self.cache.as_mut_slice() + } else { + self.temporal.as_mut_slice() + }; + let index = fast_position_of(slice, handle).unwrap(); + slice[index] = value; + } + + fn set_static(&mut self, mut handle: EntityHandle, value: T) { + self.set(&mut handle, value) + } + fn handle_by_id(&self, id: Id) -> EntityHandle { EntityHandle::new(id, id.0 as usize, true) } diff --git a/src/pages/repetition_settings.rs b/src/pages/repetition_settings.rs index 1a08472..697a10a 100644 --- a/src/pages/repetition_settings.rs +++ b/src/pages/repetition_settings.rs @@ -1,6 +1,7 @@ use crate::app::AppState; +use crate::core::deck::DeckData; use crate::data::entities::{DeckSettings, EntityHandle}; -use crate::data_provider::card_states::{delete_stats, load_stats_of_deck}; +use crate::data::repositories::{BatchedRepository, Repository}; use crate::navigation::Page::PreviousPage; use crate::navigation::{NavigatedPage, Page, RootMessage}; use crate::notification::MaybeError; @@ -13,29 +14,33 @@ use iced::widget::{button, column, row, scrollable, space, text, text_input}; use iced::{Element, Task}; use iced_core::Length::Fill; use iced_core::{Padding, Theme, color}; -use parking_lot::Mutex; use std::sync::Arc; use std::time::Duration; -use crate::core::deck::DeckData; -use crate::data::repositories::BatchedRepository; pub struct RepetitionSettingsState { - settings: EntityHandle, + settings_handle: EntityHandle, + settings_data: DeckSettings, state: AppState, real_delete: bool, correct_filter: bool, filter_changed: bool, - filtered_words: Option + filtered_words: Option, } impl RepetitionSettingsState { - pub(crate) fn new(settings: EntityHandle, state: AppState) -> RepetitionSettingsState { + pub(crate) fn new( + settings: EntityHandle, + state: AppState, + ) -> RepetitionSettingsState { + let data = state.decks.read().get_static(settings).unwrap(); RepetitionSettingsState { - settings, + settings_data: data, + settings_handle: settings, state, real_delete: false, correct_filter: false, filter_changed: false, + filtered_words: None, } } } @@ -54,36 +59,39 @@ impl NavigatedPage for RepetitionSettingsState { match message { Back => {} Save => { - let mut state = self.state.lock(); - if let Err(e) = update_deck(&mut self.settings, &state.connection) { + let mut decks = self.state.decks.write(); + decks.set(&mut self.settings_handle, self.settings_data.clone()); + + if let Err(e) = decks.save(&mut self.settings_handle) { return push_error_task!(e); } + drop(decks); if self.filter_changed - && let Err(e) = update_deck_stats(&self.settings, &state) + && let Err(e) = update_deck_stats(&self.settings_data, &self.state) { return push_error_task!(e); } - state.decks[self.index] = self.settings.clone(); } SetName(new) => { - self.settings.name = new; + self.settings_data.name = new; } SetForward(new) => { - self.settings.forward = new; + self.settings_data.forward = new; } SetBackward(backward) => { - self.settings.backward = backward; + self.settings_data.backward = backward; } SetFilter(new) => { - self.settings.filter = new; - self.correct_filter = self.settings.check_filter(); + self.settings_data.filter = new; + self.correct_filter = self.settings_data.check_filter(); self.filter_changed = true; } - TryFilter => { - let state = self.state.lock(); - let count = self.settings.get_word_list(&state).len(); - self.settings.count = Some(count); - } + TryFilter => match DeckData::list(&self.settings_data, &self.state) { + Ok(list) => { + self.filtered_words = Some(list.len() as u32); + } + Err(err) => return push_error_task!(err), + }, DeleteSet => { if !self.real_delete { self.real_delete = true; @@ -92,12 +100,11 @@ impl NavigatedPage for RepetitionSettingsState { RootMessage::RepetitionSettings(RevertDeleteSet) }); } - let mut state = self.state.lock(); - if let Err(e) = delete_set(&self.settings, &state.connection) { + let mut decks = self.state.decks.write(); + if let Err(e) = decks.delete(self.settings_handle) { return push_error_task!(e); } - state.decks.remove(self.index); return Task::done(RootMessage::RepetitionSettings(Back)); } RevertDeleteSet => self.real_delete = false, @@ -112,22 +119,22 @@ impl NavigatedPage for RepetitionSettingsState { column![ column![ text!("Название набора"), - text_input("", &self.settings.name).on_input(SetName), + text_input("", &self.settings_data.name).on_input(SetName), ] .spacing(QUARTER_SPACING), column![ text!("Передняя сторона"), - text_input("", &self.settings.forward).on_input(SetForward), + text_input("", &self.settings_data.forward).on_input(SetForward), ] .spacing(QUARTER_SPACING), column![ text!("Задняя сторона"), - text_input("", &self.settings.backward).on_input(SetBackward), + text_input("", &self.settings_data.backward).on_input(SetBackward), ] .spacing(QUARTER_SPACING), column![ text!("Фильтр"), - text_input("", &self.settings.filter) + text_input("", &self.settings_data.filter) .style(|x, status| { let mut primary = Theme::default()(x, status); if !self.correct_filter { @@ -139,7 +146,7 @@ impl NavigatedPage for RepetitionSettingsState { button("Проверить фильтр") .style(jl_button) .on_press(TryFilter), - self.count_view(&self.settings), + self.count_view(), ] .spacing(QUARTER_SPACING), ] @@ -173,23 +180,33 @@ impl NavigatedPage for RepetitionSettingsState { } fn update_deck_stats(deck: &DeckSettings, state: &AppState) -> MaybeError { - let mut db_stats = state.card_states.read().query_par(Arc::new(|s| s.set_id == deck.id)); - let filtered_words = DeckData::list(deck, state)?; - filtered_words.iter().for_each(|word| { - let word_id = state.dictionary[*word].id; - if let Some(index) = db_stats.iter().position(|stat| stat.word_id == word_id) { + let states_repo = &mut state.card_states.write(); + let deck_id = deck.id; + let mut db_stats = states_repo + .query_par(Arc::new(move |s| s.set_id == deck_id)) + .iter(&states_repo) + .collect::>(); + let filtered_words = DeckData::list(deck, state)? + .iter() + .map(|w| w.id) + .collect::>(); + filtered_words.iter().for_each(|word_id| { + if let Some(index) = db_stats.iter().position(|stat_id| stat_id.id == *word_id) { db_stats.remove(index); } }); - let repo = state.card_states.write(); - // repo.delete_many(); - // delete_stats(db_stats.as_slice(), &state.connection)?; + let mut delete_operation = db_stats + .iter() + .map(|state| EntityHandle::new(state.id, state.id.0 as usize, true)) + .collect::>(); + states_repo.delete_many(delete_operation.as_mut_slice())?; + Ok(()) } impl RepetitionSettingsState { - fn count_view(&self, set: &DeckSettings) -> Element<'_, RepetitionSettingsMessage> { + fn count_view(&self) -> Element<'_, RepetitionSettingsMessage> { if let Some(count) = self.filtered_words { return text!("Количество слов: {}", count).into(); }