Rename and clear bad code
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
use crate::lang::{AppendMode, CardSetSettings, OrderMode};
|
use crate::lang::{DeckSettings, OrderMode};
|
||||||
|
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
|
|
||||||
pub fn load_sets(connection: &Connection) -> Vec<CardSetSettings> {
|
pub fn load_sets(connection: &Connection) -> Vec<DeckSettings> {
|
||||||
let mut stmt = connection
|
let mut stmt = connection
|
||||||
.prepare("SELECT id, name, forward, backward, filter FROM card_set")
|
.prepare("SELECT id, name, forward, backward, filter FROM card_set")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let iter = stmt
|
let iter = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
Ok(CardSetSettings {
|
Ok(DeckSettings {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
name: row.get(1)?,
|
name: row.get(1)?,
|
||||||
forward: row.get(2)?,
|
forward: row.get(2)?,
|
||||||
@@ -17,7 +17,6 @@ pub fn load_sets(connection: &Connection) -> Vec<CardSetSettings> {
|
|||||||
count: None,
|
count: None,
|
||||||
worst_words_list: None,
|
worst_words_list: None,
|
||||||
open_mode: OrderMode::Default,
|
open_mode: OrderMode::Default,
|
||||||
append_mode: AppendMode::Manual,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -30,7 +29,7 @@ pub fn load_sets(connection: &Connection) -> Vec<CardSetSettings> {
|
|||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_set(set: &mut CardSetSettings, connection: &Connection) {
|
pub fn add_set(set: &mut DeckSettings, connection: &Connection) {
|
||||||
let index = connection
|
let index = connection
|
||||||
.query_row(
|
.query_row(
|
||||||
"INSERT INTO card_set (name, forward, backward, filter) VALUES (?1, ?2, ?3, ?4) RETURNING id",
|
"INSERT INTO card_set (name, forward, backward, filter) VALUES (?1, ?2, ?3, ?4) RETURNING id",
|
||||||
@@ -47,7 +46,7 @@ pub fn add_set(set: &mut CardSetSettings, connection: &Connection) {
|
|||||||
set.id = index;
|
set.id = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_card_set(set: &mut CardSetSettings, connection: &Connection) {
|
pub fn update_card_set(set: &mut DeckSettings, connection: &Connection) {
|
||||||
if set.id == 0 {
|
if set.id == 0 {
|
||||||
add_set(set, connection);
|
add_set(set, connection);
|
||||||
} else {
|
} else {
|
||||||
@@ -66,7 +65,7 @@ pub fn update_card_set(set: &mut CardSetSettings, connection: &Connection) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_set(set: &CardSetSettings, connection: &Connection) {
|
pub fn delete_set(set: &DeckSettings, connection: &Connection) {
|
||||||
if set.id == 0 {
|
if set.id == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::lang::{CardSetSettings, CardStatistics};
|
use crate::lang::{DeckSettings, CardStatistics};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
pub fn load_stats_of_set(set: &CardSetSettings, connection: &Connection) -> Vec<CardStatistics> {
|
pub fn load_stats_of_set(set: &DeckSettings, connection: &Connection) -> Vec<CardStatistics> {
|
||||||
let mut stmt = connection
|
let mut stmt = connection
|
||||||
.prepare("SELECT id, word_id, score, last_opened FROM card_stats WHERE set_id = ?1")
|
.prepare("SELECT id, word_id, score, last_opened FROM card_stats WHERE set_id = ?1")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ pub async fn get_web_version(key: &str) -> Result<u32, reqwest::Error> {
|
|||||||
let id_url = format!("{API_URL}{key}/version");
|
let id_url = format!("{API_URL}{key}/version");
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let version = client.get(&id_url).send().await?.text().await?;
|
let version = client.get(&id_url).send().await?.text().await?;
|
||||||
Ok(version.parse::<u32>().unwrap())
|
println!("version: {}", version);
|
||||||
|
Ok(version.parse::<u32>().unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_local_version() -> u32 {
|
pub async fn get_local_version() -> u32 {
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ pub enum DictionaryMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<DictionaryMessage> for DictionaryState {
|
impl NavigatedPage<DictionaryMessage> for DictionaryState {
|
||||||
fn navigate(&self, message: &DictionaryMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &DictionaryMessage) -> Option<Page> {
|
||||||
if let Back = message {
|
if let Back = message {
|
||||||
return Some(Page::PreviousPage);
|
return Some(Page::PreviousPage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ pub enum DictionaryQuizMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<DictionaryQuizMessage> for DictionaryQuizState {
|
impl NavigatedPage<DictionaryQuizMessage> for DictionaryQuizState {
|
||||||
fn navigate(&self, message: &DictionaryQuizMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &DictionaryQuizMessage) -> Option<Page> {
|
||||||
match message {
|
match message {
|
||||||
Back => Some(PreviousPage),
|
Back => Some(PreviousPage),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ pub struct HistoryState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<HistoryMessage> for HistoryState {
|
impl NavigatedPage<HistoryMessage> for HistoryState {
|
||||||
fn navigate(&self, message: &HistoryMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &HistoryMessage) -> Option<Page> {
|
||||||
match message {
|
match message {
|
||||||
Back => Some(Page::PreviousPage),
|
Back => Some(Page::PreviousPage),
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ pub enum ImportMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<ImportMessage> for ImportState {
|
impl NavigatedPage<ImportMessage> for ImportState {
|
||||||
fn navigate(&self, message: &ImportMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &ImportMessage) -> Option<Page> {
|
||||||
if self.progress.is_some() {
|
if self.progress.is_some() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-53
@@ -1,9 +1,9 @@
|
|||||||
use crate::AppState;
|
|
||||||
use crate::data_provider::card_stats::{delete_stat, load_stats_of_set, update_stat_score};
|
use crate::data_provider::card_stats::{delete_stat, load_stats_of_set, update_stat_score};
|
||||||
use crate::data_provider::history::{HistoryItem, push_note};
|
use crate::data_provider::history::{push_note, HistoryItem};
|
||||||
|
use crate::AppState;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use rand::distr::Distribution;
|
|
||||||
use rand::distr::weighted::WeightedIndex;
|
use rand::distr::weighted::WeightedIndex;
|
||||||
|
use rand::distr::Distribution;
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
use rand::rng;
|
use rand::rng;
|
||||||
use rand::rngs::ThreadRng;
|
use rand::rngs::ThreadRng;
|
||||||
@@ -12,7 +12,6 @@ use rayon::iter::IntoParallelRefIterator;
|
|||||||
use rayon::iter::ParallelIterator;
|
use rayon::iter::ParallelIterator;
|
||||||
use rhai::{Engine, Scope};
|
use rhai::{Engine, Scope};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::cmp::min;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -300,17 +299,17 @@ pub enum WordOpenMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CardSet {
|
pub struct DeckData {
|
||||||
words: Vec<WordData>,
|
words: Vec<WordData>,
|
||||||
set: Vec<CardStatistics>,
|
set: Vec<CardStatistics>,
|
||||||
current_word_index: Option<usize>,
|
current_word_index: Option<usize>,
|
||||||
state: Arc<Mutex<AppState>>,
|
state: Arc<Mutex<AppState>>,
|
||||||
order_module: OrderModule,
|
order_module: OrderModule,
|
||||||
settings: CardSetSettings,
|
settings: DeckSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardSet {
|
impl DeckData {
|
||||||
pub fn new(settings: &CardSetSettings, state: Arc<Mutex<AppState>>) -> Self {
|
pub fn new(settings: &DeckSettings, state: Arc<Mutex<AppState>>) -> Self {
|
||||||
let state_for = state.clone();
|
let state_for = state.clone();
|
||||||
let state_locked = state.lock().unwrap();
|
let state_locked = state.lock().unwrap();
|
||||||
|
|
||||||
@@ -323,30 +322,6 @@ impl CardSet {
|
|||||||
.collect();
|
.collect();
|
||||||
let word_ids = last_list.iter().map(|l| l.id).collect::<Vec<u32>>();
|
let word_ids = last_list.iter().map(|l| l.id).collect::<Vec<u32>>();
|
||||||
|
|
||||||
// let new_stats: &mut Vec<CardStatistics> = &mut last_list
|
|
||||||
// .iter()
|
|
||||||
// .filter(|word| !saved_ids.contains(&word.id))
|
|
||||||
// .map(|word| CardStatistics {
|
|
||||||
// id: 0,
|
|
||||||
// word_id: word.id,
|
|
||||||
// last_open: Utc::now(),
|
|
||||||
// score: 1,
|
|
||||||
// set_id: settings.id,
|
|
||||||
// })
|
|
||||||
// .collect();
|
|
||||||
//
|
|
||||||
// let time = Instant::now();
|
|
||||||
//
|
|
||||||
// if !new_stats.is_empty() {
|
|
||||||
// add_stat_list(new_stats, &state_locked.connection);
|
|
||||||
// current_set.append(new_stats);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// println!(
|
|
||||||
// "Added {} stats: {}",
|
|
||||||
// new_stats.len(),
|
|
||||||
// time.elapsed().as_millis()
|
|
||||||
// );
|
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
for stat in current_set.clone() {
|
for stat in current_set.clone() {
|
||||||
if !word_ids.contains(&stat.word_id) {
|
if !word_ids.contains(&stat.word_id) {
|
||||||
@@ -455,9 +430,10 @@ pub enum OrderMode {
|
|||||||
FullRandom,
|
FullRandom,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq, Default)]
|
||||||
pub enum AppendMode {
|
pub enum AppendMode {
|
||||||
Full,
|
Full,
|
||||||
|
#[default]
|
||||||
Manual,
|
Manual,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,9 +445,9 @@ enum OrderModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait SRSModule {
|
trait SRSModule {
|
||||||
fn next(&mut self, set: &mut CardSet) -> usize;
|
fn next(&mut self, set: &mut DeckData) -> usize;
|
||||||
fn open(&mut self, status: WordOpenMode, index: usize, updated_word: CardStatistics);
|
fn open(&mut self, status: WordOpenMode, index: usize, updated_word: CardStatistics);
|
||||||
fn init(&mut self, set: &mut CardSet);
|
fn init(&mut self, set: &mut DeckData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -490,7 +466,7 @@ impl RandomSRSModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SRSModule for RandomSRSModule {
|
impl SRSModule for RandomSRSModule {
|
||||||
fn next(&mut self, set: &mut CardSet) -> usize {
|
fn next(&mut self, set: &mut DeckData) -> usize {
|
||||||
if self.basket.is_empty() {
|
if self.basket.is_empty() {
|
||||||
self.basket = (0..set.words.len()).collect::<Vec<usize>>();
|
self.basket = (0..set.words.len()).collect::<Vec<usize>>();
|
||||||
self.basket.shuffle(&mut rand::rng())
|
self.basket.shuffle(&mut rand::rng())
|
||||||
@@ -501,7 +477,7 @@ impl SRSModule for RandomSRSModule {
|
|||||||
|
|
||||||
fn open(&mut self, _: WordOpenMode, _: usize, _: CardStatistics) {}
|
fn open(&mut self, _: WordOpenMode, _: usize, _: CardStatistics) {}
|
||||||
|
|
||||||
fn init(&mut self, set: &mut CardSet) {
|
fn init(&mut self, set: &mut DeckData) {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
self.basket = (0..set.words.len()).collect::<Vec<usize>>();
|
self.basket = (0..set.words.len()).collect::<Vec<usize>>();
|
||||||
self.basket.shuffle(&mut rand::rng())
|
self.basket.shuffle(&mut rand::rng())
|
||||||
@@ -528,7 +504,7 @@ impl SemiRandomSRSModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SRSModule for SemiRandomSRSModule {
|
impl SRSModule for SemiRandomSRSModule {
|
||||||
fn next(&mut self, set: &mut CardSet) -> usize {
|
fn next(&mut self, set: &mut DeckData) -> usize {
|
||||||
let index = self.last_weights.sample(&mut self.generator);
|
let index = self.last_weights.sample(&mut self.generator);
|
||||||
|
|
||||||
if self.history.contains(&index) {
|
if self.history.contains(&index) {
|
||||||
@@ -550,7 +526,7 @@ impl SRSModule for SemiRandomSRSModule {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self, set: &mut CardSet) {
|
fn init(&mut self, set: &mut DeckData) {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
let weights = set
|
let weights = set
|
||||||
.set
|
.set
|
||||||
@@ -562,11 +538,8 @@ impl SRSModule for SemiRandomSRSModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SemiRandomSRSModule {
|
impl SemiRandomSRSModule {
|
||||||
fn history_len(&self, set: &CardSet) -> usize {
|
fn history_len(&self, set: &DeckData) -> usize {
|
||||||
min(
|
((set.len() as f32 * MAX_HISTORY_LEN_PART) as usize).clamp(1, MAX_HISTORY_LEN)
|
||||||
MAX_HISTORY_LEN,
|
|
||||||
(set.len() as f32 * MAX_HISTORY_LEN_PART) as usize,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,7 +554,7 @@ struct WorstWordsSRSModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SRSModule for WorstWordsSRSModule {
|
impl SRSModule for WorstWordsSRSModule {
|
||||||
fn next(&mut self, set: &mut CardSet) -> usize {
|
fn next(&mut self, set: &mut DeckData) -> usize {
|
||||||
if self.rounds_remaining == 0 {
|
if self.rounds_remaining == 0 {
|
||||||
self.fill_pool(set);
|
self.fill_pool(set);
|
||||||
self.rounds_remaining = self.rounds_count;
|
self.rounds_remaining = self.rounds_count;
|
||||||
@@ -597,7 +570,7 @@ impl SRSModule for WorstWordsSRSModule {
|
|||||||
|
|
||||||
fn open(&mut self, _: WordOpenMode, _: usize, _: CardStatistics) {}
|
fn open(&mut self, _: WordOpenMode, _: usize, _: CardStatistics) {}
|
||||||
|
|
||||||
fn init(&mut self, _: &mut CardSet) {
|
fn init(&mut self, _: &mut DeckData) {
|
||||||
self.initialized = true;
|
self.initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -614,7 +587,7 @@ impl WorstWordsSRSModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_pool(&mut self, set: &CardSet) {
|
fn fill_pool(&mut self, set: &DeckData) {
|
||||||
let mut sorted = set
|
let mut sorted = set
|
||||||
.set
|
.set
|
||||||
.clone()
|
.clone()
|
||||||
@@ -632,7 +605,7 @@ impl WorstWordsSRSModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CardSetSettings {
|
pub struct DeckSettings {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub forward: String,
|
pub forward: String,
|
||||||
@@ -641,12 +614,11 @@ pub struct CardSetSettings {
|
|||||||
pub count: Option<usize>,
|
pub count: Option<usize>,
|
||||||
pub worst_words_list: Option<Vec<WordData>>,
|
pub worst_words_list: Option<Vec<WordData>>,
|
||||||
pub open_mode: OrderMode,
|
pub open_mode: OrderMode,
|
||||||
pub append_mode: AppendMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardSetSettings {
|
impl DeckSettings {
|
||||||
pub(crate) fn with_name(name: String) -> CardSetSettings {
|
pub(crate) fn with_name(name: String) -> DeckSettings {
|
||||||
CardSetSettings {
|
DeckSettings {
|
||||||
id: 0,
|
id: 0,
|
||||||
name,
|
name,
|
||||||
forward: "".to_string(),
|
forward: "".to_string(),
|
||||||
@@ -655,7 +627,6 @@ impl CardSetSettings {
|
|||||||
count: None,
|
count: None,
|
||||||
worst_words_list: None,
|
worst_words_list: None,
|
||||||
open_mode: OrderMode::Default,
|
open_mode: OrderMode::Default,
|
||||||
append_mode: AppendMode::Manual,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -23,7 +23,7 @@ use crate::data_provider::card_sets::load_sets;
|
|||||||
use crate::data_provider::settings::get_setting;
|
use crate::data_provider::settings::get_setting;
|
||||||
use crate::data_provider::sqlite::default_connection;
|
use crate::data_provider::sqlite::default_connection;
|
||||||
use crate::data_provider::words::{load_word_groups, load_words};
|
use crate::data_provider::words::{load_word_groups, load_words};
|
||||||
use crate::lang::{CardSetSettings, WordData, WordGroup};
|
use crate::lang::{DeckSettings, WordData, WordGroup};
|
||||||
use crate::navigation::{AppSettings, RootMessage, ScreenState};
|
use crate::navigation::{AppSettings, RootMessage, ScreenState};
|
||||||
use crate::quiz::*;
|
use crate::quiz::*;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
@@ -81,7 +81,7 @@ fn subscription(_state: &ScreenState) -> Subscription<RootMessage> {
|
|||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub dictionary: Vec<WordData>,
|
pub dictionary: Vec<WordData>,
|
||||||
pub card_sets: Vec<CardSetSettings>,
|
pub card_sets: Vec<DeckSettings>,
|
||||||
pub word_groups: Vec<WordGroup>,
|
pub word_groups: Vec<WordGroup>,
|
||||||
pub connection: Connection,
|
pub connection: Connection,
|
||||||
pub sync_data: AppSettings,
|
pub sync_data: AppSettings,
|
||||||
|
|||||||
+1
-1
@@ -330,7 +330,7 @@ macro_rules! state_navigate_handle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait NavigatedPage<T> {
|
pub trait NavigatedPage<T> {
|
||||||
fn navigate(&self, message: &T) -> Option<Page>;
|
fn navigate(&mut self, message: &T) -> Option<Page>;
|
||||||
fn navigated(&mut self);
|
fn navigated(&mut self);
|
||||||
fn update(&mut self, message: T) -> Task<RootMessage>;
|
fn update(&mut self, message: T) -> Task<RootMessage>;
|
||||||
fn view(&self) -> Element<'_, T>;
|
fn view(&self) -> Element<'_, T>;
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ pub struct QuizState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<QuizMessage> for QuizState {
|
impl NavigatedPage<QuizMessage> for QuizState {
|
||||||
fn navigate(&self, message: &QuizMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &QuizMessage) -> Option<Page> {
|
||||||
if let Back = message {
|
if let Back = message {
|
||||||
Some(PreviousPage)
|
Some(PreviousPage)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ pub enum RandomizerMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<RandomizerMessage> for RandomizerState {
|
impl NavigatedPage<RandomizerMessage> for RandomizerState {
|
||||||
fn navigate(&self, message: &RandomizerMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &RandomizerMessage) -> Option<Page> {
|
||||||
if let Back = message {
|
if let Back = message {
|
||||||
return Some(Page::PreviousPage);
|
return Some(Page::PreviousPage);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -1,5 +1,5 @@
|
|||||||
use crate::data_provider::voice::get_voice;
|
use crate::data_provider::voice::get_voice;
|
||||||
use crate::lang::{CardSet, CardSetSettings, CardStatistics, WordData, WordOpenMode};
|
use crate::lang::{DeckData, DeckSettings, CardStatistics, WordData, WordOpenMode};
|
||||||
use crate::navigation::Page::PreviousPage;
|
use crate::navigation::Page::PreviousPage;
|
||||||
use crate::navigation::{KeyPressedPage, NavigatedPage, Page};
|
use crate::navigation::{KeyPressedPage, NavigatedPage, Page};
|
||||||
use crate::styling::*;
|
use crate::styling::*;
|
||||||
@@ -17,8 +17,8 @@ use tokio::task::spawn_blocking;
|
|||||||
|
|
||||||
pub struct RepetitionState {
|
pub struct RepetitionState {
|
||||||
state: Arc<Mutex<AppState>>,
|
state: Arc<Mutex<AppState>>,
|
||||||
pub settings: CardSetSettings,
|
pub settings: DeckSettings,
|
||||||
pub set: CardSet,
|
pub set: DeckData,
|
||||||
current_word: WordData,
|
current_word: WordData,
|
||||||
current_statistic: CardStatistics,
|
current_statistic: CardStatistics,
|
||||||
open: bool,
|
open: bool,
|
||||||
@@ -28,7 +28,7 @@ pub struct RepetitionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<RepetitionMessage> for RepetitionState {
|
impl NavigatedPage<RepetitionMessage> for RepetitionState {
|
||||||
fn navigate(&self, message: &RepetitionMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &RepetitionMessage) -> Option<Page> {
|
||||||
if let RepetitionMessage::Back = message {
|
if let RepetitionMessage::Back = message {
|
||||||
Some(PreviousPage)
|
Some(PreviousPage)
|
||||||
} else {
|
} else {
|
||||||
@@ -95,8 +95,8 @@ impl NavigatedPage<RepetitionMessage> for RepetitionState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RepetitionState {
|
impl RepetitionState {
|
||||||
pub(crate) fn new(set: CardSetSettings, state: Arc<Mutex<AppState>>) -> RepetitionState {
|
pub(crate) fn new(set: DeckSettings, state: Arc<Mutex<AppState>>) -> RepetitionState {
|
||||||
let mut card_set = CardSet::new(&set, state.clone());
|
let mut card_set = DeckData::new(&set, state.clone());
|
||||||
let (word, stat) = card_set.next();
|
let (word, stat) = card_set.next();
|
||||||
let sink_handle = rodio::DeviceSinkBuilder::open_default_sink().unwrap();
|
let sink_handle = rodio::DeviceSinkBuilder::open_default_sink().unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
use crate::data_provider::card_sets::{delete_set, update_card_set};
|
use crate::data_provider::card_sets::{delete_set, update_card_set};
|
||||||
use crate::lang::CardSetSettings;
|
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::*;
|
||||||
@@ -14,7 +14,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct RepetitionSettingsState {
|
pub struct RepetitionSettingsState {
|
||||||
set: CardSetSettings,
|
set: DeckSettings,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: Arc<Mutex<AppState>>,
|
state: Arc<Mutex<AppState>>,
|
||||||
real_delete: bool,
|
real_delete: bool,
|
||||||
@@ -37,7 +37,7 @@ impl RepetitionSettingsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<RepetitionSettingsMessage> for RepetitionSettingsState {
|
impl NavigatedPage<RepetitionSettingsMessage> for RepetitionSettingsState {
|
||||||
fn navigate(&self, message: &RepetitionSettingsMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &RepetitionSettingsMessage) -> Option<Page> {
|
||||||
if let Back = message {
|
if let Back = message {
|
||||||
Some(PreviousPage)
|
Some(PreviousPage)
|
||||||
} else {
|
} else {
|
||||||
@@ -149,7 +149,7 @@ impl NavigatedPage<RepetitionSettingsMessage> for RepetitionSettingsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RepetitionSettingsState {
|
impl RepetitionSettingsState {
|
||||||
fn count_view(&self, set: &CardSetSettings) -> Element<'_, RepetitionSettingsMessage> {
|
fn count_view(&self, set: &DeckSettings) -> Element<'_, RepetitionSettingsMessage> {
|
||||||
if let Some(count) = set.count {
|
if let Some(count) = set.count {
|
||||||
return text!("Количество слов: {}", count).into();
|
return text!("Количество слов: {}", count).into();
|
||||||
}
|
}
|
||||||
|
|||||||
+128
-169
@@ -1,7 +1,8 @@
|
|||||||
|
use std::ops::Deref;
|
||||||
use crate::data_provider::card_sets::{delete_set, update_card_set};
|
use crate::data_provider::card_sets::{delete_set, update_card_set};
|
||||||
use crate::data_provider::card_stats::{add_stat_list, load_stats_of_set};
|
use crate::data_provider::card_stats::{add_stat_list, load_stats_of_set};
|
||||||
use crate::history::HistoryState;
|
use crate::history::HistoryState;
|
||||||
use crate::lang::{AppendMode, CardSetSettings, CardStatistics, OrderMode};
|
use crate::lang::{AppendMode, DeckSettings, CardStatistics, OrderMode};
|
||||||
use crate::navigation::Page::{History, PreviousPage, Repetition, RepetitionSettings};
|
use crate::navigation::Page::{History, PreviousPage, Repetition, RepetitionSettings};
|
||||||
use crate::navigation::{NavigatedPage, Page};
|
use crate::navigation::{NavigatedPage, Page};
|
||||||
use crate::repetition::RepetitionState;
|
use crate::repetition::RepetitionState;
|
||||||
@@ -11,53 +12,65 @@ use crate::styling::*;
|
|||||||
use crate::{AppState, RootMessage};
|
use crate::{AppState, RootMessage};
|
||||||
use chrono::{Days, Local, Utc};
|
use chrono::{Days, Local, Utc};
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use iced::widget::button::{danger, Status};
|
|
||||||
pub use iced::widget::button::{Catalog, Style};
|
pub use iced::widget::button::{Catalog, Style};
|
||||||
|
use iced::widget::button::{Status, danger};
|
||||||
use iced::widget::tooltip::Position::Top;
|
use iced::widget::tooltip::Position::Top;
|
||||||
use iced::widget::{
|
use iced::widget::{
|
||||||
button, column, container, lazy, radio, row, scrollable, space, svg, text, text_input, tooltip,
|
Column, Row, button, column, container, lazy, radio, row, scrollable, space, svg, text,
|
||||||
Column, Row,
|
text_input, tooltip,
|
||||||
};
|
};
|
||||||
use iced::{Background, Border, Center, Color, Element, Fill, Length, Shadow, Task, Theme};
|
use iced::{Background, Border, Center, Color, Element, Fill, Length, Shadow, Task, Theme};
|
||||||
|
use iced_core::Padding;
|
||||||
use iced_core::border::Radius;
|
use iced_core::border::Radius;
|
||||||
use iced_core::svg::Handle;
|
use iced_core::svg::Handle;
|
||||||
use iced_core::Padding;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RepetitionsState {
|
pub struct RepetitionsState {
|
||||||
selected_set: Option<usize>,
|
selected_set_index: Option<usize>,
|
||||||
correct_filters: Vec<bool>,
|
correct_filters: Vec<bool>,
|
||||||
current_sets_cards_cache: HashMap<usize, (Vec<usize>, Vec<usize>)>,
|
current_sets_cards_cache: HashMap<usize, (Vec<usize>, Vec<usize>)>,
|
||||||
word_id_index_map: HashMap<u32, usize>,
|
word_id_index_map: HashMap<u32, usize>,
|
||||||
|
local_settings: HashMap<u32, DeckLocalSetting>,
|
||||||
|
view_data: Option<SetViewData>,
|
||||||
pub state: Arc<Mutex<AppState>>,
|
pub state: Arc<Mutex<AppState>>,
|
||||||
|
set_names: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
||||||
fn navigate(&self, message: &RepetitionsMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &RepetitionsMessage) -> Option<Page> {
|
||||||
if let Back = message {
|
if let Back = message {
|
||||||
Some(PreviousPage)
|
Some(PreviousPage)
|
||||||
} else if let GoToHistory = message {
|
} else if let GoToHistory = message {
|
||||||
let card_set;
|
let card_set;
|
||||||
{
|
{
|
||||||
card_set = self.state.lock().unwrap().card_sets[self.selected_set.unwrap()].id;
|
card_set = self.state.lock().unwrap().card_sets[self.selected_set_index.unwrap()].id;
|
||||||
}
|
}
|
||||||
Some(History(HistoryState::new(card_set, self.state.clone())))
|
Some(History(HistoryState::new(card_set, self.state.clone())))
|
||||||
} else if let GoToRepetition = message {
|
} else if let GoToRepetition = message {
|
||||||
let clone = self.state.clone();
|
let clone = self.state.clone();
|
||||||
let card_set;
|
let card_set;
|
||||||
{
|
{
|
||||||
card_set = self.state.lock().unwrap().card_sets[self.selected_set.unwrap()].clone();
|
card_set = self.state.lock().unwrap().card_sets[self.selected_set_index.unwrap()].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
if card_set.append_mode == AppendMode::Full {
|
if self.local_settings[&card_set.id].append_mode == AppendMode::Full {
|
||||||
self.append_all_words(&card_set);
|
self.append_all_words(&card_set);
|
||||||
|
} else {
|
||||||
|
let cache = self
|
||||||
|
.current_sets_cards_cache
|
||||||
|
.get(&self.selected_set_index.unwrap())
|
||||||
|
.unwrap();
|
||||||
|
if cache.1.is_empty() || cache.0.is_empty() {
|
||||||
|
let local_settings = self.local_settings.get_mut(&card_set.id).unwrap();
|
||||||
|
local_settings.append_warning = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Repetition(RepetitionState::new(card_set, clone)))
|
Some(Repetition(RepetitionState::new(card_set, clone)))
|
||||||
} else if let GoToSettings = message {
|
} else if let GoToSettings = message {
|
||||||
Some(RepetitionSettings(RepetitionSettingsState::new(
|
Some(RepetitionSettings(RepetitionSettingsState::new(
|
||||||
self.selected_set.unwrap(),
|
self.selected_set_index.unwrap(),
|
||||||
self.state.clone(),
|
self.state.clone(),
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
@@ -65,110 +78,29 @@ impl NavigatedPage<RepetitionsMessage> for RepetitionsState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn navigated(&mut self) {
|
fn navigated(&mut self) {
|
||||||
self.selected_set = None;
|
self.clear_selection();
|
||||||
self.current_sets_cards_cache.clear();
|
self.current_sets_cards_cache.clear();
|
||||||
}
|
}
|
||||||
fn update(&mut self, message: RepetitionsMessage) -> Task<RootMessage> {
|
fn update(&mut self, message: RepetitionsMessage) -> Task<RootMessage> {
|
||||||
let mut state = self.state.lock().unwrap();
|
|
||||||
match message {
|
match message {
|
||||||
Next => {}
|
Next => {}
|
||||||
Back => {}
|
Back => {}
|
||||||
GoToRepetition => {}
|
GoToRepetition => {}
|
||||||
GoToHistory => {}
|
GoToHistory => {}
|
||||||
GoToSettings => {}
|
GoToSettings => {}
|
||||||
CreateSet => {
|
|
||||||
let index = state.card_sets.len() + 1;
|
|
||||||
state
|
|
||||||
.card_sets
|
|
||||||
.push(CardSetSettings::with_name(format!("Card set #{}", index)));
|
|
||||||
self.correct_filters.push(true);
|
|
||||||
}
|
|
||||||
DeleteSet => {
|
|
||||||
let set = state.card_sets.remove(self.selected_set.unwrap());
|
|
||||||
self.correct_filters.remove(self.selected_set.unwrap());
|
|
||||||
self.selected_set = None;
|
|
||||||
delete_set(&set, &state.connection);
|
|
||||||
}
|
|
||||||
SelectSet(index) => {
|
|
||||||
self.selected_set = Some(index);
|
|
||||||
let set = state.card_sets.get(index).unwrap().clone();
|
|
||||||
if !self.current_sets_cards_cache.contains_key(&index) {
|
|
||||||
let added: Vec<_> = load_stats_of_set(&set, &state.connection)
|
|
||||||
.iter()
|
|
||||||
.map(|c| self.word_id_index_map[&c.word_id])
|
|
||||||
.collect();
|
|
||||||
let total = set.get_word_list(&state);
|
|
||||||
|
|
||||||
self.current_sets_cards_cache.insert(index, (added, total));
|
CreateSet => {}
|
||||||
|
DeleteSet => {}
|
||||||
}
|
SetName(_) => {}
|
||||||
state.card_sets[index] = set;
|
SelectSet(_) => {}
|
||||||
}
|
Save => {}
|
||||||
SetName(new) => {
|
SetForward(_) => {}
|
||||||
state.card_sets[self.selected_set.unwrap()].name = new;
|
SetBackward(_) => {}
|
||||||
}
|
SetFilter(_) => {}
|
||||||
Save => {
|
TryFilter => {}
|
||||||
for i in 0..state.card_sets.len() {
|
SetOpenMode(_) => {}
|
||||||
self.correct_filters[i] = state.card_sets[i].check_filter();
|
SetAppendMode(_) => {}
|
||||||
}
|
AppendWords(_) => {}
|
||||||
|
|
||||||
let set = &mut state.card_sets[self.selected_set.unwrap()].clone();
|
|
||||||
|
|
||||||
update_card_set(set, &state.connection);
|
|
||||||
|
|
||||||
state.card_sets[self.selected_set.unwrap()] = set.clone();
|
|
||||||
}
|
|
||||||
SetForward(new) => {
|
|
||||||
state.card_sets[self.selected_set.unwrap()].forward = new;
|
|
||||||
}
|
|
||||||
SetBackward(new) => {
|
|
||||||
state.card_sets[self.selected_set.unwrap()].backward = new;
|
|
||||||
}
|
|
||||||
SetFilter(new) => {
|
|
||||||
state.card_sets[self.selected_set.unwrap()].filter = new;
|
|
||||||
}
|
|
||||||
TryFilter => {
|
|
||||||
let set = state.card_sets.get(self.selected_set.unwrap()).unwrap();
|
|
||||||
let count = set.get_word_list(&state).len();
|
|
||||||
state.card_sets[self.selected_set.unwrap()].count = Some(count);
|
|
||||||
}
|
|
||||||
SetOpenMode(mode) => {
|
|
||||||
state
|
|
||||||
.card_sets
|
|
||||||
.get_mut(self.selected_set.unwrap())
|
|
||||||
.unwrap()
|
|
||||||
.open_mode = mode;
|
|
||||||
}
|
|
||||||
SetAppendMode(mode) => {
|
|
||||||
let set = state.card_sets.get_mut(self.selected_set.unwrap()).unwrap();
|
|
||||||
set.append_mode = mode;
|
|
||||||
}
|
|
||||||
AppendWords(count) => {
|
|
||||||
let adding: Vec<usize>;
|
|
||||||
let set = state.card_sets.get(self.selected_set.unwrap()).unwrap();
|
|
||||||
let index = self.selected_set.unwrap();
|
|
||||||
{
|
|
||||||
let total_cache = &mut self.current_sets_cards_cache;
|
|
||||||
let cache = total_cache.get_mut(&index).unwrap().clone();
|
|
||||||
let mut created_set = HashSet::with_capacity(cache.0.len());
|
|
||||||
cache.0.iter().for_each(|c| {
|
|
||||||
created_set.insert(c);
|
|
||||||
});
|
|
||||||
adding = cache
|
|
||||||
.1
|
|
||||||
.iter()
|
|
||||||
.filter(|c| !created_set.contains(c))
|
|
||||||
.take(count)
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut new_current = cache.0.clone();
|
|
||||||
new_current.append(&mut adding.clone());
|
|
||||||
total_cache.insert(index, (new_current, cache.1.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Self::append_words(&state, set, adding.into_iter());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
@@ -203,55 +135,34 @@ impl RepetitionsState {
|
|||||||
let count = state_.card_sets.len();
|
let count = state_.card_sets.len();
|
||||||
let mut map = HashMap::with_capacity(state_.dictionary.len());
|
let mut map = HashMap::with_capacity(state_.dictionary.len());
|
||||||
|
|
||||||
state_.dictionary.iter().enumerate().for_each(|(index, word)| {map.insert(word.id, index);});
|
state_
|
||||||
|
.dictionary
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(index, word)| {
|
||||||
|
map.insert(word.id, index);
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut local_settings = HashMap::with_capacity(state_.card_sets.len());
|
||||||
|
state_.card_sets.iter().for_each(|card_set| {
|
||||||
|
local_settings.insert(card_set.id, Default::default());
|
||||||
|
});
|
||||||
drop(state_);
|
drop(state_);
|
||||||
RepetitionsState {
|
RepetitionsState {
|
||||||
selected_set: None,
|
selected_set_index: None,
|
||||||
correct_filters: vec![true; count],
|
correct_filters: vec![true; count],
|
||||||
current_sets_cards_cache: Default::default(),
|
current_sets_cards_cache: Default::default(),
|
||||||
word_id_index_map: map,
|
word_id_index_map: map,
|
||||||
|
local_settings,
|
||||||
|
view_data: None,
|
||||||
state,
|
state,
|
||||||
|
set_names: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RepetitionsState {
|
impl RepetitionsState {
|
||||||
fn append_all_words(&self, set: &CardSetSettings) {
|
fn launch_delete_button(&self, set: &DeckSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
let index = self.selected_set.unwrap();
|
|
||||||
let cache = &self.current_sets_cards_cache[&index];
|
|
||||||
let mut created_set = HashSet::with_capacity(cache.0.len());
|
|
||||||
cache.0.iter().for_each(|c| {
|
|
||||||
created_set.insert(c);
|
|
||||||
});
|
|
||||||
let required = cache
|
|
||||||
.1
|
|
||||||
.iter()
|
|
||||||
.filter(|i| !created_set.contains(i)).cloned();
|
|
||||||
Self::append_words(&self.state.lock().unwrap(), set, required);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append_words(state: &AppState, set: &CardSetSettings, indices: impl Iterator<Item = usize>) {
|
|
||||||
let words = &state.dictionary;
|
|
||||||
let stats = &mut indices
|
|
||||||
.map(|i| {
|
|
||||||
let word = words.get(i).unwrap();
|
|
||||||
CardStatistics {
|
|
||||||
id: 0,
|
|
||||||
word_id: word.id,
|
|
||||||
last_open: Utc::now(),
|
|
||||||
score: 1,
|
|
||||||
set_id: set.id,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if !stats.is_empty() {
|
|
||||||
add_stat_list(stats, &state.connection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn launch_delete_button(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
|
||||||
if set.id != 0 {
|
if set.id != 0 {
|
||||||
return row![
|
return row![
|
||||||
space().width(Fill),
|
space().width(Fill),
|
||||||
@@ -263,17 +174,8 @@ impl RepetitionsState {
|
|||||||
}
|
}
|
||||||
button("Удалить").style(danger).on_press(DeleteSet).into()
|
button("Удалить").style(danger).on_press(DeleteSet).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected_set_view(&self) -> Element<'_, RepetitionsMessage> {
|
fn selected_set_view(&self) -> Element<'_, RepetitionsMessage> {
|
||||||
if let Some(index) = self.selected_set {
|
if let Some(set) = &self.view_data {
|
||||||
let set;
|
|
||||||
{
|
|
||||||
let state = self.state.lock().unwrap();
|
|
||||||
if state.card_sets.len() <= index {
|
|
||||||
return space().width(Length::FillPortion(3)).into();
|
|
||||||
}
|
|
||||||
set = state.card_sets[index].clone();
|
|
||||||
}
|
|
||||||
return column![
|
return column![
|
||||||
scrollable(
|
scrollable(
|
||||||
column![
|
column![
|
||||||
@@ -362,14 +264,13 @@ impl RepetitionsState {
|
|||||||
}
|
}
|
||||||
space().width(Length::FillPortion(2)).into()
|
space().width(Length::FillPortion(2)).into()
|
||||||
}
|
}
|
||||||
|
fn filled_set_data_view(&self, set: &DeckSettings) -> Column<'_, RepetitionsMessage> {
|
||||||
fn filled_set_data_view(&self, set: &CardSetSettings) -> Column<'_, RepetitionsMessage> {
|
|
||||||
column![self.activity_bar(set), self.count_comparator_view()]
|
column![self.activity_bar(set), self.count_comparator_view()]
|
||||||
.align_x(Center)
|
.align_x(Center)
|
||||||
.width(Fill)
|
.width(Fill)
|
||||||
.spacing(DEFAULT_SPACING)
|
.spacing(DEFAULT_SPACING)
|
||||||
}
|
}
|
||||||
fn activity_bar(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
fn activity_bar(&self, set: &DeckSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
const MAX_DAY_COUNT: f32 = 128.0;
|
const MAX_DAY_COUNT: f32 = 128.0;
|
||||||
|
|
||||||
let state = self.state.lock().unwrap();
|
let state = self.state.lock().unwrap();
|
||||||
@@ -446,21 +347,20 @@ impl RepetitionsState {
|
|||||||
})
|
})
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
fn word_append_panel(&self, set: &DeckSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
fn word_append_panel(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
|
||||||
column![
|
column![
|
||||||
text!("Режим добавления карточек"),
|
text!("Режим добавления карточек"),
|
||||||
row![
|
row![
|
||||||
radio(
|
radio(
|
||||||
"Добавлять все доступные",
|
"Добавлять все доступные",
|
||||||
AppendMode::Full,
|
AppendMode::Full,
|
||||||
Some(set.append_mode),
|
Some(self.local_settings[&set.id].append_mode),
|
||||||
SetAppendMode
|
SetAppendMode
|
||||||
),
|
),
|
||||||
radio(
|
radio(
|
||||||
"Добавлять вручную",
|
"Добавлять вручную",
|
||||||
AppendMode::Manual,
|
AppendMode::Manual,
|
||||||
Some(set.append_mode),
|
Some(self.local_settings[&set.id].append_mode),
|
||||||
SetAppendMode
|
SetAppendMode
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@@ -470,9 +370,8 @@ impl RepetitionsState {
|
|||||||
.spacing(HALF_SPACING)
|
.spacing(HALF_SPACING)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
fn adder_panel(&self, set: &DeckSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
fn adder_panel(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
match self.local_settings[&set.id].append_mode {
|
||||||
match set.append_mode {
|
|
||||||
AppendMode::Full => space().into(),
|
AppendMode::Full => space().into(),
|
||||||
AppendMode::Manual => row![
|
AppendMode::Manual => row![
|
||||||
button("+5").on_press(AppendWords(5)),
|
button("+5").on_press(AppendWords(5)),
|
||||||
@@ -484,27 +383,24 @@ impl RepetitionsState {
|
|||||||
.into(),
|
.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_comparator_view(&self) -> Element<'_, RepetitionsMessage> {
|
fn count_comparator_view(&self) -> Element<'_, RepetitionsMessage> {
|
||||||
let cache = &self.current_sets_cards_cache[&self.selected_set.unwrap()];
|
let cache = &self.current_sets_cards_cache[&self.selected_set_index.unwrap()];
|
||||||
let now = cache.0.len();
|
let now = cache.0.len();
|
||||||
let available = cache.1.len();
|
let available = cache.1.len();
|
||||||
text!("{} слова добавлено из {}", now, available).into()
|
text!("{} слова добавлено из {}", now, available).into()
|
||||||
}
|
}
|
||||||
fn count_view(&self, set: &CardSetSettings) -> Element<'_, RepetitionsMessage> {
|
fn count_view(&self, set: &DeckSettings) -> Element<'_, RepetitionsMessage> {
|
||||||
if let Some(count) = set.count {
|
if let Some(count) = set.count {
|
||||||
return text!("Количество слов: {}", count).into();
|
return text!("Количество слов: {}", count).into();
|
||||||
}
|
}
|
||||||
space().into()
|
space().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sets_list(&self) -> Column<'_, RepetitionsMessage> {
|
fn sets_list(&self) -> Column<'_, RepetitionsMessage> {
|
||||||
let mut column = Column::new();
|
let mut column = Column::new();
|
||||||
|
|
||||||
let sets = &self.state.lock().unwrap().card_sets;
|
for (i, set) in self.set_names.iter().enumerate() {
|
||||||
for (i, set) in sets.iter().enumerate() {
|
|
||||||
column = column.push(
|
column = column.push(
|
||||||
button(text!("{}", set.name.clone()))
|
button(text!("{}", set.clone()))
|
||||||
.on_press_with(move || SelectSet(i))
|
.on_press_with(move || SelectSet(i))
|
||||||
.style(move |_x: &Theme, status: Status| Style {
|
.style(move |_x: &Theme, status: Status| Style {
|
||||||
background: if status == Status::Hovered {
|
background: if status == Status::Hovered {
|
||||||
@@ -532,6 +428,48 @@ impl RepetitionsState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RepetitionsState {
|
||||||
|
fn append_all_words(&self, set: &DeckSettings) {
|
||||||
|
let index = self.selected_set_index.unwrap();
|
||||||
|
let cache = &self.current_sets_cards_cache[&index];
|
||||||
|
let mut created_set = HashSet::with_capacity(cache.0.len());
|
||||||
|
cache.0.iter().for_each(|c| {
|
||||||
|
created_set.insert(c);
|
||||||
|
});
|
||||||
|
let required = cache.1.iter().filter(|i| !created_set.contains(i)).cloned();
|
||||||
|
Self::append_words(&self.state.lock().unwrap(), set, required);
|
||||||
|
}
|
||||||
|
fn append_words(state: &AppState, set: &DeckSettings, indices: impl Iterator<Item = usize>) {
|
||||||
|
let words = &state.dictionary;
|
||||||
|
let stats = &mut indices
|
||||||
|
.map(|i| {
|
||||||
|
let word = words.get(i).unwrap();
|
||||||
|
CardStatistics {
|
||||||
|
id: 0,
|
||||||
|
word_id: word.id,
|
||||||
|
last_open: Utc::now(),
|
||||||
|
score: 1,
|
||||||
|
set_id: set.id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !stats.is_empty() {
|
||||||
|
add_stat_list(stats, &state.connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn select_set(&mut self, index: usize) {
|
||||||
|
let state = self.state.lock().unwrap();
|
||||||
|
if let Some(set) = state.card_sets.get(index) {
|
||||||
|
self.selected_set_index = Some(index);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_selection(&mut self) {
|
||||||
|
self.selected_set_index = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum RepetitionsMessage {
|
pub enum RepetitionsMessage {
|
||||||
Next,
|
Next,
|
||||||
@@ -552,3 +490,24 @@ pub enum RepetitionsMessage {
|
|||||||
GoToSettings,
|
GoToSettings,
|
||||||
AppendWords(usize),
|
AppendWords(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
struct DeckLocalSetting {
|
||||||
|
append_mode: AppendMode,
|
||||||
|
append_warning: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SetViewData{
|
||||||
|
set_local_settings: DeckLocalSetting,
|
||||||
|
set_settings: DeckSettings,
|
||||||
|
existing_words_indices: Vec<usize>,
|
||||||
|
available_words_indices: Vec<usize>,
|
||||||
|
}
|
||||||
|
impl Deref for SetViewData {
|
||||||
|
type Target = DeckSettings;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.set_settings
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -36,7 +36,7 @@ pub enum SelectorMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<SelectorMessage> for SelectorState {
|
impl NavigatedPage<SelectorMessage> for SelectorState {
|
||||||
fn navigate(&self, message: &SelectorMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &SelectorMessage) -> Option<Page> {
|
||||||
if let SelectorMessage::Goto = message {
|
if let SelectorMessage::Goto = message {
|
||||||
return if self.is_writing {
|
return if self.is_writing {
|
||||||
let writing = WritingState::new(&self.set);
|
let writing = WritingState::new(&self.set);
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ pub struct SyncState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<SyncMessage> for SyncState {
|
impl NavigatedPage<SyncMessage> for SyncState {
|
||||||
fn navigate(&self, message: &SyncMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &SyncMessage) -> Option<Page> {
|
||||||
if let Back = message
|
if let Back = message
|
||||||
&& !self.frozen
|
&& !self.frozen
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ pub struct WordState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<WordMessage> for WordState {
|
impl NavigatedPage<WordMessage> for WordState {
|
||||||
fn navigate(&self, message: &WordMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &WordMessage) -> Option<Page> {
|
||||||
if let Back = message {
|
if let Back = message {
|
||||||
Some(PreviousPage)
|
Some(PreviousPage)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ pub struct WritingState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NavigatedPage<WritingMessage> for WritingState {
|
impl NavigatedPage<WritingMessage> for WritingState {
|
||||||
fn navigate(&self, message: &WritingMessage) -> Option<Page> {
|
fn navigate(&mut self, message: &WritingMessage) -> Option<Page> {
|
||||||
if let WritingMessage::Back = message {
|
if let WritingMessage::Back = message {
|
||||||
Some(PreviousPage)
|
Some(PreviousPage)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user