Set flags in backends and mark as read when read in maillisting
parent
b21d30c2ef
commit
f2a646158d
|
@ -68,3 +68,11 @@ impl From<nom::IError> for MeliError {
|
|||
MeliError::new(format!("{:?}", kind))
|
||||
}
|
||||
}
|
||||
|
||||
//use std::option;
|
||||
//impl From<option::NoneError> for MeliError {
|
||||
// #[inline]
|
||||
// fn from(kind: option::NoneError) -> MeliError {
|
||||
// MeliError::new(format!("{:?}", kind))
|
||||
// }
|
||||
//}
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
use conf::Folder;
|
||||
use error::Result;
|
||||
use async::*;
|
||||
use mailbox::backends::{BackendOp, MailBackend, RefreshEventConsumer};
|
||||
use mailbox::email::{Envelope, Flag};
|
||||
use mailbox::backends::{MailBackend, RefreshEventConsumer};
|
||||
use mailbox::email::{Envelope, };
|
||||
|
||||
/// `BackendOp` implementor for Imap
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
@ -35,6 +35,9 @@ impl ImapOp {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
impl BackendOp for ImapOp {
|
||||
fn description(&self) -> String {
|
||||
unimplemented!();
|
||||
|
@ -51,7 +54,7 @@ impl BackendOp for ImapOp {
|
|||
fn fetch_flags(&self) -> Flag {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/// Imap backend
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -43,6 +43,7 @@ use memmap::{Mmap, Protection};
|
|||
use std::path::PathBuf;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::Hasher;
|
||||
use std::fs;
|
||||
|
||||
/// `BackendOp` implementor for Maildir
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -101,18 +102,53 @@ impl BackendOp for MaildirOp {
|
|||
for f in filename.chars().rev() {
|
||||
match f {
|
||||
',' => break,
|
||||
'D' => flag |= Flag::DRAFT,
|
||||
'F' => flag |= Flag::FLAGGED,
|
||||
'P' => flag |= Flag::PASSED,
|
||||
'R' => flag |= Flag::REPLIED,
|
||||
'S' => flag |= Flag::SEEN,
|
||||
'T' => flag |= Flag::TRASHED,
|
||||
'D' => flag |= Flag::DRAFT,
|
||||
'F' => flag |= Flag::FLAGGED,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
flag
|
||||
}
|
||||
fn set_flag(&mut self, envelope: &mut Envelope, f: &Flag) -> Result<()> {
|
||||
let idx: usize = self.path.rfind(":2,").ok_or(MeliError::new(format!("Invalid email filename: {:?}", self)))? + 3;
|
||||
let mut new_name: String = self.path[..idx].to_string();
|
||||
let mut flags = self.fetch_flags();
|
||||
flags.toggle(*f);
|
||||
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');
|
||||
}
|
||||
eprintln!("new name is {}", new_name);
|
||||
|
||||
fs::rename(&self.path, &new_name)?;
|
||||
envelope.set_operation_token(
|
||||
Box::new(
|
||||
BackendOpGenerator::new(
|
||||
Box::new( move || Box::new(MaildirOp::new(new_name.clone())))
|
||||
)
|
||||
)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Maildir backend https://cr.yp.to/proto/maildir.html
|
||||
|
@ -193,14 +229,12 @@ impl MaildirType {
|
|||
Ok(())
|
||||
}
|
||||
pub fn multicore(&self, cores: usize, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
|
||||
|
||||
let mut w = AsyncBuilder::new();
|
||||
let handle = {
|
||||
let tx = w.tx();
|
||||
// TODO: Avoid clone
|
||||
let folder = folder.clone();
|
||||
|
||||
|
||||
thread::Builder::new()
|
||||
.name(format!("parsing {:?}", folder))
|
||||
.spawn(move || {
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
use conf::Folder;
|
||||
use error::Result;
|
||||
use async::*;
|
||||
use mailbox::backends::{BackendOp, MailBackend, RefreshEventConsumer};
|
||||
use mailbox::email::{Envelope, Flag};
|
||||
use mailbox::backends::{MailBackend, RefreshEventConsumer};
|
||||
use mailbox::email::{Envelope, };
|
||||
|
||||
/// `BackendOp` implementor for Mbox
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
@ -35,6 +35,7 @@ impl MboxOp {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl BackendOp for MboxOp {
|
||||
fn description(&self) -> String {
|
||||
unimplemented!();
|
||||
|
@ -51,7 +52,11 @@ impl BackendOp for MboxOp {
|
|||
fn fetch_flags(&self) -> Flag {
|
||||
unimplemented!();
|
||||
}
|
||||
fn set_flags(&self, f: Flag) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// Mbox backend
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -143,6 +143,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, &mut Envelope, &Flag) -> Result<()>;
|
||||
}
|
||||
|
||||
/// `BackendOpGenerator` is a wrapper for a closure that returns a `BackendOp` object
|
||||
|
|
|
@ -253,6 +253,9 @@ impl Envelope {
|
|||
e.flags = operation.fetch_flags();
|
||||
Some(e)
|
||||
}
|
||||
pub fn set_operation_token(&mut self, operation_token: Box<BackendOpGenerator>) {
|
||||
self.operation_token= Arc::new(operation_token);
|
||||
}
|
||||
|
||||
pub fn populate_headers(&mut self) -> Result<()> {
|
||||
let mut operation = self.operation_token.generate();
|
||||
|
@ -529,13 +532,18 @@ impl Envelope {
|
|||
self.datetime = Some(new_val);
|
||||
self.timestamp = new_val.timestamp() as u64;
|
||||
}
|
||||
pub fn set_flag(&mut self, f: Flag) -> () {
|
||||
pub fn set_flag(&mut self, f: Flag) -> Result<()> {
|
||||
let mut operation = self.operation_token.generate();
|
||||
operation.set_flag(self, &f)?;
|
||||
self.flags |= f;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn flags(&self) -> Flag {
|
||||
self.flags
|
||||
}
|
||||
pub fn set_seen(&mut self) -> Result<()> {
|
||||
self.set_flag(Flag::SEEN)
|
||||
}
|
||||
pub fn is_seen(&self) -> bool {
|
||||
!(self.flags & Flag::SEEN).is_empty()
|
||||
}
|
||||
|
|
|
@ -221,6 +221,37 @@ impl MailListing {
|
|||
|
||||
self.content = content;
|
||||
}
|
||||
|
||||
fn highlight_line_self(&mut self, idx: usize, context: &Context) {
|
||||
let threaded = context.accounts[self.cursor_pos.0]
|
||||
.runtime_settings
|
||||
.threaded;
|
||||
let mailbox = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
let envelope: &Envelope = if threaded {
|
||||
let i = mailbox.threaded_mail(idx);
|
||||
&mailbox.collection[i]
|
||||
} else {
|
||||
&mailbox.collection[idx]
|
||||
};
|
||||
|
||||
let fg_color = if !envelope.is_seen() {
|
||||
Color::Byte(0)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
let bg_color =
|
||||
if !envelope.is_seen() {
|
||||
Color::Byte(251)
|
||||
} else if idx % 2 == 0 {
|
||||
Color::Byte(236)
|
||||
} else {
|
||||
Color::Default
|
||||
};
|
||||
change_colors(&mut self.content, ((0, idx), (MAX_COLS-1, idx)), fg_color, bg_color);
|
||||
}
|
||||
|
||||
fn highlight_line(&self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
|
||||
let threaded = context.accounts[self.cursor_pos.0]
|
||||
.runtime_settings
|
||||
|
@ -311,6 +342,8 @@ impl MailListing {
|
|||
context,
|
||||
);
|
||||
context.dirty_areas.push_back(area);
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn make_thread_entry(
|
||||
|
@ -403,6 +436,37 @@ impl Component for MailListing {
|
|||
context.dirty_areas.push_back(area);
|
||||
return;
|
||||
}
|
||||
/* Mark message as read */
|
||||
let idx = self.cursor_pos.2;
|
||||
let must_highlight = {
|
||||
if self.length == 0 {
|
||||
false
|
||||
} else {
|
||||
let threaded = context.accounts[self.cursor_pos.0]
|
||||
.runtime_settings
|
||||
.threaded;
|
||||
let mailbox = &mut context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||
.as_mut()
|
||||
.unwrap();
|
||||
let envelope: &mut Envelope = if threaded {
|
||||
let i = mailbox.threaded_mail(idx);
|
||||
&mut mailbox.collection[i]
|
||||
} else {
|
||||
&mut mailbox.collection[idx]
|
||||
};
|
||||
if !envelope.is_seen() {
|
||||
eprintln!("setting seen");
|
||||
envelope.set_seen();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
if must_highlight {
|
||||
eprintln!("must highlight");
|
||||
self.highlight_line_self(idx, context);
|
||||
}
|
||||
let mid = get_y(upper_left) + total_rows - bottom_entity_rows;
|
||||
self.draw_list(
|
||||
grid,
|
||||
|
@ -444,6 +508,7 @@ impl Component for MailListing {
|
|||
.as_mut()
|
||||
.map(|v| v.draw(grid, (set_y(upper_left, mid + 1), bottom_right), context));
|
||||
self.dirty = false;
|
||||
|
||||
}
|
||||
}
|
||||
fn process_event(&mut self, event: &UIEvent, context: &mut Context) {
|
||||
|
|
Loading…
Reference in New Issue