diff --git a/src/data_provider/card_stats.rs b/src/data_provider/card_stats.rs index 144b9b4..8249c5c 100644 --- a/src/data_provider/card_stats.rs +++ b/src/data_provider/card_stats.rs @@ -81,3 +81,13 @@ pub fn delete_stat(stat: &CardStatistics, connection: &Connection) { .execute("DELETE FROM card_stats WHERE id = ?1", (&stat.id,)) .unwrap(); } + +pub fn delete_stats(stat: &[CardStatistics], connection: &Connection) { + if stat.is_empty() { + return; + } + let ids = stat.iter().map(|s| s.id.into()).collect::>().join(", "); + connection + .execute(format!("DELETE FROM card_stats WHERE id in {ids}").as_str(), ()) + .unwrap(); +} \ No newline at end of file diff --git a/src/lang.rs b/src/lang.rs index 846cc31..6370164 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -26,7 +26,7 @@ const MAX_HISTORY_LEN: usize = 20; const MAX_HISTORY_LEN_PART: f32 = 0.33; const MAX_SCORE: u8 = 25; const FADE_PER_DAY: f32 = 0.95; -#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, Debug, Hash, Copy, Ord, PartialOrd)] pub struct Id(u32); pub const INVALID_ID: Id = Id(0); impl FromStr for Id { @@ -69,6 +69,12 @@ impl ToSql for Id { } } +impl From for String { + fn from(value: Id) -> Self { + value.0.to_string() + } +} + impl Id { pub(crate) fn is_valid(self) -> bool { self.0 != 0 @@ -357,17 +363,12 @@ impl DeckData { let state_for = state.clone(); let state_locked = state.lock(); - let mut current_set = load_stats_of_deck(settings, &state_locked.connection); - let last_list: Vec<_> = settings - .get_word_list(&state_locked) - .iter() - .map(|w| &state_locked.dictionary[*w]) - .cloned() - .collect(); + let stats = load_stats_of_deck(settings, &state_locked.connection); + let words = stats.iter().map(|stat| state_locked.dictionary.binary_search_by_key(&stat.word_id, |w| w.id).unwrap()).map(|index| &state_locked.dictionary[index]).cloned().collect(); Self { - set: current_set, - words: last_list, + set: stats, + words, current_word_index: None, state: state_for, order_module: match settings.open_mode { diff --git a/src/repetition_settings.rs b/src/repetition_settings.rs index 4cbfa37..5217486 100644 --- a/src/repetition_settings.rs +++ b/src/repetition_settings.rs @@ -1,16 +1,17 @@ -use crate::AppState; use crate::data_provider::card_sets::{delete_set, update_deck}; +use crate::data_provider::card_stats::{delete_stats, load_stats_of_deck}; use crate::lang::DeckSettings; use crate::navigation::Page::PreviousPage; use crate::navigation::{NavigatedPage, Page, RootMessage}; use crate::repetition_settings::RepetitionSettingsMessage::*; use crate::styling::*; +use crate::AppState; use iced::widget::button::danger; use iced::widget::text_input::Catalog; 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 iced_core::{color, Padding, Theme}; use parking_lot::Mutex; use std::sync::Arc; use std::time::Duration; @@ -21,6 +22,7 @@ pub struct RepetitionSettingsState { state: Arc>, real_delete: bool, correct_filter: bool, + filter_changed: bool, } impl RepetitionSettingsState { @@ -38,6 +40,7 @@ impl RepetitionSettingsState { state, real_delete: false, correct_filter: filter_state, + filter_changed: false, } } } @@ -58,6 +61,9 @@ impl NavigatedPage for RepetitionSettingsState { Save => { let mut state = self.state.lock(); update_deck(&mut self.set, &state.connection); + if self.filter_changed { + update_deck_stats(&self.set, &state); + } state.decks[self.index] = self.set.clone(); } SetName(new) => { @@ -72,6 +78,7 @@ impl NavigatedPage for RepetitionSettingsState { SetFilter(new) => { self.set.filter = new; self.correct_filter = self.set.check_filter(); + self.filter_changed = true; } TryFilter => { let state = self.state.lock(); @@ -163,6 +170,19 @@ impl NavigatedPage for RepetitionSettingsState { } } +fn update_deck_stats(deck: &DeckSettings, state: &AppState) { + let mut db_stats = load_stats_of_deck(deck, &state.connection); + let filtered_words = deck.get_word_list(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) { + db_stats.remove(index); + } + }); + + delete_stats(db_stats.as_slice(), &state.connection); +} + impl RepetitionSettingsState { fn count_view(&self, set: &DeckSettings) -> Element<'_, RepetitionSettingsMessage> { if let Some(count) = set.count { diff --git a/src/repetitions.rs b/src/repetitions.rs index 7835627..1742a5f 100644 --- a/src/repetitions.rs +++ b/src/repetitions.rs @@ -87,6 +87,10 @@ impl NavigatedPage for RepetitionsState { drop(state); self.decks.remove(index); self.clear_selection(); + } else { + self.decks[self.selected_deck_index.unwrap()].general_settings = state.decks[index].clone(); + drop(state); + self.fill_deck_word_indices(); } } else { drop(state); @@ -138,16 +142,7 @@ impl NavigatedPage for RepetitionsState { self.select_deck(index); let deck = self.selected_deck().unwrap(); if deck.existing_words_indices.is_none() { - let state = self.state.lock(); - let added: Vec<_> = load_stats_of_deck(deck, &state.connection) - .iter() - .map(|c| self.word_id_index_map[&c.word_id]) - .collect(); - let total = deck.get_word_list(&state); - drop(state); - let deck = self.selected_deck_mut().unwrap(); - deck.existing_words_indices = Some(added); - deck.available_words_indices = Some(total); + self.fill_deck_word_indices(); } } Save => { @@ -618,6 +613,20 @@ impl RepetitionsState { fn clear_selection(&mut self) { self.selected_deck_index = None; } + + fn fill_deck_word_indices(&mut self) { + let state = &self.state.lock(); + let mut deck = self.selected_deck().unwrap().clone(); + let added: Vec<_> = load_stats_of_deck(&deck, &state.connection) + .iter() + .map(|c| self.word_id_index_map[&c.word_id]) + .collect(); + let total = deck.get_word_list(state); + deck.existing_words_indices = Some(added); + deck.available_words_indices = Some(total); + self.decks[self.selected_deck_index.unwrap()] = deck; + + } } #[derive(Clone)] pub enum RepetitionsMessage { @@ -648,6 +657,7 @@ struct DeckViewData { append_mode: AppendMode, index: Option, } + impl Deref for DeckViewData { type Target = DeckSettings;