diff --git a/src/core/deck.rs b/src/core/deck.rs index a0fbd05..03e0c76 100644 --- a/src/core/deck.rs +++ b/src/core/deck.rs @@ -6,7 +6,7 @@ use crate::core::srs::{ use crate::data::entities::*; use crate::data_provider::card_stats::{load_stats_of_deck, update_stat_score}; use crate::data_provider::history::push_note; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use chrono::Utc; use parking_lot::Mutex; use std::sync::Arc; @@ -88,7 +88,7 @@ impl DeckData { self.current_word_index = Some(index); (self.words[index].clone(), self.set[index].clone()) } - pub fn open(&mut self, status: WordOpenMode) -> Result<(), NotificationData> { + pub fn open(&mut self, status: WordOpenMode) -> MaybeError { if let Some(index) = self.current_word_index { let word: &mut CardStatistics = &mut self.set[index]; let old_score = word.score; diff --git a/src/data_provider/card_sets.rs b/src/data_provider/card_sets.rs index b4bb18a..4e836b4 100644 --- a/src/data_provider/card_sets.rs +++ b/src/data_provider/card_sets.rs @@ -2,7 +2,7 @@ use crate::core::srs::OrderMode; use crate::data::entities::DeckSettings; use rusqlite::Connection; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::notification::NotificationData::{DbLoadError, DbSaveError}; pub fn load_sets(connection: &Connection) -> Result, NotificationData> { @@ -28,7 +28,7 @@ pub fn load_sets(connection: &Connection) -> Result, Notificat Ok(buffer) } -pub fn add_set(set: &mut DeckSettings, connection: &Connection) -> Result<(), NotificationData> { +pub fn add_set(set: &mut DeckSettings, connection: &Connection) -> MaybeError { let index : u32 = connection .query_row( "INSERT INTO card_set (name, forward, backward, filter) VALUES (?1, ?2, ?3, ?4) RETURNING id", @@ -46,7 +46,7 @@ pub fn add_set(set: &mut DeckSettings, connection: &Connection) -> Result<(), No Ok(()) } -pub fn update_deck(set: &mut DeckSettings, connection: &Connection) -> Result<(), NotificationData> { +pub fn update_deck(set: &mut DeckSettings, connection: &Connection) -> MaybeError { if !set.id.is_valid() { add_set(set, connection)?; } else { @@ -66,7 +66,7 @@ pub fn update_deck(set: &mut DeckSettings, connection: &Connection) -> Result<() Ok(()) } -pub fn delete_set(set: &DeckSettings, connection: &Connection) -> Result<(), NotificationData> { +pub fn delete_set(set: &DeckSettings, connection: &Connection) -> MaybeError { if !set.id.is_valid() { return Err(DbSaveError); } diff --git a/src/data_provider/card_stats.rs b/src/data_provider/card_stats.rs index 95cf49d..22dff12 100644 --- a/src/data_provider/card_stats.rs +++ b/src/data_provider/card_stats.rs @@ -1,5 +1,5 @@ use crate::data::entities::{CardStatistics, DeckSettings}; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::notification::NotificationData::{DbLoadError, DbSaveError}; use log::info; use rusqlite::{Connection, params}; @@ -30,7 +30,7 @@ pub fn load_stats_of_deck( Ok(buffer) } -pub fn add_stat_list(stats: &mut [CardStatistics], connection: &mut Connection) -> Result<(), NotificationData> { +pub fn add_stat_list(stats: &mut [CardStatistics], connection: &mut Connection) -> MaybeError { let time = Instant::now(); let tx = connection.transaction().expect("Failed to create transaction"); let count = stats.len(); @@ -66,7 +66,7 @@ pub fn add_stat_list(stats: &mut [CardStatistics], connection: &mut Connection) Ok(()) } -pub fn update_stat_score(stat: &CardStatistics, connection: &Connection) -> Result<(), NotificationData> { +pub fn update_stat_score(stat: &CardStatistics, connection: &Connection) -> MaybeError { let time = Instant::now(); connection @@ -79,7 +79,7 @@ pub fn update_stat_score(stat: &CardStatistics, connection: &Connection) -> Resu Ok(()) } -pub fn delete_stats(stat: &[CardStatistics], connection: &Connection) -> Result<(), NotificationData> { +pub fn delete_stats(stat: &[CardStatistics], connection: &Connection) -> MaybeError { if stat.is_empty() { return Ok(()); } diff --git a/src/data_provider/history.rs b/src/data_provider/history.rs index aa92149..085c1fe 100644 --- a/src/data_provider/history.rs +++ b/src/data_provider/history.rs @@ -2,7 +2,7 @@ use crate::core::srs::WordOpenMode; use crate::data::Id; use crate::data::entities::HistoryItem; use crate::fs::*; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::notification::NotificationData::PermissionDenied; use chrono::DateTime; use std::fs::{File, OpenOptions}; @@ -20,7 +20,7 @@ pub fn get_history_of_set(id: Id) -> Result, NotificationData> Ok(parse_history_items(lines)) } -fn append_lines_if_exists(path: PathBuf, lines: &mut Vec) -> Result<(), NotificationData> { +fn append_lines_if_exists(path: PathBuf, lines: &mut Vec) -> MaybeError { if path.exists() { let reader = BufReader::new(File::open(path).map_err(|_| PermissionDenied)?); reader @@ -63,7 +63,7 @@ fn parse_history_items(strings: Vec) -> Vec { items } -pub fn push_note(set_id: Id, item: HistoryItem) -> Result<(), NotificationData> { +pub fn push_note(set_id: Id, item: HistoryItem) -> MaybeError { let app_dir = history_dir()?; let path = app_dir.clone().join(format!("set_{}_history.csv", set_id)); diff --git a/src/data_provider/import.rs b/src/data_provider/import.rs index b46d8a9..da4eae5 100644 --- a/src/data_provider/import.rs +++ b/src/data_provider/import.rs @@ -3,6 +3,8 @@ use hashbrown::HashMap; use log::info; use rusqlite::Connection; use serde_json::Value; +use crate::helpers::into_result; +use crate::notification::NotificationData::IncorrectAnkiFile; #[derive(Clone)] pub struct ImportData(pub(crate) Vec); @@ -26,41 +28,40 @@ pub struct ImportNote { pub fn load_groups(connection: &Connection) -> Result { let json_models: String = connection .query_one("select models from col", (), |row| row.get(0)) - .map_err(|_| NotificationData::IncorrectAnkiFile)?; + .map_err(|_| IncorrectAnkiFile)?; let raw: Value = serde_json::from_str(json_models.as_str()) - .map_err(|_| NotificationData::IncorrectAnkiFile)?; + .map_err(|_| IncorrectAnkiFile)?; let sets = raw.as_object(); if let Some(sets) = sets { let mut total_data = ImportData(vec![]); let mut count_stmt = connection .prepare("select mid, count(id) from notes group by mid") - .map_err(|_| NotificationData::IncorrectAnkiFile)?; + .map_err(|_| IncorrectAnkiFile)?; let counts = count_stmt .query_map([], |row| Ok((row.get(0)?, row.get(1)?))) - .map_err(|_| NotificationData::IncorrectAnkiFile)? + .map_err(|_| IncorrectAnkiFile)? .filter_map(|x| x.ok()) .collect::>(); for (_, collection) in sets { let fields_property = collection.get("fields"); if let Some(fields_property) = fields_property { - let fields = fields_property - .as_array() - .unwrap() + let fields = into_result(fields_property + .as_array(), IncorrectAnkiFile)? .iter() .filter_map(|x| x.get("name")) .map(|x| x.as_str().unwrap().to_string()) .collect(); let id = collection.get("id"); if id.is_none() || id.unwrap().as_u64().is_none(){ - return Err(NotificationData::IncorrectAnkiFile); + return Err(IncorrectAnkiFile); } let id = id.unwrap().as_u64().unwrap(); let name = collection.get("name"); if name.is_none() || name.unwrap().as_str().is_none() { - return Err(NotificationData::IncorrectAnkiFile); + return Err(IncorrectAnkiFile); } let name = name.unwrap().as_str().unwrap().to_string(); @@ -81,13 +82,13 @@ pub fn load_groups(connection: &Connection) -> Result Result, NotificationData> { let mut count_stmt = connection .prepare("select tags, flds from notes where mid == ?1;") - .map_err(|_| NotificationData::IncorrectAnkiFile)?; + .map_err(|_| IncorrectAnkiFile)?; Ok(count_stmt .query_map((group_id as i64,), |row| { @@ -100,7 +101,7 @@ pub fn get_words_of_group(connection: &Connection, group_id: u64) -> Result>()) } diff --git a/src/data_provider/settings.rs b/src/data_provider/settings.rs index 5d7a5ea..dce970d 100644 --- a/src/data_provider/settings.rs +++ b/src/data_provider/settings.rs @@ -1,4 +1,4 @@ -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::notification::NotificationData::{DbLoadError, DbSaveError}; use iced::futures::StreamExt; use rusqlite::Connection; @@ -22,7 +22,7 @@ pub fn set_setting( key: String, value: String, connection: &Connection, -) -> Result<(), NotificationData> { +) -> MaybeError { let current = get_settings_list(connection)?; if current.contains(&key) { update_settings(key, value, connection)?; @@ -33,7 +33,7 @@ pub fn set_setting( Ok(()) } -pub fn delete_settings(key: String, connection: &Connection) -> Result<(), NotificationData> { +pub fn delete_settings(key: String, connection: &Connection) -> MaybeError { connection .execute("DELETE FROM settings WHERE id = ?1", (&key,)) .map_err(|_| DbSaveError)?; @@ -44,7 +44,7 @@ fn create_settings( key: String, value: String, connection: &Connection, -) -> Result<(), NotificationData> { +) -> MaybeError { connection .execute( "INSERT into settings (id, value) VALUES (?1, ?2)", @@ -58,7 +58,7 @@ fn update_settings( key: String, value: String, connection: &Connection, -) -> Result<(), NotificationData> { +) -> MaybeError { connection .execute( "update settings diff --git a/src/data_provider/sqlite.rs b/src/data_provider/sqlite.rs index 0abf6a2..0843d6f 100644 --- a/src/data_provider/sqlite.rs +++ b/src/data_provider/sqlite.rs @@ -5,19 +5,19 @@ pub fn create_db() { let db_file = db_path(); if !db_file.exists() { std::fs::File::create(&db_file).expect("Database file creation failed"); - let connection = Connection::open(&db_file).unwrap(); - connection.execute("PRAGMA foreign_keys = ON;", []).unwrap(); + let connection = Connection::open(&db_file).expect("Connection open failed"); + connection.execute("PRAGMA foreign_keys = ON;", []).expect("Failed to set PRAGMA"); create_tables(&connection); } } fn create_tables(conn: &Connection) { - make_card_set(conn).unwrap(); - make_settings(conn).unwrap(); - make_word_group(conn).unwrap(); - make_words(conn).unwrap(); - make_card_stats(conn).unwrap(); + make_card_set(conn).expect("Failed to init table"); + make_settings(conn).expect("Failed to init table"); + make_word_group(conn).expect("Failed to init table"); + make_words(conn).expect("Failed to init table"); + make_card_stats(conn).expect("Failed to init table"); } fn make_settings(conn: &Connection) -> Result<(), rusqlite::Error> { @@ -51,7 +51,7 @@ fn make_card_stats(conn: &Connection) -> Result<(), rusqlite::Error> { pub fn default_connection() -> Connection { let db_file = db_path(); - let connection = Connection::open(db_file).unwrap(); - connection.execute("PRAGMA foreign_keys = ON;", []).unwrap(); + let connection = Connection::open(db_file).expect("Failed to open database"); + connection.execute("PRAGMA foreign_keys = ON;", []).expect("Failed to set PRAGMA"); connection } diff --git a/src/data_provider/web_api.rs b/src/data_provider/web_api.rs index 01d08f4..24f3dec 100644 --- a/src/data_provider/web_api.rs +++ b/src/data_provider/web_api.rs @@ -1,18 +1,20 @@ -use std::io; +use crate::fs::*; +use crate::notification::NotificationData::{CompressError, PermissionDenied, WebApiUnavailable}; +use crate::notification::{MaybeError, NotificationData}; use log::info; +use std::io; use tokio::fs::{File, OpenOptions}; use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use zstd::{DEFAULT_COMPRESSION_LEVEL, Decoder, Encoder}; -use crate::fs::*; -use crate::notification::NotificationData; -use crate::notification::NotificationData::{CompressError, PermissionDenied, WebApiUnavailable}; +use zstd::{Decoder, Encoder, DEFAULT_COMPRESSION_LEVEL}; // const API_URL: &str = "http://127.0.0.1:8089/"; const API_URL: &str = "https://learning.micialware.ru/"; -pub async fn send_data(id: String) -> Result<(), NotificationData> { +pub async fn send_data(id: String) -> MaybeError { let db_file = db_path(); - let data = tokio::fs::read(db_file).await.map_err(|_| WebApiUnavailable)?; + let data = tokio::fs::read(db_file) + .await + .map_err(|_| WebApiUnavailable)?; let data = compress(data)?; let api_url = API_URL.to_string(); @@ -23,30 +25,35 @@ pub async fn send_data(id: String) -> Result<(), NotificationData> { .post(&id_url) .body(data) .send() - .await.map_err(|_| WebApiUnavailable)? + .await + .map_err(|_| WebApiUnavailable)? .text() - .await.map_err(|_| WebApiUnavailable)?; + .await + .map_err(|_| WebApiUnavailable)?; set_local_version(new_version.parse::().unwrap_or_default()).await; Ok(()) } fn compress(data: Vec) -> Result, NotificationData> { - let mut encoder = Encoder::new(Vec::new(), DEFAULT_COMPRESSION_LEVEL).map_err(|_| CompressError)?; + let mut encoder = + Encoder::new(Vec::new(), DEFAULT_COMPRESSION_LEVEL).map_err(|_| CompressError)?; io::copy(&mut &data[..], &mut encoder).map_err(|_| PermissionDenied)?; encoder.finish().map_err(|_| CompressError)?; Ok(data) } -pub async fn load_data(id: String, temp: bool) -> Result<(), NotificationData> { +pub async fn load_data(id: String, temp: bool) -> MaybeError { let api_url = API_URL.to_string(); let id_url = format!("{api_url}download/{id}"); let client = reqwest::Client::new(); let data = client .get(&id_url) .send() - .await.map_err(|_| WebApiUnavailable)? + .await + .map_err(|_| WebApiUnavailable)? .bytes() - .await.map_err(|_| WebApiUnavailable)? + .await + .map_err(|_| WebApiUnavailable)? .to_vec(); let data = decompress(data)?; @@ -54,15 +61,19 @@ pub async fn load_data(id: String, temp: bool) -> Result<(), NotificationData> { let file_name = if temp { "data.db.tmp" } else { "data.db" }; let db_file = path.join(file_name); - tokio::fs::write(db_file, data).await.map_err(|_| PermissionDenied)?; + tokio::fs::write(db_file, data) + .await + .map_err(|_| PermissionDenied)?; let version_url = format!("{API_URL}{id}/version"); let version = client .get(&version_url) .send() - .await.map_err(|_| WebApiUnavailable)? + .await + .map_err(|_| WebApiUnavailable)? .text() - .await.map_err(|_| WebApiUnavailable)?; + .await + .map_err(|_| WebApiUnavailable)?; set_local_version(version.parse::().unwrap_or_default()).await; Ok(()) } @@ -93,22 +104,29 @@ pub async fn first_sync() -> Result { pub async fn get_web_version(key: &str) -> Result { let id_url = format!("{API_URL}{key}/version"); let client = reqwest::Client::new(); - let version = client.get(&id_url).send().await.map_err(|_| WebApiUnavailable)?.text().await.map_err(|_| WebApiUnavailable)?; + let version = client + .get(&id_url) + .send() + .await + .map_err(|_| WebApiUnavailable)? + .text() + .await + .map_err(|_| WebApiUnavailable)?; info!("version: {}", version); Ok(version.parse::().unwrap_or_default()) } -pub async fn get_local_version() -> u32 { +pub async fn get_local_version() -> Result { let file = db_meta_path(); if file.exists() { let mut data = String::new(); File::open(file.clone()) .await - .unwrap() + .map_err(|_| PermissionDenied)? .read_to_string(&mut data) .await - .unwrap(); - return data.parse::().unwrap_or_default(); + .map_err(|_| PermissionDenied)?; + return Ok(data.parse::().unwrap_or_default()); } let mut file = OpenOptions::new() @@ -117,12 +135,14 @@ pub async fn get_local_version() -> u32 { .truncate(true) .open(file) .await - .unwrap(); - file.write_all("0".as_bytes()).await.unwrap(); - 0 + .map_err(|_| PermissionDenied)?; + file.write_all("0".as_bytes()) + .await + .map_err(|_| PermissionDenied)?; + Ok(0) } -pub async fn set_local_version(version: u32) { +pub async fn set_local_version(version: u32) -> Result<(), NotificationData> { let file_path = db_meta_path(); let mut file = OpenOptions::new() .write(true) @@ -130,8 +150,9 @@ pub async fn set_local_version(version: u32) { .truncate(true) .open(file_path) .await - .unwrap(); + .map_err(|_| PermissionDenied)?; file.write_all(version.to_string().as_bytes()) .await - .unwrap(); + .map_err(|_| PermissionDenied)?; + Ok(()) } diff --git a/src/data_provider/words.rs b/src/data_provider/words.rs index 178cfb6..9c49b6c 100644 --- a/src/data_provider/words.rs +++ b/src/data_provider/words.rs @@ -1,10 +1,10 @@ use crate::data::entities::{WordData, WordGroup}; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::notification::NotificationData::{DbLoadError, DbSaveError}; use rusqlite::{Connection, params}; use std::collections::HashMap; -pub fn add_word(word: &mut WordData, connection: &Connection) -> Result<(), NotificationData> { +pub fn add_word(word: &mut WordData, connection: &Connection) -> MaybeError { let index : u32 = connection .query_row( "INSERT INTO words (key, value, tags, more, group_id) VALUES (?1, ?2, ?3, ?4, ?5) RETURNING id", @@ -25,7 +25,7 @@ pub fn add_word(word: &mut WordData, connection: &Connection) -> Result<(), Noti pub fn add_words( words: &mut [WordData], connection: &mut Connection, -) -> Result<(), NotificationData> { +) -> MaybeError { let tx = connection.transaction().map_err(|_| DbLoadError)?; let count = words.len(); @@ -60,7 +60,7 @@ pub fn add_words( Ok(()) } -pub fn update_word(word: &mut WordData, connection: &Connection) -> Result<(), NotificationData> { +pub fn update_word(word: &mut WordData, connection: &Connection) -> MaybeError { if !word.id.is_valid() { Ok(add_word(word, connection)?) } else { @@ -71,7 +71,7 @@ pub fn update_word(word: &mut WordData, connection: &Connection) -> Result<(), N &word.key, &word.value, &word.tags, - serde_json::to_string(&word.additional).unwrap(), + serde_json::to_string(&word.additional).map_err(|_| DbSaveError)?, &word.id, ), ) @@ -80,7 +80,7 @@ pub fn update_word(word: &mut WordData, connection: &Connection) -> Result<(), N } } -pub fn delete_word(word: &WordData, connection: &Connection) -> Result<(), NotificationData> { +pub fn delete_word(word: &WordData, connection: &Connection) -> MaybeError { if !word.id.is_valid() { return Err(DbSaveError); } @@ -133,7 +133,7 @@ pub fn load_word_groups(connection: &Connection) -> Result, Notif Ok(buffer) } -pub fn add_group(group: &mut WordGroup, connection: &Connection) -> Result<(), NotificationData> { +pub fn add_group(group: &mut WordGroup, connection: &Connection) -> MaybeError { let index: u32 = connection .query_row( "INSERT INTO word_group (name) VALUES (?1) RETURNING id", @@ -149,7 +149,7 @@ pub fn add_group(group: &mut WordGroup, connection: &Connection) -> Result<(), N pub fn update_group( group: &mut WordGroup, connection: &Connection, -) -> Result<(), NotificationData> { +) -> MaybeError { if !group.id.is_valid() { Ok(add_group(group, connection)?) } else { @@ -163,7 +163,7 @@ pub fn update_group( } } -pub fn delete_group(group: &WordGroup, connection: &Connection) -> Result<(), NotificationData> { +pub fn delete_group(group: &WordGroup, connection: &Connection) -> MaybeError { if !group.id.is_valid() { return Err(DbSaveError); } diff --git a/src/helpers.rs b/src/helpers.rs index b8536f5..25a02c7 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -10,4 +10,14 @@ macro_rules! push_error { ($e:expr) => { $crate::navigation::RootMessage::PushNotification($crate::notification::NotificationRequest::Error($e)) } +} + +#[inline(always)] +pub fn into_result(option: Option, error: E) -> Result{ + if let Some(r) = option { + Ok(r) + } + else { + Err(error) + } } \ No newline at end of file diff --git a/src/navigation.rs b/src/navigation.rs index 6dbd736..35c4c1b 100644 --- a/src/navigation.rs +++ b/src/navigation.rs @@ -172,7 +172,7 @@ impl ScreenState { } async fn load_web_backup(string: String) -> Result { - let local = get_local_version().await; + let local = get_local_version().await?; let web = get_web_version(string.as_str()).await?; info!("{} {}", local, web); if web > local { diff --git a/src/notification.rs b/src/notification.rs index 35be9cb..2336fc0 100644 --- a/src/notification.rs +++ b/src/notification.rs @@ -192,3 +192,5 @@ pub enum NotificationData { DbLoadError, CompressError, } + +pub type MaybeError = Result<(), NotificationData>; \ No newline at end of file diff --git a/src/pages/import.rs b/src/pages/import.rs index 91fbb93..7f2302d 100644 --- a/src/pages/import.rs +++ b/src/pages/import.rs @@ -4,7 +4,7 @@ use crate::pages::import::ImportMessage::*; use crate::data::entities::{WordData, WordGroup}; use crate::navigation::{NavigatedPage, Page, RootMessage}; use crate::notification::NotificationData::OpenFileError; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::styling::*; use iced::widget::button::danger; use iced::widget::container::success; @@ -373,7 +373,7 @@ impl ImportState { ) } - fn extract_import_file(path: PathBuf) -> Result<(), NotificationData> { + fn extract_import_file(path: PathBuf) -> MaybeError { let file = File::open(path).map_err(|_| OpenFileError)?; let reader = BufReader::new(file); let mut archive = ZipArchive::new(reader).map_err(|_| OpenFileError)?; diff --git a/src/pages/repetition.rs b/src/pages/repetition.rs index 868d875..b38e739 100644 --- a/src/pages/repetition.rs +++ b/src/pages/repetition.rs @@ -6,7 +6,7 @@ use crate::data::entities::{CardStatistics, DeckSettings, WordData}; use crate::data_provider::voice::get_voice; use crate::navigation::Page::PreviousPage; use crate::navigation::{KeyPressedPage, NavigatedPage, Page, RootMessage}; -use crate::notification::NotificationData; +use crate::notification::{MaybeError, NotificationData}; use crate::styling::*; use crate::{push_error, push_error_task}; use chrono::Local; @@ -337,7 +337,7 @@ pub enum RepetitionMessage { async fn play_sound( sink: Arc>, text: String, -) -> Result<(), NotificationData> { +) -> MaybeError { let data = get_voice(text.as_str()).await?; spawn_blocking(move || { if let Some(sink) = sink.as_ref() @@ -347,6 +347,6 @@ async fn play_sound( } }) .await - .unwrap(); + .expect("Playing sound failed"); Ok(()) } diff --git a/src/pages/repetition_settings.rs b/src/pages/repetition_settings.rs index 139f607..3e52d83 100644 --- a/src/pages/repetition_settings.rs +++ b/src/pages/repetition_settings.rs @@ -4,7 +4,7 @@ use crate::data_provider::card_sets::{delete_set, update_deck}; use crate::data_provider::card_stats::{delete_stats, load_stats_of_deck}; use crate::navigation::Page::PreviousPage; use crate::navigation::{NavigatedPage, Page, RootMessage}; -use crate::notification::NotificationData; +use crate::notification::MaybeError; use crate::pages::repetition_settings::RepetitionSettingsMessage::*; use crate::styling::*; use crate::{push_error, push_error_task}; @@ -13,7 +13,7 @@ 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; @@ -179,7 +179,7 @@ impl NavigatedPage for RepetitionSettingsState { } } -fn update_deck_stats(deck: &DeckSettings, state: &AppState) -> Result<(), NotificationData> { +fn update_deck_stats(deck: &DeckSettings, state: &AppState) -> MaybeError { let mut db_stats = load_stats_of_deck(deck, &state.connection).expect("Wrong db operation"); let filtered_words = deck.get_word_list(state); filtered_words.iter().for_each(|word| { diff --git a/src/pages/repetitions.rs b/src/pages/repetitions.rs index 50b5018..76e655f 100644 --- a/src/pages/repetitions.rs +++ b/src/pages/repetitions.rs @@ -1,12 +1,12 @@ use crate::app::AppState; use crate::core::srs::{AppendMode, OrderMode}; -use crate::data::Id; use crate::data::entities::{CardStatistics, DeckSettings}; +use crate::data::Id; use crate::data_provider::card_sets::update_deck; use crate::data_provider::card_stats::{add_stat_list, load_stats_of_deck}; use crate::navigation::Page::{History, PreviousPage, Repetition, RepetitionSettings}; use crate::navigation::{NavigatedPage, Page, RootMessage}; -use crate::notification::{NotificationData, NotificationRequest}; +use crate::notification::{MaybeError, NotificationRequest}; use crate::pages::history::HistoryState; use crate::pages::repetition::RepetitionState; use crate::pages::repetition_settings::RepetitionSettingsState; @@ -16,17 +16,17 @@ use crate::push_error_task; use crate::styling::*; use chrono::{Days, Local, Utc}; use hashbrown::{HashMap, HashSet}; +use iced::widget::button::{danger, Status}; pub use iced::widget::button::{Catalog, Style}; -use iced::widget::button::{Status, danger}; use iced::widget::tooltip::Position::Top; use iced::widget::{ - Column, Row, button, column, container, lazy, radio, row, scrollable, space, svg, text, - text_input, tooltip, + button, column, container, lazy, radio, row, scrollable, space, svg, text, text_input, tooltip, + Column, Row, }; use iced::{Background, Border, Center, Color, Element, Fill, Length, Shadow, Task, Theme}; -use iced_core::Padding; use iced_core::border::Radius; use iced_core::svg::Handle; +use iced_core::Padding; use parking_lot::Mutex; use std::ops::Deref; use std::sync::Arc; @@ -562,7 +562,7 @@ impl RepetitionsState { } impl RepetitionsState { - fn append_all_words(state: &mut AppState, deck: &DeckViewData) -> Result<(), NotificationData> { + fn append_all_words(state: &mut AppState, deck: &DeckViewData) -> MaybeError { let existing = &deck.existing_words_indices; let mut created_set = HashSet::with_capacity(existing.len()); existing.iter().for_each(|c| { @@ -580,7 +580,7 @@ impl RepetitionsState { state: &mut AppState, deck: &DeckSettings, indices: impl Iterator, - ) -> Result<(), NotificationData> { + ) -> MaybeError { let words = &state.dictionary; let stats = &mut indices .map(|i| { @@ -618,7 +618,7 @@ impl RepetitionsState { self.selected_deck_index = None; } - fn fill_deck_word_indices(&mut self) -> Result<(), NotificationData> { + fn fill_deck_word_indices(&mut self) -> MaybeError { let state = &self.state.lock(); let mut deck = self.selected_deck().unwrap().clone(); let added: Vec<_> = load_stats_of_deck(&deck, &state.connection)?