parent
d9269335a1
commit
5e68d600b9
|
@ -122,7 +122,9 @@ macro_rules! make {
|
||||||
$threads.thread_nodes.entry($c).and_modify(|e| {
|
$threads.thread_nodes.entry($c).and_modify(|e| {
|
||||||
e.parent = Some($p);
|
e.parent = Some($p);
|
||||||
});
|
});
|
||||||
let old_group = $threads.groups[&old_group_hash].clone();
|
let old_group = std::mem::replace($threads.groups.entry(old_group_hash).or_default(), ThreadGroup::Node {
|
||||||
|
parent: RefCell::new(parent_group_hash),
|
||||||
|
});
|
||||||
$threads.thread_nodes.entry($c).and_modify(|e| {
|
$threads.thread_nodes.entry($c).and_modify(|e| {
|
||||||
e.group = parent_group_hash;
|
e.group = parent_group_hash;
|
||||||
});
|
});
|
||||||
|
@ -130,21 +132,21 @@ macro_rules! make {
|
||||||
e.group = parent_group_hash;
|
e.group = parent_group_hash;
|
||||||
});
|
});
|
||||||
{
|
{
|
||||||
let parent_group = $threads.groups.entry(parent_group_hash).or_default();
|
let parent_group = $threads.thread_ref_mut(parent_group_hash);
|
||||||
match (parent_group, old_group) {
|
match (parent_group, old_group) {
|
||||||
(ThreadGroup::Group {
|
(Thread {
|
||||||
ref mut date,
|
ref mut date,
|
||||||
ref mut len,
|
ref mut len,
|
||||||
ref mut unseen,
|
ref mut unseen,
|
||||||
ref mut snoozed,
|
ref mut snoozed,
|
||||||
..
|
..
|
||||||
}, ThreadGroup::Group {
|
}, ThreadGroup::Root(Thread {
|
||||||
date: old_date,
|
date: old_date,
|
||||||
len: old_len,
|
len: old_len,
|
||||||
unseen: old_unseen,
|
unseen: old_unseen,
|
||||||
snoozed: old_snoozed,
|
snoozed: old_snoozed,
|
||||||
..
|
..
|
||||||
}) => {
|
})) => {
|
||||||
*date = std::cmp::max(old_date, *date);
|
*date = std::cmp::max(old_date, *date);
|
||||||
*len += old_len;
|
*len += old_len;
|
||||||
*unseen |= old_unseen;
|
*unseen |= old_unseen;
|
||||||
|
@ -153,14 +155,10 @@ macro_rules! make {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
prev_parent
|
||||||
let old_group = $threads.groups.entry(old_group_hash).or_default();
|
} else {
|
||||||
*old_group = ThreadGroup::Node {
|
None
|
||||||
parent: RefCell::new(parent_group_hash),
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
prev_parent
|
|
||||||
} else { None }
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,69 +267,62 @@ impl FromStr for SortOrder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Thread {
|
||||||
|
root: ThreadNodeHash,
|
||||||
|
date: UnixTimestamp,
|
||||||
|
len: usize,
|
||||||
|
unseen: usize,
|
||||||
|
|
||||||
|
snoozed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub enum ThreadGroup {
|
pub enum ThreadGroup {
|
||||||
Group {
|
Root(Thread),
|
||||||
root: ThreadNodeHash,
|
Node { parent: RefCell<ThreadHash> },
|
||||||
date: UnixTimestamp,
|
|
||||||
len: usize,
|
|
||||||
unseen: usize,
|
|
||||||
|
|
||||||
snoozed: bool,
|
|
||||||
},
|
|
||||||
Node {
|
|
||||||
parent: RefCell<ThreadHash>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ThreadGroup {
|
impl Default for ThreadGroup {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ThreadGroup::Group {
|
ThreadGroup::Root(Thread::default())
|
||||||
root: ThreadNodeHash::null(),
|
}
|
||||||
date: 0,
|
}
|
||||||
len: 0,
|
|
||||||
unseen: 0,
|
impl ThreadGroup {
|
||||||
snoozed: false,
|
fn root(&self) -> Option<&Thread> {
|
||||||
|
if let ThreadGroup::Root(ref root) = self {
|
||||||
|
Some(root)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn root_mut(&mut self) -> Option<&mut Thread> {
|
||||||
|
if let ThreadGroup::Root(ref mut root) = self {
|
||||||
|
Some(root)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! property {
|
macro_rules! property {
|
||||||
($name:ident: $t:ty, $e:expr) => {
|
($name:ident: $t:ty) => {
|
||||||
pub fn $name(&self) -> $t {
|
pub fn $name(&self) -> $t {
|
||||||
match self {
|
(self.$name).into()
|
||||||
ThreadGroup::Group { $name, .. } => (*$name).into(),
|
|
||||||
_ => {
|
|
||||||
debug!(
|
|
||||||
"ThreadGroup::{}() called on a ThreadGroup::Node: {:?}",
|
|
||||||
stringify!($name),
|
|
||||||
self
|
|
||||||
);
|
|
||||||
$e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ThreadGroup {
|
|
||||||
property!(root: Option<ThreadNodeHash>, None);
|
impl Thread {
|
||||||
property!(len: usize, 0);
|
property!(root: ThreadNodeHash);
|
||||||
property!(unseen: usize, 0);
|
property!(len: usize);
|
||||||
property!(snoozed: bool, false);
|
property!(unseen: usize);
|
||||||
property!(date: UnixTimestamp, 0);
|
property!(snoozed: bool);
|
||||||
|
property!(date: UnixTimestamp);
|
||||||
|
|
||||||
pub fn set_snoozed(&mut self, val: bool) {
|
pub fn set_snoozed(&mut self, val: bool) {
|
||||||
match self {
|
self.snoozed = val;
|
||||||
ThreadGroup::Group {
|
|
||||||
ref mut snoozed, ..
|
|
||||||
} => *snoozed = val,
|
|
||||||
_ => {
|
|
||||||
debug!(
|
|
||||||
"ThreadGroup::set_snoozed() called on a ThreadGroup::Node: {:?}",
|
|
||||||
self
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,13 +495,26 @@ impl PartialEq for ThreadNode {
|
||||||
|
|
||||||
impl Threads {
|
impl Threads {
|
||||||
pub fn is_snoozed(&self, h: ThreadNodeHash) -> bool {
|
pub fn is_snoozed(&self, h: ThreadNodeHash) -> bool {
|
||||||
let root = &self.find_group(self.thread_nodes[&h].group);
|
self.thread_ref(self.thread_nodes[&h].group).snoozed()
|
||||||
self.groups[&root].snoozed()
|
}
|
||||||
|
|
||||||
|
pub fn thread_ref(&self, h: ThreadHash) -> &Thread {
|
||||||
|
match self.groups[&self.find_group(h)] {
|
||||||
|
ThreadGroup::Root(ref root) => root,
|
||||||
|
ThreadGroup::Node { .. } => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn thread_ref_mut(&mut self, h: ThreadHash) -> &mut Thread {
|
||||||
|
match self.groups.get_mut(&self.find_group(h)) {
|
||||||
|
Some(ThreadGroup::Root(ref mut root)) => root,
|
||||||
|
Some(ThreadGroup::Node { .. }) | None => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_group(&self, h: ThreadHash) -> ThreadHash {
|
pub fn find_group(&self, h: ThreadHash) -> ThreadHash {
|
||||||
let p = match self.groups[&h] {
|
let p = match self.groups[&h] {
|
||||||
ThreadGroup::Group { .. } => return h,
|
ThreadGroup::Root(_) => return h,
|
||||||
ThreadGroup::Node { ref parent } => *parent.borrow(),
|
ThreadGroup::Node { ref parent } => *parent.borrow(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -579,7 +583,7 @@ impl Threads {
|
||||||
|
|
||||||
pub fn thread_group_iter(&self, index: ThreadHash) -> ThreadGroupIterator {
|
pub fn thread_group_iter(&self, index: ThreadHash) -> ThreadGroupIterator {
|
||||||
ThreadGroupIterator {
|
ThreadGroupIterator {
|
||||||
group: self.groups[&index].root().unwrap(),
|
group: self.thread_ref(index).root(),
|
||||||
pos: 0,
|
pos: 0,
|
||||||
stack: SmallVec::new(),
|
stack: SmallVec::new(),
|
||||||
thread_nodes: &self.thread_nodes,
|
thread_nodes: &self.thread_nodes,
|
||||||
|
@ -610,16 +614,15 @@ impl Threads {
|
||||||
let was_unseen = self.thread_nodes[&thread_hash].unseen;
|
let was_unseen = self.thread_nodes[&thread_hash].unseen;
|
||||||
let is_unseen = !envelopes.read().unwrap()[&new_hash].is_seen();
|
let is_unseen = !envelopes.read().unwrap()[&new_hash].is_seen();
|
||||||
if was_unseen != is_unseen {
|
if was_unseen != is_unseen {
|
||||||
let thread = self.find_group(self.thread_nodes[&thread_hash].group);
|
if let Thread { ref mut unseen, .. } =
|
||||||
self.groups.entry(thread).and_modify(|e| {
|
self.thread_ref_mut(self.thread_nodes[&thread_hash].group)
|
||||||
if let ThreadGroup::Group { ref mut unseen, .. } = e {
|
{
|
||||||
if was_unseen {
|
if was_unseen {
|
||||||
*unseen -= 1;
|
*unseen -= 1;
|
||||||
} else {
|
} else {
|
||||||
*unseen += 1;
|
*unseen += 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
self.thread_nodes.get_mut(&thread_hash).unwrap().unseen = is_unseen;
|
self.thread_nodes.get_mut(&thread_hash).unwrap().unseen = is_unseen;
|
||||||
self.hash_set.remove(&old_hash);
|
self.hash_set.remove(&old_hash);
|
||||||
|
@ -753,7 +756,7 @@ impl Threads {
|
||||||
|
|
||||||
self.groups.insert(
|
self.groups.insert(
|
||||||
self.thread_nodes[&new_id].group,
|
self.thread_nodes[&new_id].group,
|
||||||
ThreadGroup::Group {
|
ThreadGroup::Root(Thread {
|
||||||
root: new_id,
|
root: new_id,
|
||||||
date: envelopes_lck[&env_hash].date(),
|
date: envelopes_lck[&env_hash].date(),
|
||||||
len: 1,
|
len: 1,
|
||||||
|
@ -763,7 +766,7 @@ impl Threads {
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
snoozed: false,
|
snoozed: false,
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
self.message_ids
|
self.message_ids
|
||||||
.insert(envelopes_lck[&env_hash].message_id().raw().to_vec(), new_id);
|
.insert(envelopes_lck[&env_hash].message_id().raw().to_vec(), new_id);
|
||||||
|
@ -795,13 +798,13 @@ impl Threads {
|
||||||
|
|
||||||
self.groups.insert(
|
self.groups.insert(
|
||||||
self.thread_nodes[&reply_to_id].group,
|
self.thread_nodes[&reply_to_id].group,
|
||||||
ThreadGroup::Group {
|
ThreadGroup::Root(Thread {
|
||||||
root: reply_to_id,
|
root: reply_to_id,
|
||||||
date: envelopes_lck[&env_hash].date(),
|
date: envelopes_lck[&env_hash].date(),
|
||||||
len: 0,
|
len: 0,
|
||||||
unseen: 0,
|
unseen: 0,
|
||||||
snoozed: false,
|
snoozed: false,
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
make!((reply_to_id) parent of (new_id), self);
|
make!((reply_to_id) parent of (new_id), self);
|
||||||
self.missing_message_ids.insert(r.to_vec());
|
self.missing_message_ids.insert(r.to_vec());
|
||||||
|
@ -838,13 +841,13 @@ impl Threads {
|
||||||
);
|
);
|
||||||
self.groups.insert(
|
self.groups.insert(
|
||||||
self.thread_nodes[&id].group,
|
self.thread_nodes[&id].group,
|
||||||
ThreadGroup::Group {
|
ThreadGroup::Root(Thread {
|
||||||
root: id,
|
root: id,
|
||||||
date: envelopes_lck[&env_hash].date(),
|
date: envelopes_lck[&env_hash].date(),
|
||||||
len: 0,
|
len: 0,
|
||||||
unseen: 0,
|
unseen: 0,
|
||||||
snoozed: false,
|
snoozed: false,
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
make!((id) parent of (current_descendant_id), self);
|
make!((id) parent of (current_descendant_id), self);
|
||||||
self.missing_message_ids.insert(reference.raw().to_vec());
|
self.missing_message_ids.insert(reference.raw().to_vec());
|
||||||
|
@ -960,18 +963,18 @@ impl Threads {
|
||||||
let envelopes = envelopes.read().unwrap();
|
let envelopes = envelopes.read().unwrap();
|
||||||
vec.sort_by(|a, b| match sort {
|
vec.sort_by(|a, b| match sort {
|
||||||
(SortField::Date, SortOrder::Desc) => {
|
(SortField::Date, SortOrder::Desc) => {
|
||||||
let a = self.groups[&a].date();
|
let a = self.thread_ref(*a).date();
|
||||||
let b = self.groups[&b].date();
|
let b = self.thread_ref(*b).date();
|
||||||
b.cmp(&a)
|
b.cmp(&a)
|
||||||
}
|
}
|
||||||
(SortField::Date, SortOrder::Asc) => {
|
(SortField::Date, SortOrder::Asc) => {
|
||||||
let a = self.groups[&a].date();
|
let a = self.thread_ref(*a).date();
|
||||||
let b = self.groups[&b].date();
|
let b = self.thread_ref(*b).date();
|
||||||
a.cmp(&b)
|
a.cmp(&b)
|
||||||
}
|
}
|
||||||
(SortField::Subject, SortOrder::Desc) => {
|
(SortField::Subject, SortOrder::Desc) => {
|
||||||
let a = &self.thread_nodes[&self.groups[&a].root().unwrap()].message();
|
let a = &self.thread_nodes[&self.thread_ref(*a).root()].message();
|
||||||
let b = &self.thread_nodes[&self.groups[&b].root().unwrap()].message();
|
let b = &self.thread_nodes[&self.thread_ref(*b).root()].message();
|
||||||
|
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
(Some(_), Some(_)) => {}
|
(Some(_), Some(_)) => {}
|
||||||
|
@ -999,8 +1002,8 @@ impl Threads {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(SortField::Subject, SortOrder::Asc) => {
|
(SortField::Subject, SortOrder::Asc) => {
|
||||||
let a = &self.thread_nodes[&self.groups[&a].root().unwrap()].message();
|
let a = &self.thread_nodes[&self.thread_ref(*a).root()].message();
|
||||||
let b = &self.thread_nodes[&self.groups[&b].root().unwrap()].message();
|
let b = &self.thread_nodes[&self.thread_ref(*b).root()].message();
|
||||||
|
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
(Some(_), Some(_)) => {}
|
(Some(_), Some(_)) => {}
|
||||||
|
@ -1040,17 +1043,13 @@ impl Threads {
|
||||||
let envelopes = envelopes.read().unwrap();
|
let envelopes = envelopes.read().unwrap();
|
||||||
vec.sort_by(|a, b| match sort {
|
vec.sort_by(|a, b| match sort {
|
||||||
(SortField::Date, SortOrder::Desc) => {
|
(SortField::Date, SortOrder::Desc) => {
|
||||||
let a_group = self.find_group(self.thread_nodes[&a].group);
|
let a = self.thread_ref(self.thread_nodes[&a].group).date();
|
||||||
let b_group = self.find_group(self.thread_nodes[&b].group);
|
let b = self.thread_ref(self.thread_nodes[&b].group).date();
|
||||||
let a = self.groups[&a_group].date();
|
|
||||||
let b = self.groups[&b_group].date();
|
|
||||||
b.cmp(&a)
|
b.cmp(&a)
|
||||||
}
|
}
|
||||||
(SortField::Date, SortOrder::Asc) => {
|
(SortField::Date, SortOrder::Asc) => {
|
||||||
let a_group = self.find_group(self.thread_nodes[&a].group);
|
let a = self.thread_ref(self.thread_nodes[&a].group).date();
|
||||||
let b_group = self.find_group(self.thread_nodes[&b].group);
|
let b = self.thread_ref(self.thread_nodes[&b].group).date();
|
||||||
let a = self.groups[&a_group].date();
|
|
||||||
let b = self.groups[&b_group].date();
|
|
||||||
a.cmp(&b)
|
a.cmp(&b)
|
||||||
}
|
}
|
||||||
(SortField::Subject, SortOrder::Desc) => {
|
(SortField::Subject, SortOrder::Desc) => {
|
||||||
|
@ -1120,17 +1119,13 @@ impl Threads {
|
||||||
let envelopes = envelopes.read().unwrap();
|
let envelopes = envelopes.read().unwrap();
|
||||||
tree.sort_by(|a, b| match sort {
|
tree.sort_by(|a, b| match sort {
|
||||||
(SortField::Date, SortOrder::Desc) => {
|
(SortField::Date, SortOrder::Desc) => {
|
||||||
let a_group = self.find_group(self.thread_nodes[&a].group);
|
let a = self.thread_ref(self.thread_nodes[&a].group).date();
|
||||||
let b_group = self.find_group(self.thread_nodes[&b].group);
|
let b = self.thread_ref(self.thread_nodes[&b].group).date();
|
||||||
let a = self.groups[&a_group].date();
|
|
||||||
let b = self.groups[&b_group].date();
|
|
||||||
b.cmp(&a)
|
b.cmp(&a)
|
||||||
}
|
}
|
||||||
(SortField::Date, SortOrder::Asc) => {
|
(SortField::Date, SortOrder::Asc) => {
|
||||||
let a_group = self.find_group(self.thread_nodes[&a].group);
|
let a = self.thread_ref(self.thread_nodes[&a].group).date();
|
||||||
let b_group = self.find_group(self.thread_nodes[&b].group);
|
let b = self.thread_ref(self.thread_nodes[&b].group).date();
|
||||||
let a = self.groups[&a_group].date();
|
|
||||||
let b = self.groups[&b_group].date();
|
|
||||||
a.cmp(&b)
|
a.cmp(&b)
|
||||||
}
|
}
|
||||||
(SortField::Subject, SortOrder::Desc) => {
|
(SortField::Subject, SortOrder::Desc) => {
|
||||||
|
|
|
@ -118,13 +118,14 @@ impl ListingTrait for CompactListing {
|
||||||
if self.length == 0 {
|
if self.length == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let thread = self.get_thread_under_cursor(idx, context);
|
let thread_hash = self.get_thread_under_cursor(idx, context);
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
||||||
let threads = &account.collection.threads[&folder_hash];
|
let threads = &account.collection.threads[&folder_hash];
|
||||||
|
let thread = threads.thread_ref(thread_hash);
|
||||||
|
|
||||||
let fg_color = if threads.groups[&thread].unseen() > 0 {
|
let fg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(0)
|
Color::Byte(0)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
|
@ -132,9 +133,9 @@ impl ListingTrait for CompactListing {
|
||||||
let bg_color = if context.settings.terminal.theme == "light" {
|
let bg_color = if context.settings.terminal.theme == "light" {
|
||||||
if self.cursor_pos.2 == idx {
|
if self.cursor_pos.2 == idx {
|
||||||
Color::Byte(244)
|
Color::Byte(244)
|
||||||
} else if self.selection[&thread] {
|
} else if self.selection[&thread_hash] {
|
||||||
Color::Byte(210)
|
Color::Byte(210)
|
||||||
} else if threads.groups[&thread].unseen() > 0 {
|
} else if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else if idx % 2 == 0 {
|
} else if idx % 2 == 0 {
|
||||||
Color::Byte(252)
|
Color::Byte(252)
|
||||||
|
@ -144,9 +145,9 @@ impl ListingTrait for CompactListing {
|
||||||
} else {
|
} else {
|
||||||
if self.cursor_pos.2 == idx {
|
if self.cursor_pos.2 == idx {
|
||||||
Color::Byte(246)
|
Color::Byte(246)
|
||||||
} else if self.selection[&thread] {
|
} else if self.selection[&thread_hash] {
|
||||||
Color::Byte(210)
|
Color::Byte(210)
|
||||||
} else if threads.groups[&thread].unseen() > 0 {
|
} else if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else if idx % 2 == 0 {
|
} else if idx % 2 == 0 {
|
||||||
Color::Byte(236)
|
Color::Byte(236)
|
||||||
|
@ -549,7 +550,7 @@ impl CompactListing {
|
||||||
threads: &Threads,
|
threads: &Threads,
|
||||||
hash: ThreadHash,
|
hash: ThreadHash,
|
||||||
) -> EntryStrings {
|
) -> EntryStrings {
|
||||||
let thread = &threads.groups[&hash];
|
let thread = threads.thread_ref(hash);
|
||||||
let folder_hash = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
let folder_hash = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.folder
|
.folder
|
||||||
|
@ -714,7 +715,7 @@ impl CompactListing {
|
||||||
for (idx, thread) in items.enumerate() {
|
for (idx, thread) in items.enumerate() {
|
||||||
debug!(thread);
|
debug!(thread);
|
||||||
self.length += 1;
|
self.length += 1;
|
||||||
let thread_node = &threads.thread_nodes()[&threads.groups[&thread].root().unwrap()];
|
let thread_node = &threads.thread_nodes()[&threads.thread_ref(thread).root()];
|
||||||
let root_env_hash = thread_node.message().unwrap_or_else(|| {
|
let root_env_hash = thread_node.message().unwrap_or_else(|| {
|
||||||
let mut iter_ptr = thread_node.children()[0];
|
let mut iter_ptr = thread_node.children()[0];
|
||||||
while threads.thread_nodes()[&iter_ptr].message().is_none() {
|
while threads.thread_nodes()[&iter_ptr].message().is_none() {
|
||||||
|
@ -811,13 +812,14 @@ impl CompactListing {
|
||||||
|
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let fg_color = if threads.groups[&thread].unseen() > 0 {
|
let thread = threads.thread_ref(thread);
|
||||||
|
let fg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(0)
|
Color::Byte(0)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
};
|
};
|
||||||
let bg_color = if context.settings.terminal.theme == "light" {
|
let bg_color = if context.settings.terminal.theme == "light" {
|
||||||
if threads.groups[&thread].unseen() > 0 {
|
if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else if idx % 2 == 0 {
|
} else if idx % 2 == 0 {
|
||||||
Color::Byte(252)
|
Color::Byte(252)
|
||||||
|
@ -825,7 +827,7 @@ impl CompactListing {
|
||||||
Color::Default
|
Color::Default
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if threads.groups[&thread].unseen() > 0 {
|
if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else if idx % 2 == 0 {
|
} else if idx % 2 == 0 {
|
||||||
Color::Byte(236)
|
Color::Byte(236)
|
||||||
|
@ -921,7 +923,7 @@ impl CompactListing {
|
||||||
self.data_columns.columns[4][(x, idx)].set_bg(bg_color);
|
self.data_columns.columns[4][(x, idx)].set_bg(bg_color);
|
||||||
}
|
}
|
||||||
match (
|
match (
|
||||||
threads.groups[&thread].snoozed(),
|
thread.snoozed(),
|
||||||
context.accounts[self.cursor_pos.0]
|
context.accounts[self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(root_env_hash)
|
.get_env(root_env_hash)
|
||||||
|
@ -983,9 +985,9 @@ impl CompactListing {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
||||||
let threads = &account.collection.threads[&folder_hash];
|
let threads = &account.collection.threads[&folder_hash];
|
||||||
if let Some(env_hash) =
|
let thread = threads.thread_ref(thread_hash);
|
||||||
threads.thread_nodes()[&threads.groups[&thread_hash].root().unwrap()].message()
|
// FIXME: Thread root doesn't nessessarily have message set
|
||||||
{
|
if let Some(env_hash) = threads.thread_nodes()[&thread.root()].message() {
|
||||||
if !account.contains_key(env_hash) {
|
if !account.contains_key(env_hash) {
|
||||||
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
||||||
* arrive */
|
* arrive */
|
||||||
|
@ -993,14 +995,14 @@ impl CompactListing {
|
||||||
}
|
}
|
||||||
let envelope: EnvelopeRef = account.collection.get_env(env_hash);
|
let envelope: EnvelopeRef = account.collection.get_env(env_hash);
|
||||||
let has_attachments = envelope.has_attachments();
|
let has_attachments = envelope.has_attachments();
|
||||||
let fg_color = if threads.groups[&thread_hash].unseen() > 0 {
|
let fg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(0)
|
Color::Byte(0)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
};
|
};
|
||||||
let idx = self.order[&thread_hash];
|
let idx = self.order[&thread_hash];
|
||||||
let bg_color = if context.settings.terminal.theme == "light" {
|
let bg_color = if context.settings.terminal.theme == "light" {
|
||||||
if threads.groups[&thread_hash].unseen() > 0 {
|
if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else if idx % 2 == 0 {
|
} else if idx % 2 == 0 {
|
||||||
Color::Byte(252)
|
Color::Byte(252)
|
||||||
|
@ -1008,7 +1010,7 @@ impl CompactListing {
|
||||||
Color::Default
|
Color::Default
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if threads.groups[&thread_hash].unseen() > 0 {
|
if thread.unseen() > 0 {
|
||||||
Color::Byte(253)
|
Color::Byte(253)
|
||||||
} else if idx % 2 == 0 {
|
} else if idx % 2 == 0 {
|
||||||
Color::Byte(236)
|
Color::Byte(236)
|
||||||
|
@ -1117,7 +1119,7 @@ impl CompactListing {
|
||||||
columns[4][c].set_ch(' ');
|
columns[4][c].set_ch(' ');
|
||||||
columns[4][c].set_bg(bg_color);
|
columns[4][c].set_bg(bg_color);
|
||||||
}
|
}
|
||||||
match (threads.groups[&thread_hash].snoozed(), has_attachments) {
|
match (thread.snoozed(), has_attachments) {
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
columns[3][(0, idx)].set_fg(Color::Byte(103));
|
columns[3][(0, idx)].set_fg(Color::Byte(103));
|
||||||
columns[3][(2, idx)].set_fg(Color::Red);
|
columns[3][(2, idx)].set_fg(Color::Red);
|
||||||
|
@ -1246,41 +1248,45 @@ impl Component for CompactListing {
|
||||||
let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
||||||
self.selection.entry(thread_hash).and_modify(|e| *e = !*e);
|
self.selection.entry(thread_hash).and_modify(|e| *e = !*e);
|
||||||
}
|
}
|
||||||
UIEvent::Action(ref action) => match action {
|
UIEvent::Action(ref action) => {
|
||||||
Action::Sort(field, order) if !self.unfocused => {
|
match action {
|
||||||
debug!("Sort {:?} , {:?}", field, order);
|
Action::Sort(field, order) if !self.unfocused => {
|
||||||
self.sort = (*field, *order);
|
debug!("Sort {:?} , {:?}", field, order);
|
||||||
if !self.filtered_selection.is_empty() {
|
self.sort = (*field, *order);
|
||||||
// FIXME: perform sort
|
if !self.filtered_selection.is_empty() {
|
||||||
self.dirty = true;
|
// FIXME: perform sort
|
||||||
} else {
|
self.dirty = true;
|
||||||
self.refresh_mailbox(context);
|
} else {
|
||||||
|
self.refresh_mailbox(context);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Action::SubSort(field, order) if !self.unfocused => {
|
||||||
|
debug!("SubSort {:?} , {:?}", field, order);
|
||||||
|
self.subsort = (*field, *order);
|
||||||
|
// FIXME: perform subsort.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Action::ToggleThreadSnooze if !self.unfocused => {
|
||||||
|
let thread = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
||||||
|
let account = &mut context.accounts[self.cursor_pos.0];
|
||||||
|
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
||||||
|
account
|
||||||
|
.collection
|
||||||
|
.threads
|
||||||
|
.entry(folder_hash)
|
||||||
|
.and_modify(|threads| {
|
||||||
|
let is_snoozed = threads.thread_ref(thread).snoozed();
|
||||||
|
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
||||||
|
});
|
||||||
|
self.row_updates.push(thread);
|
||||||
|
self.refresh_mailbox(context);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Action::SubSort(field, order) if !self.unfocused => {
|
|
||||||
debug!("SubSort {:?} , {:?}", field, order);
|
|
||||||
self.subsort = (*field, *order);
|
|
||||||
// FIXME: perform subsort.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Action::ToggleThreadSnooze if !self.unfocused => {
|
|
||||||
let thread = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
|
||||||
let account = &mut context.accounts[self.cursor_pos.0];
|
|
||||||
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
|
||||||
let threads = account.collection.threads.entry(folder_hash).or_default();
|
|
||||||
let is_snoozed = threads.groups[&thread].snoozed();
|
|
||||||
threads
|
|
||||||
.groups
|
|
||||||
.entry(thread)
|
|
||||||
.and_modify(|entry| entry.set_snoozed(!is_snoozed));
|
|
||||||
self.row_updates.push(thread);
|
|
||||||
self.refresh_mailbox(context);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,22 +149,23 @@ impl ListingTrait for ConversationsListing {
|
||||||
if self.length == 0 {
|
if self.length == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let thread = self.get_thread_under_cursor(idx, context);
|
let thread_hash = self.get_thread_under_cursor(idx, context);
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
||||||
let threads = &account.collection.threads[&folder_hash];
|
let threads = &account.collection.threads[&folder_hash];
|
||||||
|
let thread = threads.thread_ref(thread_hash);
|
||||||
|
|
||||||
let fg_color = if threads.groups[&thread].unseen() > 0 {
|
let fg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(0)
|
Color::Byte(0)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
};
|
};
|
||||||
let bg_color = if self.cursor_pos.2 == idx {
|
let bg_color = if self.cursor_pos.2 == idx {
|
||||||
Color::Byte(246)
|
Color::Byte(246)
|
||||||
} else if self.selection[&thread] {
|
} else if self.selection[&thread_hash] {
|
||||||
Color::Byte(210)
|
Color::Byte(210)
|
||||||
} else if threads.groups[&thread].unseen() > 0 {
|
} else if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
|
@ -186,7 +187,7 @@ impl ListingTrait for ConversationsListing {
|
||||||
let (upper_left, bottom_right) = area;
|
let (upper_left, bottom_right) = area;
|
||||||
let width = self.content.size().0;
|
let width = self.content.size().0;
|
||||||
let (x, y) = upper_left;
|
let (x, y) = upper_left;
|
||||||
if self.cursor_pos.2 == idx || self.selection[&thread] {
|
if self.cursor_pos.2 == idx || self.selection[&thread_hash] {
|
||||||
for x in x..=get_x(bottom_right) {
|
for x in x..=get_x(bottom_right) {
|
||||||
grid[(x, y)].set_fg(fg_color);
|
grid[(x, y)].set_fg(fg_color);
|
||||||
grid[(x, y)].set_bg(bg_color);
|
grid[(x, y)].set_bg(bg_color);
|
||||||
|
@ -522,7 +523,7 @@ impl ConversationsListing {
|
||||||
threads: &Threads,
|
threads: &Threads,
|
||||||
hash: ThreadHash,
|
hash: ThreadHash,
|
||||||
) -> EntryStrings {
|
) -> EntryStrings {
|
||||||
let thread = &threads.groups[&hash];
|
let thread = threads.thread_ref(hash);
|
||||||
let folder_hash = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
let folder_hash = &context.accounts[self.cursor_pos.0][self.cursor_pos.1]
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.folder
|
.folder
|
||||||
|
@ -676,7 +677,7 @@ impl ConversationsListing {
|
||||||
std::collections::HashSet::new();
|
std::collections::HashSet::new();
|
||||||
for (idx, thread) in items.enumerate() {
|
for (idx, thread) in items.enumerate() {
|
||||||
self.length += 1;
|
self.length += 1;
|
||||||
let thread_node = &threads.thread_nodes()[&threads.groups[&thread].root().unwrap()];
|
let thread_node = &threads.thread_nodes()[&threads.thread_ref(thread).root()];
|
||||||
let root_env_hash = thread_node.message().unwrap_or_else(|| {
|
let root_env_hash = thread_node.message().unwrap_or_else(|| {
|
||||||
let mut iter_ptr = thread_node.children()[0];
|
let mut iter_ptr = thread_node.children()[0];
|
||||||
while threads.thread_nodes()[&iter_ptr].message().is_none() {
|
while threads.thread_nodes()[&iter_ptr].message().is_none() {
|
||||||
|
@ -750,12 +751,13 @@ impl ConversationsListing {
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(root_env_hash) {
|
if !context.accounts[self.cursor_pos.0].contains_key(root_env_hash) {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let fg_color = if threads.groups[&thread].unseen() > 0 {
|
let thread = threads.thread_ref(thread);
|
||||||
|
let fg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(0)
|
Color::Byte(0)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
};
|
};
|
||||||
let bg_color = if threads.groups[&thread].unseen() > 0 {
|
let bg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
|
@ -919,19 +921,18 @@ impl ConversationsListing {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
||||||
let threads = &account.collection.threads[&folder_hash];
|
let threads = &account.collection.threads[&folder_hash];
|
||||||
|
let thread = threads.thread_ref(thread_hash);
|
||||||
let idx: usize = self.order[&thread_hash];
|
let idx: usize = self.order[&thread_hash];
|
||||||
let width = self.content.size().0;
|
let width = self.content.size().0;
|
||||||
|
|
||||||
let env_hash = threads.thread_nodes()[&threads.groups[&thread_hash].root().unwrap()]
|
let env_hash = threads.thread_nodes()[&thread.root()].message().unwrap();
|
||||||
.message()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let fg_color = if threads.groups[&thread_hash].unseen() > 0 {
|
let fg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(0)
|
Color::Byte(0)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
};
|
};
|
||||||
let bg_color = if threads.groups[&thread_hash].unseen() > 0 {
|
let bg_color = if thread.unseen() > 0 {
|
||||||
Color::Byte(251)
|
Color::Byte(251)
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
|
@ -1262,12 +1263,14 @@ impl Component for ConversationsListing {
|
||||||
let thread = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
let thread = self.get_thread_under_cursor(self.cursor_pos.2, context);
|
||||||
let account = &mut context.accounts[self.cursor_pos.0];
|
let account = &mut context.accounts[self.cursor_pos.0];
|
||||||
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
let folder_hash = account[self.cursor_pos.1].unwrap().folder.hash();
|
||||||
let threads = account.collection.threads.entry(folder_hash).or_default();
|
account
|
||||||
let is_snoozed = threads.groups[&thread].snoozed();
|
.collection
|
||||||
threads
|
.threads
|
||||||
.groups
|
.entry(folder_hash)
|
||||||
.entry(thread)
|
.and_modify(|threads| {
|
||||||
.and_modify(|entry| entry.set_snoozed(!is_snoozed));
|
let is_snoozed = threads.thread_ref(thread).snoozed();
|
||||||
|
threads.thread_ref_mut(thread).set_snoozed(!is_snoozed);
|
||||||
|
});
|
||||||
self.row_updates.push(thread);
|
self.row_updates.push(thread);
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -599,7 +599,10 @@ impl Account {
|
||||||
self.collection.threads[&folder_hash]
|
self.collection.threads[&folder_hash]
|
||||||
.find_group(self.collection.threads[&folder_hash][&thread_hash].group)
|
.find_group(self.collection.threads[&folder_hash][&thread_hash].group)
|
||||||
};
|
};
|
||||||
if self.collection.threads[&folder_hash].groups[&thread].snoozed() {
|
if self.collection.threads[&folder_hash]
|
||||||
|
.thread_ref(thread)
|
||||||
|
.snoozed()
|
||||||
|
{
|
||||||
return Some(UIEvent::MailboxUpdate((self.index, folder_hash)));
|
return Some(UIEvent::MailboxUpdate((self.index, folder_hash)));
|
||||||
}
|
}
|
||||||
if is_seen || is_draft {
|
if is_seen || is_draft {
|
||||||
|
|
Loading…
Reference in New Issue