Repetitions remake #1
No files matched your search
@@ -81,3 +81,13 @@ pub fn delete_stat(stat: &CardStatistics, connection: &Connection) {
|
|||||||
.execute("DELETE FROM card_stats WHERE id = ?1", (&stat.id,))
|
.execute("DELETE FROM card_stats WHERE id = ?1", (&stat.id,))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_stats(stat: &[CardStatistics], connection: &Connection) {
|
||||||
|
if stat.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ids = stat.iter().map(|s| s.id.into()).collect::<Vec<String>>().join(", ");
|
||||||
|
connection
|
||||||
|
.execute(format!("DELETE FROM card_stats WHERE id in {ids}").as_str(), ())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
+11
-10
@@ -26,7 +26,7 @@ const MAX_HISTORY_LEN: usize = 20;
|
|||||||
const MAX_HISTORY_LEN_PART: f32 = 0.33;
|
const MAX_HISTORY_LEN_PART: f32 = 0.33;
|
||||||
const MAX_SCORE: u8 = 25;
|
const MAX_SCORE: u8 = 25;
|
||||||
const FADE_PER_DAY: f32 = 0.95;
|
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 struct Id(u32);
|
||||||
pub const INVALID_ID: Id = Id(0);
|
pub const INVALID_ID: Id = Id(0);
|
||||||
impl FromStr for Id {
|
impl FromStr for Id {
|
||||||
@@ -69,6 +69,12 @@ impl ToSql for Id {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Id> for String {
|
||||||
|
fn from(value: Id) -> Self {
|
||||||
|
value.0.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Id {
|
impl Id {
|
||||||
pub(crate) fn is_valid(self) -> bool {
|
pub(crate) fn is_valid(self) -> bool {
|
||||||
self.0 != 0
|
self.0 != 0
|
||||||
@@ -357,17 +363,12 @@ impl DeckData {
|
|||||||
let state_for = state.clone();
|
let state_for = state.clone();
|
||||||
let state_locked = state.lock();
|
let state_locked = state.lock();
|
||||||
|
|
||||||
let mut current_set = load_stats_of_deck(settings, &state_locked.connection);
|
let stats = load_stats_of_deck(settings, &state_locked.connection);
|
||||||
let last_list: Vec<_> = settings
|
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();
|
||||||
.get_word_list(&state_locked)
|
|
||||||
.iter()
|
|
||||||
.map(|w| &state_locked.dictionary[*w])
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
set: current_set,
|
set: stats,
|
||||||
words: last_list,
|
words,
|
||||||
current_word_index: None,
|
current_word_index: None,
|
||||||
state: state_for,
|
state: state_for,
|
||||||
order_module: match settings.open_mode {
|
order_module: match settings.open_mode {
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
use crate::AppState;
|
|
||||||
use crate::data_provider::card_sets::{delete_set, update_deck};
|
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::lang::DeckSettings;
|
||||||
use crate::navigation::Page::PreviousPage;
|
use crate::navigation::Page::PreviousPage;
|
||||||
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
use crate::navigation::{NavigatedPage, Page, RootMessage};
|
||||||
use crate::repetition_settings::RepetitionSettingsMessage::*;
|
use crate::repetition_settings::RepetitionSettingsMessage::*;
|
||||||
use crate::styling::*;
|
use crate::styling::*;
|
||||||
|
use crate::AppState;
|
||||||
use iced::widget::button::danger;
|
use iced::widget::button::danger;
|
||||||
use iced::widget::text_input::Catalog;
|
use iced::widget::text_input::Catalog;
|
||||||
use iced::widget::{button, column, row, scrollable, space, text, text_input};
|
use iced::widget::{button, column, row, scrollable, space, text, text_input};
|
||||||
use iced::{Element, Task};
|
use iced::{Element, Task};
|
||||||
use iced_core::Length::Fill;
|
use iced_core::Length::Fill;
|
||||||
use iced_core::{Padding, Theme, color};
|
use iced_core::{color, Padding, Theme};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -21,6 +22,7 @@ pub struct RepetitionSettingsState {
|
|||||||
state: Arc<Mutex<AppState>>,
|
state: Arc<Mutex<AppState>>,
|
||||||
real_delete: bool,
|
real_delete: bool,
|
||||||
correct_filter: bool,
|
correct_filter: bool,
|
||||||
|
filter_changed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RepetitionSettingsState {
|
impl RepetitionSettingsState {
|
||||||
@@ -38,6 +40,7 @@ impl RepetitionSettingsState {
|
|||||||
state,
|
state,
|
||||||
real_delete: false,
|
real_delete: false,
|
||||||
correct_filter: filter_state,
|
correct_filter: filter_state,
|
||||||
|
filter_changed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,6 +61,9 @@ impl NavigatedPage<RepetitionSettingsMessage> for RepetitionSettingsState {
|
|||||||
Save => {
|
Save => {
|
||||||
let mut state = self.state.lock();
|
let mut state = self.state.lock();
|
||||||
update_deck(&mut self.set, &state.connection);
|
update_deck(&mut self.set, &state.connection);
|
||||||
|
if self.filter_changed {
|
||||||
|
update_deck_stats(&self.set, &state);
|
||||||
|
}
|
||||||
state.decks[self.index] = self.set.clone();
|
state.decks[self.index] = self.set.clone();
|
||||||
}
|
}
|
||||||
SetName(new) => {
|
SetName(new) => {
|
||||||
@@ -72,6 +78,7 @@ impl NavigatedPage<RepetitionSettingsMessage> for RepetitionSettingsState {
|
|||||||
SetFilter(new) => {
|
SetFilter(new) => {
|
||||||
self.set.filter = new;
|
self.set.filter = new;
|
||||||
self.correct_filter = self.set.check_filter();
|
self.correct_filter = self.set.check_filter();
|
||||||
|
self.filter_changed = true;
|
||||||
}
|
}
|
||||||
TryFilter => {
|
TryFilter => {
|
||||||
let state = self.state.lock();
|
let state = self.state.lock();
|
||||||
@@ -163,6 +170,19 @@ impl NavigatedPage<RepetitionSettingsMessage> 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 {
|
impl RepetitionSettingsState {
|
||||||
fn count_view(&self, set: &DeckSettings) -> Element<'_, RepetitionSettingsMessage> {
|
fn count_view(&self, set: &DeckSettings) -> Element<'_, RepetitionSettingsMessage> {
|
||||||
if let Some(count) = set.count {
|
if let Some(count) = set.count {
|
||||||
|
|||||||
+20
-10
@@ -87,6 +87,10 @@ impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
|||||||
drop(state);
|
drop(state);
|
||||||
self.decks.remove(index);
|
self.decks.remove(index);
|
||||||
self.clear_selection();
|
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 {
|
} else {
|
||||||
drop(state);
|
drop(state);
|
||||||
@@ -138,16 +142,7 @@ impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
|||||||
self.select_deck(index);
|
self.select_deck(index);
|
||||||
let deck = self.selected_deck().unwrap();
|
let deck = self.selected_deck().unwrap();
|
||||||
if deck.existing_words_indices.is_none() {
|
if deck.existing_words_indices.is_none() {
|
||||||
let state = self.state.lock();
|
self.fill_deck_word_indices();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Save => {
|
Save => {
|
||||||
@@ -618,6 +613,20 @@ impl RepetitionsState {
|
|||||||
fn clear_selection(&mut self) {
|
fn clear_selection(&mut self) {
|
||||||
self.selected_deck_index = None;
|
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)]
|
#[derive(Clone)]
|
||||||
pub enum RepetitionsMessage {
|
pub enum RepetitionsMessage {
|
||||||
@@ -648,6 +657,7 @@ struct DeckViewData {
|
|||||||
append_mode: AppendMode,
|
append_mode: AppendMode,
|
||||||
index: Option<usize>,
|
index: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for DeckViewData {
|
impl Deref for DeckViewData {
|
||||||
type Target = DeckSettings;
|
type Target = DeckSettings;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user