diff --git a/Cargo.lock b/Cargo.lock index 7ced088..34a76dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,23 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" +[[package]] +name = "ahash" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" + +[[package]] +name = "ahash" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796540673305a66d127804eef19ad696f1f204b8c1025aaca4958c17eab32877" +dependencies = [ + "getrandom 0.2.2", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.15" @@ -42,7 +59,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d308d8fa3f687f7a7588fccc4812ed6914be09518232f00454693a7417273ad2" dependencies = [ - "static_assertions", + "static_assertions 0.3.4", ] [[package]] @@ -103,6 +120,15 @@ dependencies = [ "syn 1.0.64", ] +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] + [[package]] name = "atty" version = "0.2.14" @@ -162,6 +188,18 @@ dependencies = [ "typenum", ] +[[package]] +name = "bitvec" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2b_simd" version = "0.5.11" @@ -197,6 +235,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" + [[package]] name = "bumpalo" version = "3.6.1" @@ -472,6 +516,15 @@ dependencies = [ "url", ] +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -481,6 +534,26 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.3", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.3", +] + [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -700,6 +773,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "downcast-rs" version = "1.2.0" @@ -864,6 +943,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e04cda45add94e71c2990de778ae13059897d77b773130a9bc225e2970c413e" +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures" version = "0.1.31" @@ -1249,7 +1334,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" dependencies = [ - "ahash", + "ahash 0.3.8", "autocfg", ] @@ -1258,6 +1343,18 @@ name = "hashbrown" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash 0.4.7", +] + +[[package]] +name = "hashlink" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d99cf782f0dc4372d26846bec3de7804ceb5df083c2d4462c0b8d2330e894fa8" +dependencies = [ + "hashbrown 0.9.1", +] [[package]] name = "heck" @@ -1480,6 +1577,19 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lexical-core" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374" +dependencies = [ + "arrayvec", + "bitflags 1.2.1", + "cfg-if 1.0.0", + "ryu", + "static_assertions 1.1.0", +] + [[package]] name = "libc" version = "0.2.90" @@ -1510,6 +1620,17 @@ dependencies = [ "libc", ] +[[package]] +name = "libsqlite3-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "libssh2-sys" version = "0.2.21" @@ -1655,6 +1776,19 @@ dependencies = [ "void", ] +[[package]] +name = "nom" +version = "6.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" +dependencies = [ + "bitvec", + "funty", + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "notify-rust" version = "4.3.0" @@ -1828,6 +1962,7 @@ dependencies = [ "parking_lot", "quoted_printable", "serde", + "sqlx", "structopt", "tokio 1.3.0", "tokio-rustls", @@ -2108,6 +2243,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b080c5db639b292ac79cbd34be0cfc5d36694768d8341109634d90b86930e2" +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "rand" version = "0.7.3" @@ -2459,6 +2600,19 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" +dependencies = [ + "block-buffer", + "cfg-if 1.0.0", + "cpuid-bool", + "digest", + "opaque-debug", +] + [[package]] name = "shell-escape" version = "0.1.5" @@ -2530,12 +2684,114 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "sqlformat" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d86e3c77ff882a828346ba401a7ef4b8e440df804491c6064fe8295765de71c" +dependencies = [ + "lazy_static", + "maplit", + "nom", + "regex", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2739d54a2ae9fdd0f545cb4e4b5574efb95e2ec71b7f921678e246fb20dcaaf" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1cad9cae4ca8947eba1a90e8ec7d3c59e7a768e2f120dc9013b669c34a90711" +dependencies = [ + "ahash 0.6.3", + "atoi", + "bitflags 1.2.1", + "byteorder", + "bytes 1.0.1", + "crc", + "crossbeam-channel", + "crossbeam-queue", + "crossbeam-utils 0.8.3", + "either", + "futures-channel", + "futures-core", + "futures-util", + "hashlink", + "hex 0.4.3", + "itoa", + "libc", + "libsqlite3-sys", + "log", + "memchr", + "once_cell", + "parking_lot", + "percent-encoding", + "rustls", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki", + "webpki-roots", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01caee2b3935b4efe152f3262afbe51546ce3b1fc27ad61014e1b3cf5f55366e" +dependencies = [ + "dotenv", + "either", + "futures 0.3.13", + "heck", + "proc-macro2", + "quote 1.0.9", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn 1.0.64", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ce2e16b6774c671cc183e1d202386fdf9cde1e8468c1894a7f2a63eb671c4f4" +dependencies = [ + "once_cell", + "tokio 1.3.0", + "tokio-rustls", +] + [[package]] name = "static_assertions" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.1" @@ -2548,6 +2804,16 @@ dependencies = [ "precomputed-hash", ] +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "strip-ansi-escapes" version = "0.1.0" @@ -2646,6 +2912,12 @@ dependencies = [ "unicode-xid 0.0.4", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tar" version = "0.4.33" @@ -2699,6 +2971,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote 1.0.9", + "syn 1.0.64", +] + [[package]] name = "thread_local" version = "1.1.3" @@ -2908,6 +3200,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "untrusted" version = "0.7.1" @@ -3092,6 +3390,16 @@ dependencies = [ "cc", ] +[[package]] +name = "whoami" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e296f550993cba2c5c3eba5da0fb335562b2fa3d97b7a8ac9dc91f40a3abc70" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3145,6 +3453,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "xdg" version = "2.2.0" diff --git a/Cargo.toml b/Cargo.toml index 3083462..7b402a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,6 +41,7 @@ webpki-roots = "0.21.0" xdg = "2.2.0" downcast-rs = "1.2.0" quoted_printable = "0.4.2" +sqlx = { version = "0.5.1", features = ["runtime-tokio-rustls", "sqlite"] } [dependencies.panorama-imap] path = "imap" diff --git a/src/lib.rs b/src/lib.rs index 53b23fd..dd275d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,8 @@ extern crate format_bytes; #[macro_use] extern crate serde; #[macro_use] +extern crate sqlx; +#[macro_use] extern crate log; pub mod config; diff --git a/src/mail/mod.rs b/src/mail/mod.rs index f541ca2..c01bbf3 100644 --- a/src/mail/mod.rs +++ b/src/mail/mod.rs @@ -3,6 +3,7 @@ mod client; mod event; mod metadata; +mod store; use anyhow::Result; use futures::{ diff --git a/src/mail/store.rs b/src/mail/store.rs new file mode 100644 index 0000000..a88edaf --- /dev/null +++ b/src/mail/store.rs @@ -0,0 +1,23 @@ +//! Package for managing the offline storage of emails + +use anyhow::Result; +use sqlx::sqlite::SqlitePool; + +/// SQLite email manager +#[derive(Clone)] +pub struct MailStore { + pool: SqlitePool, +} + +impl MailStore { + pub async fn new() -> Result { + let pool = SqlitePool::connect("hellosu.db").await?; + + let run = tokio::spawn(listen_loop(pool.clone())); + + Ok(MailStore { pool }) + } +} + +async fn listen_loop(pool: SqlitePool) { +} diff --git a/src/main.rs b/src/main.rs index 54427d1..1d5fa9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,8 @@ use futures::future::TryFutureExt; use panorama::{ config::spawn_config_watcher_system, mail::{self, MailEvent}, - report_err, ui, + report_err, + ui::{self, UiParams}, }; use structopt::StructOpt; use tokio::{ @@ -97,11 +98,14 @@ fn run_ui( thread::spawn(move || { let localset = LocalSet::new(); + let params = UiParams { + stdout, + exit_tx, + mail2ui_rx, + }; localset.spawn_local(async { - ui::run_ui2(stdout, exit_tx, mail2ui_rx) - .unwrap_or_else(report_err) - .await; + ui::run_ui2(params).unwrap_or_else(report_err).await; }); rt.block_on(localset); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index c51e17a..b86cbfa 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -22,7 +22,7 @@ use anyhow::Result; use chrono::{Local, TimeZone}; use crossterm::{ cursor, - event::{self, Event, KeyCode, KeyEvent, EventStream}, + event::{self, Event, EventStream, KeyCode, KeyEvent}, style, terminal, }; use downcast_rs::Downcast; @@ -50,14 +50,24 @@ use self::windows::*; pub(crate) type FrameType<'a, 'b, 'c> = &'c mut Frame<'a, CrosstermBackend<&'b mut Stdout>>; pub(crate) type TermType<'a, 'b> = &'b mut Terminal>; -const FRAME_DURATION: Duration = Duration::from_millis(17); +/// Parameters for passing to the UI thread +pub struct UiParams { + /// Handle to the screen + pub stdout: Stdout, + + /// A channel for telling the UI to quit + pub exit_tx: mpsc::Sender<()>, + + /// All the events coming in from the mail thread + pub mail2ui_rx: mpsc::UnboundedReceiver, +} /// Main entrypoint for the UI -pub async fn run_ui2( - mut stdout: Stdout, - exit_tx: mpsc::Sender<()>, - mut mail2ui_rx: mpsc::UnboundedReceiver, -) -> Result<()> { +pub async fn run_ui2(params: UiParams) -> Result<()> { + let mut stdout = params.stdout; + let mut mail2ui_rx = params.mail2ui_rx; + let exit_tx = params.exit_tx; + execute!(stdout, cursor::Hide, terminal::EnterAlternateScreen)?; terminal::enable_raw_mode()?;