diff --git a/Cargo.lock b/Cargo.lock index d66281f..7a7de7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1557,7 +1557,9 @@ name = "postsack" version = "0.2.0" dependencies = [ "ps-core", + "ps-database", "ps-gui", + "ps-importer", ] [[package]] @@ -1608,8 +1610,10 @@ dependencies = [ "crossbeam-channel", "eyre", "flate2", + "getrandom", "lru", "once_cell", + "rand", "regex", "rsql_builder", "serde", diff --git a/postsack/Cargo.toml b/postsack/Cargo.toml index b52f906..ee3c190 100644 --- a/postsack/Cargo.toml +++ b/postsack/Cargo.toml @@ -19,9 +19,8 @@ osx_minimum_system_version = "10.14" [dependencies] ps-gui = { path = "../ps-gui" } ps-core = { path = "../ps-core" } - -[profile.dev] -split-debuginfo = "unpacked" +ps-importer = { path = "../ps-importer" } +ps-database = { path = "../ps-database" } #[profile.release] #lto = "fat" diff --git a/tests/resources/applemail/INBOX.mbox/1.emlx b/postsack/tests/resources/applemail/INBOX.mbox/1.emlx similarity index 100% rename from tests/resources/applemail/INBOX.mbox/1.emlx rename to postsack/tests/resources/applemail/INBOX.mbox/1.emlx diff --git a/tests/resources/applemail/INBOX.mbox/2.emlx b/postsack/tests/resources/applemail/INBOX.mbox/2.emlx similarity index 100% rename from tests/resources/applemail/INBOX.mbox/2.emlx rename to postsack/tests/resources/applemail/INBOX.mbox/2.emlx diff --git a/tests/resources/applemail/INBOX.mbox/3.emlx b/postsack/tests/resources/applemail/INBOX.mbox/3.emlx similarity index 100% rename from tests/resources/applemail/INBOX.mbox/3.emlx rename to postsack/tests/resources/applemail/INBOX.mbox/3.emlx diff --git a/tests/resources/applemail/INBOX.mbox/4.emlx b/postsack/tests/resources/applemail/INBOX.mbox/4.emlx similarity index 100% rename from tests/resources/applemail/INBOX.mbox/4.emlx rename to postsack/tests/resources/applemail/INBOX.mbox/4.emlx diff --git a/tests/resources/mbox/INBOX.mbox b/postsack/tests/resources/mbox/INBOX.mbox similarity index 100% rename from tests/resources/mbox/INBOX.mbox rename to postsack/tests/resources/mbox/INBOX.mbox diff --git a/tests/resources/mbox/SENT.mbox b/postsack/tests/resources/mbox/SENT.mbox similarity index 100% rename from tests/resources/mbox/SENT.mbox rename to postsack/tests/resources/mbox/SENT.mbox diff --git a/tests/resources/mbox/WORK.mbox b/postsack/tests/resources/mbox/WORK.mbox similarity index 100% rename from tests/resources/mbox/WORK.mbox rename to postsack/tests/resources/mbox/WORK.mbox diff --git a/tests/test_engine.rs b/postsack/tests/test_engine.rs similarity index 78% rename from tests/test_engine.rs rename to postsack/tests/test_engine.rs index a5b7814..91e6b81 100644 --- a/tests/test_engine.rs +++ b/postsack/tests/test_engine.rs @@ -1,12 +1,10 @@ -use eframe::egui; -use postsack::{ +use ps_core::{ self, - database::query::{Field, Filter, ValueField}, - importer::Importerlike, - model::{self, Engine}, - types::Config, - types::FormatType, + model::{self, Engine, Rect}, + Config, DatabaseLike, Field, Filter, FormatType, Importerlike, ValueField, }; +use ps_database::Database; +use ps_importer::mbox_importer; #[cfg(test)] mod tests { @@ -20,7 +18,7 @@ mod tests { if std::env::var("RUST_LOG").is_err() { std::env::set_var("RUST_LOG", "trace"); } - postsack::setup_tracing(); + ps_core::setup_tracing(); }); } @@ -28,7 +26,7 @@ mod tests { fn test_engine_all() { initialize(); let config = create_database(); - let mut engine = Engine::new(&config).expect("Expected Engine"); + let mut engine = Engine::new::(&config).expect("Expected Engine"); engine.start().expect("Expect to start engine"); engine.wait().expect("Expected working wait"); let segment = { @@ -85,19 +83,21 @@ mod tests { } } -fn default_rect() -> egui::Rect { - egui::Rect::from_min_size( - egui::Pos2 { x: 50.0, y: 50.0 }, - egui::Vec2 { x: 500.0, y: 500.0 }, - ) +fn default_rect() -> Rect { + Rect { + left: 50.0, + top: 50.0, + width: 500.0, + height: 500.0, + } } fn create_database() -> Config { let path = "tests/resources/mbox"; - let config = postsack::types::Config::new(None, path, vec!["".to_string()], FormatType::Mbox) - .expect("Config"); - let importer = postsack::importer::mbox_importer(config.clone()); - let (_receiver, handle) = importer.import().unwrap(); + let config = Config::new(None, path, vec!["".to_string()], FormatType::Mbox).expect("Config"); + let importer = mbox_importer(config.clone()); + let database = Database::new(&config.database_path).unwrap(); + let (_receiver, handle) = importer.import(database).unwrap(); handle.join().expect("").expect(""); config } diff --git a/tests/test_importer.rs b/postsack/tests/test_importer.rs similarity index 64% rename from tests/test_importer.rs rename to postsack/tests/test_importer.rs index 68b1759..ee0eda8 100644 --- a/tests/test_importer.rs +++ b/postsack/tests/test_importer.rs @@ -1,14 +1,10 @@ -use postsack::{ - self, - database::{query, Database}, - importer::Importerlike, - types::FormatType, -}; - +use ps_core::{self, DatabaseLike, FormatType, Importerlike}; +use ps_database::Database; +use ps_importer; #[cfg(test)] mod tests { - use postsack::database::{query::Field, query_result::QueryResult}; + use ps_core::{Config, Field, Query, QueryResult}; use std::sync::Once; use super::*; @@ -20,7 +16,7 @@ mod tests { if std::env::var("RUST_LOG").is_err() { std::env::set_var("RUST_LOG", "trace"); } - postsack::setup_tracing(); + ps_core::setup_tracing(); }); } @@ -30,20 +26,19 @@ mod tests { initialize(); let path = "tests/resources/mbox"; let config = - postsack::types::Config::new(None, path, vec!["".to_string()], FormatType::Mbox) - .expect("Config"); - let importer = postsack::importer::mbox_importer(config.clone()); - let (_receiver, handle) = importer.import().unwrap(); + Config::new(None, path, vec!["".to_string()], FormatType::Mbox).expect("Config"); + let importer = ps_importer::mbox_importer(config.clone()); + let database = Database::new(&config.database_path).unwrap(); + let (_receiver, handle) = importer.import(database).unwrap(); handle.join().expect("").expect(""); - // The temporary database path let db = Database::new(&config.database_path).unwrap(); let total_mails = db.total_mails().expect("Expected total mails"); assert_eq!(total_mails, 141); - let mails = db.query(&query::Query::Normal { - fields: vec![query::Field::Subject], + let mails = db.query(&Query::Normal { + fields: vec![Field::Subject], filters: Vec::new(), range: 0..141, }); @@ -69,15 +64,17 @@ mod tests { initialize(); let path = "tests/resources/applemail"; let config = - postsack::types::Config::new(None, path, vec!["".to_string()], FormatType::AppleMail) - .expect("Config"); - let importer = postsack::importer::applemail_importer(config.clone()); - let (_receiver, handle) = importer.import().unwrap(); + Config::new(None, path, vec!["".to_string()], FormatType::AppleMail).expect("Config"); + let importer = ps_importer::applemail_importer(config.clone()); + + let (_receiver, handle) = importer + .import(Database::new(&config.database_path).unwrap()) + .unwrap(); handle.join().expect("").expect(""); // The temporary database path let db = Database::new(&config.database_path).unwrap(); - let mails = db.query(&query::Query::Normal { - fields: vec![query::Field::Subject], + let mails = db.query(&Query::Normal { + fields: vec![Field::Subject], filters: Vec::new(), range: 0..10, }); diff --git a/ps-core/Cargo.toml b/ps-core/Cargo.toml index 818f9e2..d2a9e44 100644 --- a/ps-core/Cargo.toml +++ b/ps-core/Cargo.toml @@ -22,6 +22,12 @@ strum = "0.23.0" strum_macros = "0.23.0" lru = { version = "0.7.0", optional = true } shellexpand = "2.1.0" +rand = "0.8.4" + +[target."cfg(target_arch = \"wasm32\")".dependencies] +# https://docs.rs/getrandom/latest/getrandom/#webassembly-support +getrandom = { version = "0.2", features = ["js"] } + [features] default = ["lru"] diff --git a/ps-core/src/types/config.rs b/ps-core/src/types/config.rs index 46f59a8..804e8e1 100644 --- a/ps-core/src/types/config.rs +++ b/ps-core/src/types/config.rs @@ -8,7 +8,8 @@ use std::iter::FromIterator; use std::path::{Path, PathBuf}; use std::str::FromStr; -// use super::ImporterFormatType; +// FIXME: This abstraction should be in the `ps-importer` crate with only +// a protocol here. #[derive(Debug, Clone, Copy, PartialEq, Eq, IntoStaticStr, EnumIter)] pub enum FormatType { @@ -29,17 +30,6 @@ impl FormatType { FormatType::Mbox => "Mbox", } } - - /// Forward the importer format location - pub fn default_path(&self) -> Option { - todo!() - // use crate::importer::formats::{self, ImporterFormat}; - // match self { - // FormatType::AppleMail => formats::AppleMail::default_path(), - // FormatType::GmailVault => formats::Gmail::default_path(), - // FormatType::Mbox => formats::Mbox::default_path(), - // } - } } impl Default for FormatType { @@ -154,7 +144,7 @@ impl Config { let database_path = match db { Some(n) => n.as_ref().to_path_buf(), None => { - let number = timestamp(); + let number = random_filename(); let folder = "postsack"; let filename = format!("{}.sqlite", number); let mut temp_dir = std::env::temp_dir(); @@ -201,11 +191,10 @@ impl Config { } } -fn timestamp() -> u32 { - use std::time::{SystemTime, UNIX_EPOCH}; - let start = SystemTime::now(); - let since_the_epoch = start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); - since_the_epoch.as_millis() as u32 +fn random_filename() -> String { + use rand::Rng; + let number: u32 = rand::thread_rng().gen(); + let folder = "postsack"; + let filename = format!("{}.sqlite", number); + return filename; } diff --git a/ps-gui/src/app_state/startup.rs b/ps-gui/src/app_state/startup.rs index d1d00bf..4af4b82 100644 --- a/ps-gui/src/app_state/startup.rs +++ b/ps-gui/src/app_state/startup.rs @@ -155,7 +155,7 @@ impl StartupUI { self.open_email_folder_dialog() } if self.format == FormatType::AppleMail && ui.button("or Mail.app default folder").clicked(){ - self.email_folder = self.format.default_path(); + self.email_folder = ps_importer::default_path(&self.format); } }); ui.end_row(); @@ -302,9 +302,7 @@ impl StartupUI { fn open_email_folder_dialog(&mut self) { let fallback = shellexpand::tilde("~/"); - let default_path = self - .format - .default_path() + let default_path = ps_importer::default_path(&self.format) .unwrap_or_else(|| std::path::Path::new(&fallback.to_string()).to_path_buf()); let folder = match tinyfiledialogs::select_folder_dialog( diff --git a/ps-importer/src/lib.rs b/ps-importer/src/lib.rs index 8ef67f3..6088394 100644 --- a/ps-importer/src/lib.rs +++ b/ps-importer/src/lib.rs @@ -4,10 +4,11 @@ pub(crate) mod formats; use formats::{shared, ImporterFormat}; -use std::thread::JoinHandle; +use std::{path::PathBuf, thread::JoinHandle}; use ps_core::{ - crossbeam_channel::unbounded, Config, DatabaseLike, Importerlike, Message, MessageReceiver, + crossbeam_channel::unbounded, Config, DatabaseLike, FormatType, Importerlike, Message, + MessageReceiver, }; pub struct Importer { @@ -65,3 +66,11 @@ pub fn applemail_importer(config: Config) -> Importer { pub fn mbox_importer(config: Config) -> Importer { Importer::new(config, formats::Mbox::default()) } + +pub fn default_path(format: &FormatType) -> Option { + match format { + FormatType::AppleMail => formats::AppleMail::default_path(), + FormatType::GmailVault => formats::Gmail::default_path(), + FormatType::Mbox => formats::Mbox::default_path(), + } +}