ui: toggle thread snooze flag

snooze field translated to whether the user wants to be notified of new
email in the thread or not. This is toggled with an (temp) EX cmd: `toggle_thread_snooze`

closes #112
embed
Manos Pitsidianakis 2019-05-15 20:58:59 +03:00
parent 22d868f499
commit 3c575c823d
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
5 changed files with 97 additions and 9 deletions

View File

@ -359,6 +359,8 @@ pub struct ThreadNode {
len: usize,
has_unseen: bool,
snoozed: bool,
/* Union/Find set fields */
thread_group: ThreadHash,
rank: i32,
@ -376,6 +378,8 @@ impl Default for ThreadNode {
len: 0,
has_unseen: false,
snoozed: false,
thread_group: ThreadHash::default(),
rank: 0,
}
@ -428,11 +432,23 @@ impl ThreadNode {
pub fn indentation(&self) -> usize {
self.indentation
}
pub fn snoozed(&self) -> bool {
self.snoozed
}
pub fn thread_group(&self) -> ThreadHash {
self.thread_group
}
pub fn set_snoozed(&mut self, set: bool) {
self.snoozed = set;
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Threads {
thread_nodes: FnvHashMap<ThreadHash, ThreadNode>,
pub thread_nodes: FnvHashMap<ThreadHash, ThreadNode>,
root_set: RefCell<Vec<ThreadHash>>,
tree: RefCell<Vec<ThreadTree>>,
@ -468,6 +484,13 @@ impl<'a> Iterator for RootIterator<'a> {
}
}
}
fn find_ref(buf: &FnvHashMap<ThreadHash, ThreadNode>, h: ThreadHash) -> ThreadHash {
if buf[&h].thread_group == h {
return h;
}
let p = buf[&h].thread_group;
find_ref(buf, p)
}
fn find(buf: &mut FnvHashMap<ThreadHash, ThreadNode>, h: ThreadHash) -> ThreadHash {
if buf[&h].thread_group == h {
return h;
@ -502,7 +525,11 @@ fn union(buf: &mut FnvHashMap<ThreadHash, ThreadNode>, x: ThreadHash, y: ThreadH
}
impl Threads {
fn find(&mut self, i: ThreadHash) -> ThreadHash {
pub fn is_snoozed(&self, h: ThreadHash) -> bool {
let root = find_ref(&self.thread_nodes, h);
self.thread_nodes[&root].snoozed()
}
pub fn find(&mut self, i: ThreadHash) -> ThreadHash {
find(&mut self.thread_nodes, i)
}
fn union(&mut self, x: ThreadHash, y: ThreadHash) -> ThreadHash {

View File

@ -104,20 +104,30 @@ impl MailboxView {
e: &Envelope,
len: usize,
idx: usize,
is_snoozed: bool,
) -> (IndexNoString, FromString, DateString, SubjectString) {
if len > 0 {
(
IndexNoString(idx.to_string()),
FromString(address_list!((e.from()) as comma_sep_list)),
DateString(MailboxView::format_date(e)),
SubjectString(format!("{} ({})", e.subject(), len)),
SubjectString(format!(
"{} ({}){}",
e.subject(),
len,
if is_snoozed { " 💤" } else { "" }
)),
)
} else {
(
IndexNoString(idx.to_string()),
FromString(address_list!((e.from()) as comma_sep_list)),
DateString(MailboxView::format_date(e)),
SubjectString(e.subject().to_string()),
SubjectString(format!(
"{}{}",
e.subject(),
if is_snoozed { " 💤" } else { "" }
)),
)
}
}
@ -229,7 +239,13 @@ impl MailboxView {
panic!();
}
let root_envelope: &Envelope = &mailbox.collection[&i];
let strings = MailboxView::make_entry_string(root_envelope, thread_node.len(), idx);
let strings = MailboxView::make_entry_string(
root_envelope,
thread_node.len(),
idx,
threads.is_snoozed(root_idx),
);
min_width.0 = cmp::max(min_width.0, strings.0.len()); /* index */
min_width.1 = cmp::max(min_width.1, strings.2.split_graphemes().len()); /* date */
min_width.2 = cmp::max(min_width.2, strings.3.split_graphemes().len()); /* subject */
@ -328,6 +344,9 @@ impl MailboxView {
((_x, idx), (widths.2 + _x, idx)),
false,
);
if threads.is_snoozed(root_idx) {
self.content[(x - 1, idx)].set_fg(Color::Red);
}
self.order.insert(i, idx);
@ -596,8 +615,7 @@ impl Component for MailboxView {
}
UIEvent::StartupCheck(ref f)
if *f
== context.accounts[self.new_cursor_pos.0].folders_order
[self.new_cursor_pos.1] =>
== context.accounts[self.cursor_pos.0].folders_order[self.new_cursor_pos.1] =>
{
self.refresh_mailbox(context);
self.set_dirty();
@ -639,6 +657,35 @@ impl Component for MailboxView {
self.refresh_mailbox(context);
return true;
}
Action::ToggleThreadSnooze => {
{
//FIXME NLL
let mailbox = &mut context.accounts[self.cursor_pos.0][self.cursor_pos.1]
.as_mut()
.unwrap();
let threads = &mut mailbox.collection.threads;
let thread_group = threads.thread_nodes()
[&threads.root_set(self.cursor_pos.2)]
.thread_group();
let thread_group = threads.find(thread_group);
/*let i = if let Some(i) = threads.thread_nodes[&thread_group].message() {
i
} else {
let mut iter_ptr = threads.thread_nodes[&thread_group].children()[0];
while threads.thread_nodes()[&iter_ptr].message().is_none() {
iter_ptr = threads.thread_nodes()[&iter_ptr].children()[0];
}
threads.thread_nodes()[&iter_ptr].message().unwrap()
};*/
let root_node = threads.thread_nodes.entry(thread_group).or_default();
let is_snoozed = root_node.snoozed();
root_node.set_snoozed(!is_snoozed);
//self.row_updates.push(i);
}
self.refresh_mailbox(context);
return true;
}
_ => {}
},
_ => {}

View File

@ -290,12 +290,20 @@ impl Account {
}
RefreshEventKind::Create(envelope) => {
debug!("create {}", envelope.hash());
let env: &Envelope = mailbox!(&folder_hash, self.folders).insert(*envelope);
let env_hash: EnvelopeHash = {
let mailbox = mailbox!(&folder_hash, self.folders);
mailbox.insert(*envelope).hash()
};
let ref_folders: FnvHashMap<FolderHash, Folder> = self.backend.folders();
let folder_conf = &self.settings.folder_confs[&self.folder_names[&folder_hash]];
if folder_conf.ignore.is_true() {
return None;
}
let (env, thread_node) =
mailbox!(&folder_hash, self.folders).mail_and_thread(env_hash);
if thread_node.snoozed() {
return None;
}
return Some(Notification(
Some("new mail".into()),
format!(

View File

@ -90,6 +90,11 @@ named!(
preceded!(tag!("set "), alt_complete!(threaded | plain | compact))
);
named!(
toggle_thread_snooze<Action>,
map!(ws!(tag!("toggle_thread_snooze")), |_| ToggleThreadSnooze)
);
named!(pub parse_command<Action>,
alt_complete!( goto | toggle | sort | subsort | close)
alt_complete!( goto | toggle | sort | subsort | close | toggle_thread_snooze)
);

View File

@ -54,4 +54,5 @@ pub enum Action {
Sort(SortField, SortOrder),
SubSort(SortField, SortOrder),
Tab(TabAction),
ToggleThreadSnooze,
}