Browse Source

melib: change BackendOp::set_flag() signature

tags/pre-alpha-0.4.0
Manos Pitsidianakis 3 months ago
parent
commit
7463248da8
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS. GPG Key ID: 73627C2F690DF710
9 changed files with 56 additions and 42 deletions
  1. +2
    -2
      melib/src/backends.rs
  2. +16
    -16
      melib/src/backends/imap/operations.rs
  3. +15
    -1
      melib/src/backends/imap/protocol_parser.rs
  4. +3
    -2
      melib/src/backends/maildir.rs
  5. +1
    -1
      melib/src/backends/mbox.rs
  6. +3
    -12
      melib/src/collection.rs
  7. +11
    -6
      melib/src/email.rs
  8. +4
    -1
      ui/src/components/mail/view.rs
  9. +1
    -1
      ui/src/conf/accounts.rs

+ 2
- 2
melib/src/backends.rs View File

@@ -250,7 +250,7 @@ pub trait BackendOp: ::std::fmt::Debug + ::std::marker::Send {
fn fetch_headers(&mut self) -> Result<&[u8]>;
fn fetch_body(&mut self) -> Result<&[u8]>;
fn fetch_flags(&self) -> Flag;
fn set_flag(&mut self, envelope: &mut Envelope, flag: Flag) -> Result<()>;
fn set_flag(&mut self, envelope: &mut Envelope, flag: Flag, value: bool) -> Result<()>;
}

/// Wrapper for BackendOps that are to be set read-only.
@@ -284,7 +284,7 @@ impl BackendOp for ReadOnlyOp {
fn fetch_flags(&self) -> Flag {
self.op.fetch_flags()
}
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag) -> Result<()> {
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> {
Err(MeliError::new("read-only set."))
}
}


+ 16
- 16
melib/src/backends/imap/operations.rs View File

@@ -230,6 +230,9 @@ impl BackendOp for ImapOp {
} else {
let mut response = String::with_capacity(8 * 1024);
let mut conn = self.connection.lock().unwrap();
conn.send_command(format!("EXAMINE \"{}\"", &self.folder_path,).as_bytes())
.unwrap();
conn.read_response(&mut response).unwrap();
conn.send_command(format!("UID FETCH {} FLAGS", self.uid).as_bytes())
.unwrap();
conn.read_response(&mut response).unwrap();
@@ -238,7 +241,7 @@ impl BackendOp for ImapOp {
response.len(),
response.lines().collect::<Vec<&str>>().len()
);
match protocol_parser::uid_fetch_response(response.as_bytes())
match protocol_parser::uid_fetch_flags_response(response.as_bytes())
.to_full_result()
.map_err(MeliError::from)
{
@@ -248,12 +251,10 @@ impl BackendOp for ImapOp {
/* TODO: Trigger cache invalidation here. */
panic!(format!("message with UID {} was not found", self.uid));
}
let (uid, flags, _) = v[0];
let (uid, flags) = v[0];
assert_eq!(uid, self.uid);
if flags.is_some() {
cache.flags = flags;
self.flags.set(flags);
}
cache.flags = Some(flags);
self.flags.set(Some(flags));
}
Err(e) => Err(e).unwrap(),
}
@@ -261,7 +262,10 @@ impl BackendOp for ImapOp {
self.flags.get().unwrap()
}

fn set_flag(&mut self, _envelope: &mut Envelope, flag: Flag) -> Result<()> {
fn set_flag(&mut self, _envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
let mut flags = self.fetch_flags();
flags.set(f, value);

let mut response = String::with_capacity(8 * 1024);
let mut conn = self.connection.lock().unwrap();
conn.send_command(format!("SELECT \"{}\"", &self.folder_path,).as_bytes())?;
@@ -271,33 +275,29 @@ impl BackendOp for ImapOp {
format!(
"UID STORE {} FLAGS.SILENT ({})",
self.uid,
flags_to_imap_list!(flag)
flags_to_imap_list!(flags)
)
.as_bytes(),
)?;
conn.read_response(&mut response)?;
debug!(&response);
match protocol_parser::uid_fetch_response(response.as_bytes())
match protocol_parser::uid_fetch_flags_response(response.as_bytes())
.to_full_result()
.map_err(MeliError::from)
{
Ok(v) => {
if v.len() == 1 {
debug!("responses len is {}", v.len());
let (uid, flags, _) = v[0];
let (uid, flags) = v[0];
assert_eq!(uid, self.uid);
if flags.is_some() {
self.flags.set(flags);
}
self.flags.set(Some(flags));
}
}
Err(e) => Err(e).unwrap(),
}
conn.send_command(format!("EXAMINE \"{}\"", &self.folder_path,).as_bytes())?;
conn.read_response(&mut response)?;
let mut bytes_cache = self.uid_store.byte_cache.lock()?;
let cache = bytes_cache.entry(self.uid).or_default();
cache.flags = Some(flag);
cache.flags = Some(flags);
Ok(())
}
}

+ 15
- 1
melib/src/backends/imap/protocol_parser.rs View File

