BackendOp: Change set_{flag,tag} methods
parent
8c1fc031e5
commit
c82367e00d
|
@ -68,9 +68,9 @@ use std::fmt::Debug;
|
|||
use std::ops::Deref;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use core::pin::Pin;
|
||||
pub use futures::stream::Stream;
|
||||
use std::future::Future;
|
||||
pub use std::pin::Pin;
|
||||
|
||||
use std;
|
||||
use std::collections::HashMap;
|
||||
|
@ -330,6 +330,11 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
|
|||
work_context: WorkContext,
|
||||
) -> Result<std::thread::ThreadId>;
|
||||
fn mailboxes(&self) -> Result<HashMap<MailboxHash, Mailbox>>;
|
||||
fn mailboxes_async(
|
||||
&self,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<HashMap<MailboxHash, Mailbox>>> + Send>>> {
|
||||
Err(MeliError::new("Unimplemented."))
|
||||
}
|
||||
fn operation(&self, hash: EnvelopeHash) -> Result<Box<dyn BackendOp>>;
|
||||
|
||||
fn save(&self, bytes: &[u8], mailbox_hash: MailboxHash, flags: Option<Flag>) -> Result<()>;
|
||||
|
@ -427,8 +432,16 @@ pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
|
|||
fn description(&self) -> String;
|
||||
fn as_bytes(&mut self) -> Result<&[u8]>;
|
||||
fn fetch_flags(&self) -> Result<Flag>;
|
||||
fn set_flag(&mut self, envelope: &mut Envelope, flag: Flag, value: bool) -> Result<()>;
|
||||
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()>;
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
flag: Flag,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>>;
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
tag: String,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>>;
|
||||
}
|
||||
|
||||
/// Wrapper for BackendOps that are to be set read-only.
|
||||
|
@ -456,10 +469,18 @@ impl BackendOp for ReadOnlyOp {
|
|||
fn fetch_flags(&self) -> Result<Flag> {
|
||||
self.op.fetch_flags()
|
||||
}
|
||||
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> {
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
_flag: Flag,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("read-only set."))
|
||||
}
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, _value: bool) -> Result<()> {
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
_tag: String,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("read-only set."))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
use super::*;
|
||||
|
||||
use crate::backends::BackendOp;
|
||||
use crate::backends::*;
|
||||
use crate::email::*;
|
||||
use crate::error::{MeliError, Result};
|
||||
use std::cell::Cell;
|
||||
|
@ -98,7 +98,6 @@ impl BackendOp for ImapOp {
|
|||
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
||||
let cache = bytes_cache.entry(self.uid).or_default();
|
||||
if let Some((flags, _)) = flags {
|
||||
self.flags.set(Some(flags));
|
||||
cache.flags = Some(flags);
|
||||
}
|
||||
cache.bytes =
|
||||
|
@ -149,77 +148,87 @@ impl BackendOp for ImapOp {
|
|||
Ok(self.flags.get().unwrap())
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, _envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
f: Flag,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
let mut flags = self.fetch_flags()?;
|
||||
flags.set(f, value);
|
||||
let connection = self.connection.clone();
|
||||
let mailbox_hash = self.mailbox_hash;
|
||||
let uid = self.uid;
|
||||
let uid_store = self.uid_store.clone();
|
||||
|
||||
let mut response = String::with_capacity(8 * 1024);
|
||||
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||
conn.select_mailbox(self.mailbox_hash, &mut response, false)?;
|
||||
debug!(&response);
|
||||
conn.send_command(
|
||||
format!(
|
||||
"UID STORE {} FLAGS.SILENT ({})",
|
||||
self.uid,
|
||||
flags_to_imap_list!(flags)
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
conn.read_response(&mut response, RequiredResponses::STORE_REQUIRED)?;
|
||||
debug!(&response);
|
||||
match protocol_parser::uid_fetch_flags_response(response.as_bytes())
|
||||
.map(|(_, v)| v)
|
||||
.map_err(MeliError::from)
|
||||
{
|
||||
Ok(v) => {
|
||||
if v.len() == 1 {
|
||||
debug!("responses len is {}", v.len());
|
||||
let (uid, (flags, _)) = v[0];
|
||||
assert_eq!(uid, self.uid);
|
||||
self.flags.set(Some(flags));
|
||||
Ok(Box::pin(async move {
|
||||
let mut conn = try_lock(&connection, Some(std::time::Duration::new(2, 0)))?;
|
||||
conn.select_mailbox(mailbox_hash, &mut response, false)?;
|
||||
debug!(&response);
|
||||
conn.send_command(
|
||||
format!(
|
||||
"UID STORE {} FLAGS.SILENT ({})",
|
||||
uid,
|
||||
flags_to_imap_list!(flags)
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
conn.read_response(&mut response, RequiredResponses::STORE_REQUIRED)?;
|
||||
debug!(&response);
|
||||
match protocol_parser::uid_fetch_flags_response(response.as_bytes())
|
||||
.map(|(_, v)| v)
|
||||
.map_err(MeliError::from)
|
||||
{
|
||||
Ok(v) => {
|
||||
if v.len() == 1 {
|
||||
debug!("responses len is {}", v.len());
|
||||
let (uid, (flags, _)) = v[0];
|
||||
assert_eq!(uid, uid);
|
||||
}
|
||||
}
|
||||
Err(e) => Err(e)?,
|
||||
}
|
||||
Err(e) => Err(e)?,
|
||||
}
|
||||
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
|
||||
let cache = bytes_cache.entry(self.uid).or_default();
|
||||
cache.flags = Some(flags);
|
||||
Ok(())
|
||||
let mut bytes_cache = uid_store.byte_cache.lock()?;
|
||||
let cache = bytes_cache.entry(uid).or_default();
|
||||
cache.flags = Some(flags);
|
||||
Ok(())
|
||||
}))
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()> {
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
tag: String,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
let mut response = String::with_capacity(8 * 1024);
|
||||
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||
conn.select_mailbox(self.mailbox_hash, &mut response, false)?;
|
||||
conn.send_command(
|
||||
format!(
|
||||
"UID STORE {} {}FLAGS.SILENT ({})",
|
||||
self.uid,
|
||||
if value { "+" } else { "-" },
|
||||
&tag
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
conn.read_response(&mut response, RequiredResponses::STORE_REQUIRED)?;
|
||||
protocol_parser::uid_fetch_flags_response(response.as_bytes())
|
||||
.map(|(_, v)| v)
|
||||
.map_err(MeliError::from)?;
|
||||
let hash = tag_hash!(tag);
|
||||
if value {
|
||||
self.uid_store.tag_index.write().unwrap().insert(hash, tag);
|
||||
} else {
|
||||
self.uid_store.tag_index.write().unwrap().remove(&hash);
|
||||
}
|
||||
if !envelope.labels().iter().any(|&h_| h_ == hash) {
|
||||
let connection = self.connection.clone();
|
||||
let mailbox_hash = self.mailbox_hash;
|
||||
let uid = self.uid;
|
||||
let uid_store = self.uid_store.clone();
|
||||
|
||||
Ok(Box::pin(async move {
|
||||
let mut conn = try_lock(&connection, Some(std::time::Duration::new(2, 0)))?;
|
||||
conn.select_mailbox(mailbox_hash, &mut response, false)?;
|
||||
conn.send_command(
|
||||
format!(
|
||||
"UID STORE {} {}FLAGS.SILENT ({})",
|
||||
uid,
|
||||
if value { "+" } else { "-" },
|
||||
&tag
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
conn.read_response(&mut response, RequiredResponses::STORE_REQUIRED)?;
|
||||
protocol_parser::uid_fetch_flags_response(response.as_bytes())
|
||||
.map(|(_, v)| v)
|
||||
.map_err(MeliError::from)?;
|
||||
let hash = tag_hash!(tag);
|
||||
if value {
|
||||
envelope.labels_mut().push(hash);
|
||||
uid_store.tag_index.write().unwrap().insert(hash, tag);
|
||||
} else {
|
||||
uid_store.tag_index.write().unwrap().remove(&hash);
|
||||
}
|
||||
}
|
||||
if !value {
|
||||
if let Some(pos) = envelope.labels().iter().position(|&h_| h_ == hash) {
|
||||
envelope.labels_mut().remove(pos);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(())
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ impl BackendOp for ImapOp {
|
|||
self.flags.get().unwrap()
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, _envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
|
||||
fn set_flag(&mut self, f: Flag, value: bool) -> Result<()> {
|
||||
let mut flags = self.fetch_flags();
|
||||
flags.set(f, value);
|
||||
|
||||
|
@ -202,7 +202,7 @@ impl BackendOp for ImapOp {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()> {
|
||||
fn set_tag(&mut self, tag: String, value: bool) -> Result<()> {
|
||||
let mut response = String::with_capacity(8 * 1024);
|
||||
let mut conn = try_lock(&self.connection, Some(std::time::Duration::new(2, 0)))?;
|
||||
conn.select_mailbox(self.mailbox_hash, &mut response)?;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
use super::*;
|
||||
|
||||
use crate::backends::BackendOp;
|
||||
use crate::backends::*;
|
||||
use crate::error::Result;
|
||||
use std::cell::Cell;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
@ -101,11 +101,19 @@ impl BackendOp for JmapOp {
|
|||
Ok(Flag::default())
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, _envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {
|
||||
Ok(())
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
_f: Flag,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("Unimplemented"))
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, _value: bool) -> Result<()> {
|
||||
Ok(())
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
_tag: String,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("Unimplemented"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,11 @@ pub use self::backend::*;
|
|||
mod stream;
|
||||
pub use stream::*;
|
||||
|
||||
pub use futures::stream::Stream;
|
||||
use crate::backends::*;
|
||||
use crate::email::{Envelope, Flag};
|
||||
use crate::email::Flag;
|
||||
use crate::error::{MeliError, Result};
|
||||
use crate::shellexpand::ShellExpandTrait;
|
||||
pub use futures::stream::Stream;
|
||||
|
||||
use memmap::{Mmap, Protection};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
|
@ -106,49 +106,61 @@ impl<'a> BackendOp for MaildirOp {
|
|||
Ok(path.flags())
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
|
||||
let path = self.path();
|
||||
let path = path.to_str().unwrap(); // Assume UTF-8 validity
|
||||
let idx: usize = path
|
||||
.rfind(":2,")
|
||||
.ok_or_else(|| MeliError::new(format!("Invalid email filename: {:?}", self)))?
|
||||
+ 3;
|
||||
let mut new_name: String = path[..idx].to_string();
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
f: Flag,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
let mut flags = self.fetch_flags()?;
|
||||
flags.set(f, value);
|
||||
|
||||
if !(flags & Flag::DRAFT).is_empty() {
|
||||
new_name.push('D');
|
||||
}
|
||||
if !(flags & Flag::FLAGGED).is_empty() {
|
||||
new_name.push('F');
|
||||
}
|
||||
if !(flags & Flag::PASSED).is_empty() {
|
||||
new_name.push('P');
|
||||
}
|
||||
if !(flags & Flag::REPLIED).is_empty() {
|
||||
new_name.push('R');
|
||||
}
|
||||
if !(flags & Flag::SEEN).is_empty() {
|
||||
new_name.push('S');
|
||||
}
|
||||
if !(flags & Flag::TRASHED).is_empty() {
|
||||
new_name.push('T');
|
||||
}
|
||||
let old_hash = envelope.hash();
|
||||
let new_name: PathBuf = new_name.into();
|
||||
let old_hash = self.hash;
|
||||
let mailbox_hash = self.mailbox_hash;
|
||||
let hash_index = self.hash_index.clone();
|
||||
let mut map = hash_index.lock().unwrap();
|
||||
let map = map.entry(self.mailbox_hash).or_default();
|
||||
map.entry(old_hash).or_default().modified = Some(PathMod::Path(new_name.clone()));
|
||||
let path = self.path();
|
||||
Ok(Box::pin(async move {
|
||||
let path = path;
|
||||
let path = path.to_str().unwrap(); // Assume UTF-8 validity
|
||||
let idx: usize = path
|
||||
.rfind(":2,")
|
||||
.ok_or_else(|| MeliError::new(format!("Invalid email filename: {:?}", path)))?
|
||||
+ 3;
|
||||
let mut new_name: String = path[..idx].to_string();
|
||||
flags.set(f, value);
|
||||
|
||||
debug!("renaming {:?} to {:?}", path, new_name);
|
||||
fs::rename(&path, &new_name)?;
|
||||
debug!("success in rename");
|
||||
Ok(())
|
||||
if !(flags & Flag::DRAFT).is_empty() {
|
||||
new_name.push('D');
|
||||
}
|
||||
if !(flags & Flag::FLAGGED).is_empty() {
|
||||
new_name.push('F');
|
||||
}
|
||||
if !(flags & Flag::PASSED).is_empty() {
|
||||
new_name.push('P');
|
||||
}
|
||||
if !(flags & Flag::REPLIED).is_empty() {
|
||||
new_name.push('R');
|
||||
}
|
||||
if !(flags & Flag::SEEN).is_empty() {
|
||||
new_name.push('S');
|
||||
}
|
||||
if !(flags & Flag::TRASHED).is_empty() {
|
||||
new_name.push('T');
|
||||
}
|
||||
let new_name: PathBuf = new_name.into();
|
||||
let mut map = hash_index.lock().unwrap();
|
||||
let map = map.entry(mailbox_hash).or_default();
|
||||
map.entry(old_hash).or_default().modified = Some(PathMod::Path(new_name.clone()));
|
||||
|
||||
debug!("renaming {:?} to {:?}", path, new_name);
|
||||
fs::rename(&path, &new_name)?;
|
||||
debug!("success in rename");
|
||||
Ok(())
|
||||
}))
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, _value: bool) -> Result<()> {
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
_tag: String,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("Maildir doesn't support tags."))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,7 @@
|
|||
*/
|
||||
|
||||
use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
||||
use crate::backends::BackendOp;
|
||||
use crate::backends::MailboxHash;
|
||||
use crate::backends::{
|
||||
BackendMailbox, MailBackend, Mailbox, MailboxPermissions, RefreshEvent, RefreshEventConsumer,
|
||||
RefreshEventKind, SpecialUsageMailbox,
|
||||
};
|
||||
use crate::backends::*;
|
||||
use crate::conf::AccountSettings;
|
||||
use crate::email::parser::BytesExt;
|
||||
use crate::email::*;
|
||||
|
@ -257,11 +252,19 @@ impl BackendOp for MboxOp {
|
|||
Ok(flags)
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> {
|
||||
Ok(())
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
_flag: Flag,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("Unimplemented."))
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, _value: bool) -> Result<()> {
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
_tag: String,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("mbox doesn't support tags."))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,11 +20,7 @@
|
|||
*/
|
||||
|
||||
use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
||||
use crate::backends::MailboxHash;
|
||||
use crate::backends::{
|
||||
BackendMailbox, BackendOp, MailBackend, Mailbox, MailboxPermissions, RefreshEventConsumer,
|
||||
SpecialUsageMailbox,
|
||||
};
|
||||
use crate::backends::*;
|
||||
use crate::conf::AccountSettings;
|
||||
use crate::email::{Envelope, EnvelopeHash, Flag};
|
||||
use crate::error::{MeliError, Result};
|
||||
|
@ -407,7 +403,7 @@ impl MailBackend for NotmuchDb {
|
|||
_work_context: WorkContext,
|
||||
) -> Result<std::thread::ThreadId> {
|
||||
extern crate notify;
|
||||
use crate::backends::{RefreshEvent, RefreshEventKind::*};
|
||||
use crate::backends::RefreshEventKind::*;
|
||||
use notify::{watcher, RecursiveMode, Watcher};
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let mut watcher = watcher(tx, std::time::Duration::from_secs(2)).unwrap();
|
||||
|
@ -621,7 +617,7 @@ impl MailBackend for NotmuchDb {
|
|||
.as_ref()
|
||||
.unwrap_or(&self.path)
|
||||
.to_path_buf();
|
||||
crate::backends::MaildirType::save_to_mailbox(path, bytes, flags)
|
||||
MaildirType::save_to_mailbox(path, bytes, flags)
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
|
@ -681,10 +677,13 @@ impl BackendOp for NotmuchOp {
|
|||
Ok(flags)
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
f: Flag,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
let mut flags = self.fetch_flags()?;
|
||||
flags.set(f, value);
|
||||
envelope.set_flags(flags);
|
||||
let mut message: *mut notmuch_message_t = std::ptr::null_mut();
|
||||
let mut index_lck = self.index.write().unwrap();
|
||||
unsafe {
|
||||
|
@ -713,7 +712,7 @@ impl BackendOp for NotmuchOp {
|
|||
macro_rules! add_tag {
|
||||
($l:literal) => {{
|
||||
if tags.contains(unsafe { &cstr!($l) }) {
|
||||
return Ok(());
|
||||
return Ok(Box::pin(async { Ok(()) }));
|
||||
}
|
||||
if let Err(err) = try_call!(
|
||||
self.lib,
|
||||
|
@ -728,7 +727,7 @@ impl BackendOp for NotmuchOp {
|
|||
macro_rules! remove_tag {
|
||||
($l:literal) => {{
|
||||
if !tags.contains(unsafe { &cstr!($l) }) {
|
||||
return Ok(());
|
||||
return Ok(Box::pin(async { Ok(()) }));
|
||||
}
|
||||
if let Err(err) = try_call!(
|
||||
self.lib,
|
||||
|
@ -771,10 +770,14 @@ impl BackendOp for NotmuchOp {
|
|||
*p = c_str.into();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(Box::pin(async { Ok(()) }))
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, envelope: &mut Envelope, tag: String, value: bool) -> Result<()> {
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
tag: String,
|
||||
value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
let mut message: *mut notmuch_message_t = std::ptr::null_mut();
|
||||
let index_lck = self.index.read().unwrap();
|
||||
unsafe {
|
||||
|
@ -817,17 +820,7 @@ impl BackendOp for NotmuchOp {
|
|||
if value {
|
||||
self.tag_index.write().unwrap().insert(hash, tag);
|
||||
}
|
||||
if !envelope.labels().iter().any(|&h_| h_ == hash) {
|
||||
if value {
|
||||
envelope.labels_mut().push(hash);
|
||||
}
|
||||
}
|
||||
if !value {
|
||||
if let Some(pos) = envelope.labels().iter().position(|&h_| h_ == hash) {
|
||||
envelope.labels_mut().remove(pos);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(Box::pin(async { Ok(()) }))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,10 @@ use std::borrow::Cow;
|
|||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::hash::Hasher;
|
||||
use std::option::Option;
|
||||
use std::pin::Pin;
|
||||
use std::str;
|
||||
use std::string::String;
|
||||
|
||||
|
@ -605,9 +607,9 @@ impl Envelope {
|
|||
f: Flag,
|
||||
value: bool,
|
||||
mut operation: Box<dyn BackendOp>,
|
||||
) -> Result<()> {
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
self.flags.set(f, value);
|
||||
operation.set_flag(self, f, value)
|
||||
operation.set_flag(f, value)
|
||||
}
|
||||
pub fn set_flags(&mut self, f: Flag) {
|
||||
self.flags = f;
|
||||
|
@ -615,18 +617,24 @@ impl Envelope {
|
|||
pub fn flags(&self) -> Flag {
|
||||
self.flags
|
||||
}
|
||||
pub fn set_seen(&mut self, operation: Box<dyn BackendOp>) -> Result<()> {
|
||||
pub fn set_seen(
|
||||
&mut self,
|
||||
operation: Box<dyn BackendOp>,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
if !self.flags.contains(Flag::SEEN) {
|
||||
self.set_flag(Flag::SEEN, true, operation)
|
||||
} else {
|
||||
Ok(())
|
||||
Ok(Box::pin(async { Ok(()) }))
|
||||
}
|
||||
}
|
||||
pub fn set_unseen(&mut self, operation: Box<dyn BackendOp>) -> Result<()> {
|
||||
pub fn set_unseen(
|
||||
&mut self,
|
||||
operation: Box<dyn BackendOp>,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
if self.flags.contains(Flag::SEEN) {
|
||||
self.set_flag(Flag::SEEN, false, operation)
|
||||
} else {
|
||||
Ok(())
|
||||
Ok(Box::pin(async { Ok(()) }))
|
||||
}
|
||||
}
|
||||
pub fn is_seen(&self) -> bool {
|
||||
|
|
|
@ -168,48 +168,56 @@ pub trait MailListingTrait: ListingTrait {
|
|||
};
|
||||
let mut envelope: EnvelopeRefMut = account.collection.get_env_mut(env_hash);
|
||||
match a {
|
||||
ListingAction::SetSeen => {
|
||||
if let Err(e) = envelope.set_seen(op) {
|
||||
ListingAction::SetSeen => match envelope.set_seen(op) {
|
||||
Err(e) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(e.to_string()),
|
||||
));
|
||||
}
|
||||
}
|
||||
ListingAction::SetUnseen => {
|
||||
if let Err(e) = envelope.set_unseen(op) {
|
||||
Ok(fut) => {
|
||||
//accout.job_executor.spawn_specialized(fut);
|
||||
}
|
||||
},
|
||||
ListingAction::SetUnseen => match envelope.set_unseen(op) {
|
||||
Err(e) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(e.to_string()),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(fut) => {}
|
||||
},
|
||||
ListingAction::Delete => {
|
||||
drop(envelope);
|
||||
if let Err(err) = account.delete(env_hash, mailbox_hash) {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Could not delete.".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
return;
|
||||
match account.delete(env_hash, mailbox_hash) {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Could not delete.".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
return;
|
||||
}
|
||||
Ok(fut) => {}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ListingAction::CopyTo(ref mailbox_path) => {
|
||||
drop(envelope);
|
||||
if let Err(err) =
|
||||
account
|
||||
.mailbox_by_path(mailbox_path)
|
||||
.and_then(|mailbox_hash| {
|
||||
op.as_bytes()
|
||||
.and_then(|bytes| account.save(bytes, mailbox_hash, None))
|
||||
})
|
||||
{
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Could not copy.".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
return;
|
||||
match account
|
||||
.mailbox_by_path(mailbox_path)
|
||||
.and_then(|mailbox_hash| {
|
||||
op.as_bytes()
|
||||
.and_then(|bytes| account.save(bytes, mailbox_hash, None))
|
||||
}) {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Could not copy.".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
return;
|
||||
}
|
||||
Ok(fut) => {}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -297,7 +305,7 @@ pub trait MailListingTrait: ListingTrait {
|
|||
continue;
|
||||
}
|
||||
ListingAction::Tag(Remove(ref tag_str)) => {
|
||||
if let Err(err) = op.set_tag(&mut envelope, tag_str.to_string(), false) {
|
||||
if let Err(err) = op.set_tag(tag_str.to_string(), false) {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Could not set tag.".to_string()),
|
||||
err.to_string(),
|
||||
|
@ -307,7 +315,7 @@ pub trait MailListingTrait: ListingTrait {
|
|||
}
|
||||
}
|
||||
ListingAction::Tag(Add(ref tag_str)) => {
|
||||
if let Err(err) = op.set_tag(&mut envelope, tag_str.to_string(), true) {
|
||||
if let Err(err) = op.set_tag(tag_str.to_string(), true) {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Could not set tag.".to_string()),
|
||||
err.to_string(),
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
|
||||
use super::*;
|
||||
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
||||
use melib::backends::MailboxHash;
|
||||
use melib::backends::{Backend, BackendOp, Backends, MailBackend, Mailbox, RefreshEventConsumer};
|
||||
use melib::backends::*;
|
||||
use melib::conf::AccountSettings;
|
||||
use melib::email::{Envelope, EnvelopeHash, Flag};
|
||||
use melib::error::{MeliError, Result};
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
// TODO replace with melib::Envelope after simplifying melib::Envelope's
|
||||
|
@ -318,11 +318,19 @@ impl BackendOp for PluginOp {
|
|||
Err(MeliError::new("Unimplemented."))
|
||||
}
|
||||
|
||||
fn set_flag(&mut self, __envelope: &mut Envelope, _f: Flag, _value: bool) -> Result<()> {
|
||||
fn set_flag(
|
||||
&mut self,
|
||||
_f: Flag,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("Unimplemented."))
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, _value: bool) -> Result<()> {
|
||||
fn set_tag(
|
||||
&mut self,
|
||||
_tag: String,
|
||||
_value: bool,
|
||||
) -> Result<Pin<Box<dyn Future<Output = Result<()>> + Send>>> {
|
||||
Err(MeliError::new("Unimplemented."))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue