From e9d17f6897d90d465859941a41e0511c1c3ae360 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Wed, 30 Oct 2019 21:09:48 +0200 Subject: [PATCH] add cache struct in Account --- ui/src/cache.rs | 110 ++++++++++++++++++ ui/src/components/mail/listing/compact.rs | 8 +- .../components/mail/listing/conversations.rs | 8 +- ui/src/conf.rs | 21 ++++ ui/src/conf/accounts.rs | 39 ++++++- ui/src/execute.rs | 17 ++- ui/src/execute/actions.rs | 6 + ui/src/lib.rs | 2 +- ui/src/sqlite3.rs | 6 - 9 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 ui/src/cache.rs diff --git a/ui/src/cache.rs b/ui/src/cache.rs new file mode 100644 index 000000000..a54b65e11 --- /dev/null +++ b/ui/src/cache.rs @@ -0,0 +1,110 @@ +/* + * meli - ui crate. + * + * Copyright 2017-2018 Manos Pitsidianakis + * + * This file is part of meli. + * + * meli is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * meli is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with meli. If not, see . + */ + +use melib::backends::{FolderHash, MailBackend}; +use melib::email::{EnvelopeHash, Flag, UnixTimestamp}; +use melib::mailbox::*; +use melib::thread::{ThreadHash, ThreadNode}; + +#[derive(Debug)] +pub enum Query { + Before(UnixTimestamp), + After(UnixTimestamp), + Between(UnixTimestamp, UnixTimestamp), + On(UnixTimestamp), + /* * * * */ + From(String), + To(String), + Cc(String), + Bcc(String), + InReplyTo(String), + References(String), + AllAddresses(String), + /* * * * */ + Body(String), + Subject(String), + AllText(String), + /* * * * */ + Flag(Flag), +} + +enum CacheType { + Sqlite3, +} + +pub struct Cache { + collection: Collection, + kind: CacheType, + backend: Box, +} + +impl Cache { + pub fn build_index(&mut self) { + unimplemented!() + } + + pub fn new(backend: Box) -> Self { + unimplemented!() + } + pub fn get_env(&self, h: &EnvelopeHash) -> &Envelope { + &self.collection[h] + } + pub fn get_env_mut(&mut self, h: &EnvelopeHash) -> &mut Envelope { + self.collection.entry(*h).or_default() + } + pub fn contains_key(&self, h: EnvelopeHash) -> bool { + self.collection.contains_key(&h) + } + /* + pub fn operation(&self, h: EnvelopeHash) -> Box { + //let operation = self.backend.operation(h, m.folder.hash()) + unimplemented!() + unreachable!() + } + */ + pub fn thread_to_mail_mut(&mut self, h: ThreadHash, f: FolderHash) -> &mut Envelope { + self.collection + .envelopes + .entry(self.collection.threads[&f].thread_to_mail(h)) + .or_default() + } + pub fn thread_to_mail(&self, h: ThreadHash, f: FolderHash) -> &Envelope { + &self.collection.envelopes[&self.collection.threads[&f].thread_to_mail(h)] + } + pub fn threaded_mail(&self, h: ThreadHash, f: FolderHash) -> EnvelopeHash { + self.collection.threads[&f].thread_to_mail(h) + } + pub fn mail_and_thread( + &mut self, + i: EnvelopeHash, + f: FolderHash, + ) -> (&mut Envelope, &ThreadNode) { + let thread; + { + let x = &mut self.collection.envelopes.entry(i).or_default(); + thread = &self.collection.threads[&f][&x.thread()]; + } + (self.collection.envelopes.entry(i).or_default(), thread) + } + pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode { + &self.collection.threads[&f].thread_nodes()[&h] + } +} diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index 537bd96f5..993267794 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -360,13 +360,7 @@ impl ListingTrait for CompactListing { let account = &context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); - match crate::search::filter( - filter_term, - context, - self.cursor_pos.0, - self.sort, - folder_hash, - ) { + match account.search(filter_term, self.sort, folder_hash) { Ok(results) => { let threads = &account.collection.threads[&folder_hash]; for env_hash in results { diff --git a/ui/src/components/mail/listing/conversations.rs b/ui/src/components/mail/listing/conversations.rs index f7ae339a1..45c91fff0 100644 --- a/ui/src/components/mail/listing/conversations.rs +++ b/ui/src/components/mail/listing/conversations.rs @@ -351,13 +351,7 @@ impl ListingTrait for ConversationsListing { let account = &context.accounts[self.cursor_pos.0]; let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash(); - match crate::search::filter( - filter_term, - context, - self.cursor_pos.0, - self.sort, - folder_hash, - ) { + match account.search(filter_term, self.sort, folder_hash) { Ok(results) => { let threads = &account.collection.threads[&folder_hash]; for env_hash in results { diff --git a/ui/src/conf.rs b/ui/src/conf.rs index 93fe3c659..79a7d9f83 100644 --- a/ui/src/conf.rs +++ b/ui/src/conf.rs @@ -553,3 +553,24 @@ impl Serialize for IndexStyle { } } } + +#[derive(Debug)] +pub enum IndexCache { + Nothing, + #[cfg(feature = "sqlite3")] + Sqlite3, + Backend, +} + +impl Default for IndexCache { + fn default() -> Self { + #[cfg(feature = "sqlite3")] + { + IndexCache::Sqlite3 + } + #[cfg(not(feature = "sqlite3"))] + { + IndexCache::Nothing + } + } +} diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index e4e560b99..7ee254394 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -32,7 +32,7 @@ use melib::backends::{ }; use melib::error::{MeliError, Result}; use melib::mailbox::*; -use melib::thread::{ThreadHash, ThreadNode, Threads}; +use melib::thread::{SortField, SortOrder, ThreadHash, ThreadNode, Threads}; use melib::AddressBook; use melib::StackVec; @@ -821,6 +821,43 @@ impl Account { self.is_online = ret; ret } + + pub fn search( + &self, + search_term: &str, + sort: (SortField, SortOrder), + folder_hash: FolderHash, + ) -> Result> { + #[cfg(feature = "sqlite3")] + { + crate::sqlite3::search(search_term, sort) + } + + #[cfg(not(feature = "sqlite3"))] + { + let mut ret = StackVec::new(); + + for env_hash in self.folders[folder_hash].as_result()?.envelopes { + let envelope = &account.collection[&env_hash]; + if envelope.subject().contains(&search_term) { + ret.push(env_hash); + continue; + } + if envelope.field_from_to_string().contains(&search_term) { + ret.push(env_hash); + continue; + } + let op = self.operation(env_hash); + let body = envelope.body(op)?; + let decoded = decode_rec(&body, None); + let body_text = String::from_utf8_lossy(&decoded); + if body_text.contains(&search_term) { + ret.push(env_hash); + } + } + ret + } + } } impl Index for Account { diff --git a/ui/src/execute.rs b/ui/src/execute.rs index 6393c05f6..8741058f3 100644 --- a/ui/src/execute.rs +++ b/ui/src/execute.rs @@ -27,6 +27,7 @@ use nom::{digit, not_line_ending}; use std; pub mod actions; pub mod history; +pub use crate::actions::AccountAction::{self, *}; pub use crate::actions::Action::{self, *}; pub use crate::actions::ComposeAction::{self, *}; pub use crate::actions::ListingAction::{self, *}; @@ -297,6 +298,18 @@ define_commands!([ ); ) }, + { tags: ["reindex "], + desc: "reindex ACCOUNT, rebuild account cache in the background", + parser:( + named!( reindex, + do_parse!( + ws!(tag!("reindex")) + >> account: map_res!(is_not!(" "), std::str::from_utf8) + >> (AccountAction(account.to_string(), ReIndex)) + ) + ); + ) + }, { tags: ["open-in-tab"], desc: "opens envelope view in new tab", parser:( @@ -364,6 +377,8 @@ named!( alt_complete!(add_attachment | remove_attachment | toggle_sign) ); +named!(account_action, alt_complete!(reindex)); + named!(pub parse_command, - alt_complete!( goto | listing_action | sort | subsort | close | mailinglist | setenv | printenv | pipe | compose_action | create_folder | sub_folder | unsub_folder | delete_folder | rename_folder) + alt_complete!( goto | listing_action | sort | subsort | close | mailinglist | setenv | printenv | pipe | compose_action | create_folder | sub_folder | unsub_folder | delete_folder | rename_folder | account_action ) ); diff --git a/ui/src/execute/actions.rs b/ui/src/execute/actions.rs index 4357e26a2..a76a678c8 100644 --- a/ui/src/execute/actions.rs +++ b/ui/src/execute/actions.rs @@ -74,6 +74,11 @@ pub enum ComposeAction { ToggleSign, } +#[derive(Debug)] +pub enum AccountAction { + ReIndex, +} + #[derive(Debug)] pub enum Action { Listing(ListingAction), @@ -88,6 +93,7 @@ pub enum Action { PrintEnv(String), Compose(ComposeAction), Folder(AccountName, FolderPath, FolderOperation), + AccountAction(AccountName, AccountAction), } type AccountName = String; diff --git a/ui/src/lib.rs b/ui/src/lib.rs index a8a85e91d..cabedc71b 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -72,7 +72,7 @@ pub use crate::workers::*; #[cfg(feature = "sqlite3")] pub mod sqlite3; -pub mod search; +pub mod cache; pub use crate::username::*; pub mod username { diff --git a/ui/src/sqlite3.rs b/ui/src/sqlite3.rs index 2f027a7e7..c96036fc6 100644 --- a/ui/src/sqlite3.rs +++ b/ui/src/sqlite3.rs @@ -19,10 +19,7 @@ * along with meli. If not, see . */ -use crate::search::Query; -use crate::state::Context; use melib::{ - backends::FolderHash, email::EnvelopeHash, thread::{SortField, SortOrder}, MeliError, Result, StackVec, @@ -189,10 +186,7 @@ pub fn insert(context: &crate::state::Context) -> Result<()> { pub fn search( term: &str, - _context: &Context, - _account_idx: usize, (sort_field, sort_order): (SortField, SortOrder), - _folder_hash: FolderHash, ) -> Result> { let data_dir = xdg::BaseDirectories::with_prefix("meli").map_err(|e| MeliError::new(e.to_string()))?;