@@ -70,7 +70,7 @@ named!(
named!(
my_flags<Flag>,
do_parse!(
flags: separated_nonempty_list!(tag!(" "), preceded!(tag!("\\"), is_not!(")")))
flags: separated_list!(tag!(" "), preceded!(tag!("\\"), is_not!(")")))
>> ({
let mut ret = Flag::default();
for f in flags {
@@ -122,6 +122,20 @@ named!(
)
);

named!(
pub uid_fetch_flags_response<Vec<(usize, Flag)>>,
many0!(
do_parse!(
tag!("* ")
>> take_while!(call!(is_digit))
>> tag!(" FETCH (")
>> uid_flags: permutation!(preceded!(ws!(tag!("UID ")), map_res!(digit, |s| { usize::from_str(unsafe { std::str::from_utf8_unchecked(s) }) })), preceded!(ws!(tag!("FLAGS ")), delimited!(tag!("("), byte_flags, tag!(")"))))
>> tag!(")\r\n")
>> ((uid_flags.0, uid_flags.1))
)
)
);

macro_rules! flags_to_imap_list {
($flags:ident) => {{
let mut ret = String::new();


+ 3
- 2
melib/src/backends/maildir.rs View File

@@ -132,7 +132,7 @@ impl<'a> BackendOp for MaildirOp {
flag
}

fn set_flag(&mut self, envelope: &mut Envelope, f: Flag) -> Result<()> {
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
@@ -141,7 +141,8 @@ impl<'a> BackendOp for MaildirOp {
+ 3;
let mut new_name: String = path[..idx].to_string();
let mut flags = self.fetch_flags();
flags.toggle(f);
flags.set(f, value);

if !(flags & Flag::DRAFT).is_empty() {
new_name.push('D');
}


+ 1
- 1
melib/src/backends/mbox.rs View File

@@ -250,7 +250,7 @@ impl BackendOp for MboxOp {
flags
}

fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag) -> Result<()> {
fn set_flag(&mut self, _envelope: &mut Envelope, _flag: Flag, _value: bool) -> Result<()> {
Ok(())
}
}


+ 3
- 12
melib/src/collection.rs View File

@@ -159,21 +159,12 @@ impl Collection {
&mut self,
mut new_envelopes: FnvHashMap<EnvelopeHash, Envelope>,
folder_hash: FolderHash,
mailbox: &mut Mailbox,
sent_folder: Option<FolderHash>,
) -> Option<StackVec<FolderHash>> {
self.sent_folder = sent_folder;
new_envelopes.retain(|&h, e| {
if self.message_ids.contains_key(e.message_id().raw()) {
/* skip duplicates until a better way to handle them is found. */
//FIXME
mailbox.remove(h);
false
} else {
self.message_ids.insert(e.message_id().raw().to_vec(), h);
true
}
});
for (h, e) in new_envelopes.iter() {
self.message_ids.insert(e.message_id().raw().to_vec(), *h);
}

let &mut Collection {
ref mut threads,


+ 11
- 6
melib/src/email.rs View File

@@ -556,10 +556,14 @@ impl Envelope {
pub fn set_datetime(&mut self, new_val: chrono::DateTime<chrono::FixedOffset>) {
self.timestamp = new_val.timestamp() as UnixTimestamp;
}
pub fn set_flag(&mut self, f: Flag, mut operation: Box<dyn BackendOp>) -> Result<()> {
self.flags.toggle(f);
operation.set_flag(self, f)?;
Ok(())
pub fn set_flag(
&mut self,
f: Flag,
value: bool,
mut operation: Box<dyn BackendOp>,
) -> Result<()> {
self.flags.set(f, value);
operation.set_flag(self, f, value)
}
pub fn set_flags(&mut self, f: Flag) {
self.flags = f;
@@ -569,14 +573,14 @@ impl Envelope {
}
pub fn set_seen(&mut self, operation: Box<dyn BackendOp>) -> Result<()> {
if !self.flags.contains(Flag::SEEN) {
self.set_flag(Flag::SEEN, operation)
self.set_flag(Flag::SEEN, true, operation)
} else {
Ok(())
}
}
pub fn set_unseen(&mut self, operation: Box<dyn BackendOp>) -> Result<()> {
if self.flags.contains(Flag::SEEN) {
self.set_flag(Flag::SEEN, operation)
self.set_flag(Flag::SEEN, false, operation)
} else {
Ok(())
}
@@ -595,6 +599,7 @@ impl Ord for Envelope {
self.datetime().cmp(&other.datetime())
}
}

impl PartialOrd for Envelope {
fn partial_cmp(&self, other: &Envelope) -> Option<Ordering> {
Some(self.cmp(other))


+ 4
- 1
ui/src/components/mail/view.rs View File

@@ -1292,7 +1292,10 @@ impl Component for MailView {
let mut our_map = FnvHashMap::with_capacity_and_hasher(4, Default::default());
our_map.insert("add_addresses_to_contacts", Key::Char('c'));
our_map.insert("view_raw_source", Key::Alt('r'));
if self.mode.is_attachment() || self.mode == ViewMode::Subview || self.mode == ViewMode::Raw
if self.mode.is_attachment()
|| self.mode == ViewMode::Subview
|| self.mode == ViewMode::Raw
|| self.mode == ViewMode::Url
{
our_map.insert("return_to_normal_view", Key::Char('r'));
}


+ 1
- 1
ui/src/conf/accounts.rs View File

@@ -738,7 +738,7 @@ impl Account {
m.merge(&envelopes);
if let Some(updated_folders) =
self.collection
.merge(envelopes, folder_hash, m, self.sent_folder)
.merge(envelopes, folder_hash, self.sent_folder)
{
for f in updated_folders {
self.notify_fn.notify(f);


Loading…
Cancel
Save