Some listing refactoring
parent
f58ed387dd
commit
0ac10aa4d0
|
@ -141,6 +141,9 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
|
|
||||||
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]>;
|
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]>;
|
||||||
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]>;
|
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]>;
|
||||||
|
fn redraw_list(&mut self, context: &Context, items: Box<dyn Iterator<Item = ThreadHash>>) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ListingTrait: Component {
|
pub trait ListingTrait: Component {
|
||||||
|
|
|
@ -469,7 +469,11 @@ impl ListingTrait for CompactListing {
|
||||||
self.data_columns.columns[0] =
|
self.data_columns.columns[0] =
|
||||||
CellBuffer::new_with_context(0, 0, Cell::with_char(' '), context);
|
CellBuffer::new_with_context(0, 0, Cell::with_char(' '), context);
|
||||||
}
|
}
|
||||||
self.redraw_list(context);
|
self.redraw_list(
|
||||||
|
context,
|
||||||
|
Box::new(self.filtered_selection.clone().into_iter())
|
||||||
|
as Box<dyn Iterator<Item = ThreadHash>>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.cursor_pos.2 = 0;
|
self.cursor_pos.2 = 0;
|
||||||
|
@ -545,9 +549,13 @@ impl CompactListing {
|
||||||
&self,
|
&self,
|
||||||
e: &Envelope,
|
e: &Envelope,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
thread_node: &ThreadNode,
|
threads: &Threads,
|
||||||
is_snoozed: bool,
|
hash: ThreadHash,
|
||||||
) -> EntryStrings {
|
) -> EntryStrings {
|
||||||
|
let is_snoozed: bool = threads.is_snoozed(hash);
|
||||||
|
let date =
|
||||||
|
threads.thread_dates[&melib::thread::find_thread_group(threads.thread_nodes(), hash)];
|
||||||
|
let thread_node = &threads[&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
|
||||||
|
@ -591,7 +599,7 @@ impl CompactListing {
|
||||||
subject.truncate_at_boundary(150);
|
subject.truncate_at_boundary(150);
|
||||||
if thread_node.len() > 0 {
|
if thread_node.len() > 0 {
|
||||||
EntryStrings {
|
EntryStrings {
|
||||||
date: DateString(ConversationsListing::format_date(context, thread_node)),
|
date: DateString(ConversationsListing::format_date(context, date)),
|
||||||
subject: SubjectString(format!("{} ({})", subject, thread_node.len(),)),
|
subject: SubjectString(format!("{} ({})", subject, thread_node.len(),)),
|
||||||
flag: FlagString(format!(
|
flag: FlagString(format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -603,7 +611,7 @@ impl CompactListing {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EntryStrings {
|
EntryStrings {
|
||||||
date: DateString(ConversationsListing::format_date(context, thread_node)),
|
date: DateString(ConversationsListing::format_date(context, date)),
|
||||||
subject: SubjectString(subject),
|
subject: SubjectString(subject),
|
||||||
flag: FlagString(format!(
|
flag: FlagString(format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -667,10 +675,22 @@ impl CompactListing {
|
||||||
self.view = ThreadView::new(self.new_cursor_pos, None, context);
|
self.view = ThreadView::new(self.new_cursor_pos, None, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.redraw_list(context);
|
let threads = &context.accounts[self.cursor_pos.0].collection.threads[&folder_hash];
|
||||||
|
threads.sort_by(
|
||||||
|
self.sort,
|
||||||
|
self.subsort,
|
||||||
|
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
||||||
|
);
|
||||||
|
self.all_threads.clear();
|
||||||
|
|
||||||
|
self.redraw_list(
|
||||||
|
context,
|
||||||
|
Box::new(threads.root_iter().collect::<Vec<ThreadHash>>().into_iter())
|
||||||
|
as Box<dyn Iterator<Item = ThreadHash>>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redraw_list(&mut self, context: &Context) {
|
fn redraw_list(&mut self, context: &Context, items: Box<dyn Iterator<Item = ThreadHash>>) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[self.cursor_pos.0];
|
||||||
let mailbox = &account[self.cursor_pos.1].unwrap();
|
let mailbox = &account[self.cursor_pos.1].unwrap();
|
||||||
|
|
||||||
|
@ -694,18 +714,7 @@ impl CompactListing {
|
||||||
SmallVec::new(),
|
SmallVec::new(),
|
||||||
);
|
);
|
||||||
|
|
||||||
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
|
for (idx, root_idx) in items.enumerate() {
|
||||||
|
|
||||||
let mut refresh_mailbox = false;
|
|
||||||
let threads_iter = if self.filter_term.is_empty() {
|
|
||||||
refresh_mailbox = true;
|
|
||||||
self.all_threads.clear();
|
|
||||||
Box::new(threads.root_iter()) as Box<dyn Iterator<Item = ThreadHash>>
|
|
||||||
} else {
|
|
||||||
Box::new(self.filtered_selection.iter().map(|h| *h))
|
|
||||||
as Box<dyn Iterator<Item = ThreadHash>>
|
|
||||||
};
|
|
||||||
for (idx, root_idx) in threads_iter.enumerate() {
|
|
||||||
self.length += 1;
|
self.length += 1;
|
||||||
let thread_node = &threads.thread_nodes()[&root_idx];
|
let thread_node = &threads.thread_nodes()[&root_idx];
|
||||||
let i = thread_node.message().unwrap_or_else(|| {
|
let i = thread_node.message().unwrap_or_else(|| {
|
||||||
|
@ -729,12 +738,7 @@ impl CompactListing {
|
||||||
let root_envelope: EnvelopeRef =
|
let root_envelope: EnvelopeRef =
|
||||||
context.accounts[self.cursor_pos.0].collection.get_env(i);
|
context.accounts[self.cursor_pos.0].collection.get_env(i);
|
||||||
|
|
||||||
let entry_strings = self.make_entry_string(
|
let entry_strings = self.make_entry_string(&root_envelope, context, threads, root_idx);
|
||||||
&root_envelope,
|
|
||||||
context,
|
|
||||||
thread_node,
|
|
||||||
threads.is_snoozed(root_idx),
|
|
||||||
);
|
|
||||||
row_widths.1.push(
|
row_widths.1.push(
|
||||||
entry_strings
|
entry_strings
|
||||||
.date
|
.date
|
||||||
|
@ -768,10 +772,8 @@ impl CompactListing {
|
||||||
min_width.4,
|
min_width.4,
|
||||||
entry_strings.subject.grapheme_width() + 1 + entry_strings.tags.grapheme_width(),
|
entry_strings.subject.grapheme_width() + 1 + entry_strings.tags.grapheme_width(),
|
||||||
); /* subject */
|
); /* subject */
|
||||||
rows.push(entry_strings);
|
rows.push(((idx, root_idx), entry_strings));
|
||||||
if refresh_mailbox {
|
|
||||||
self.all_threads.insert(root_idx);
|
self.all_threads.insert(root_idx);
|
||||||
}
|
|
||||||
|
|
||||||
self.order.insert(root_idx, idx);
|
self.order.insert(root_idx, idx);
|
||||||
self.selection.insert(root_idx, false);
|
self.selection.insert(root_idx, false);
|
||||||
|
@ -797,14 +799,8 @@ impl CompactListing {
|
||||||
self.data_columns.columns[4] =
|
self.data_columns.columns[4] =
|
||||||
CellBuffer::new_with_context(min_width.4, rows.len(), Cell::with_char(' '), context);
|
CellBuffer::new_with_context(min_width.4, rows.len(), Cell::with_char(' '), context);
|
||||||
self.data_columns.segment_tree[4] = row_widths.4.into();
|
self.data_columns.segment_tree[4] = row_widths.4.into();
|
||||||
let threads_iter = if self.filter_term.is_empty() {
|
|
||||||
Box::new(threads.root_iter()) as Box<dyn Iterator<Item = ThreadHash>>
|
|
||||||
} else {
|
|
||||||
Box::new(self.filtered_selection.iter().map(|h| *h))
|
|
||||||
as Box<dyn Iterator<Item = ThreadHash>>
|
|
||||||
};
|
|
||||||
|
|
||||||
for ((idx, root_idx), strings) in threads_iter.enumerate().zip(rows) {
|
for ((idx, root_idx), strings) in rows {
|
||||||
let thread_node = &threads.thread_nodes()[&root_idx];
|
let thread_node = &threads.thread_nodes()[&root_idx];
|
||||||
let i = thread_node.message().unwrap_or_else(|| {
|
let i = thread_node.message().unwrap_or_else(|| {
|
||||||
let mut iter_ptr = thread_node.children()[0];
|
let mut iter_ptr = thread_node.children()[0];
|
||||||
|
@ -975,11 +971,19 @@ impl CompactListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_thread_under_cursor(&self, cursor: usize, context: &Context) -> ThreadHash {
|
fn get_thread_under_cursor(&self, cursor: usize, context: &Context) -> ThreadHash {
|
||||||
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];
|
|
||||||
if self.filter_term.is_empty() {
|
if self.filter_term.is_empty() {
|
||||||
threads.root_set(cursor)
|
*self
|
||||||
|
.order
|
||||||
|
.iter()
|
||||||
|
.find(|(_, &r)| r == cursor)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
debug!("self.order empty ? cursor={} {:#?}", cursor, &self.order);
|
||||||
|
panic!();
|
||||||
|
})
|
||||||
|
.0
|
||||||
|
//threads.root_set(cursor)
|
||||||
} else {
|
} else {
|
||||||
self.filtered_selection[cursor]
|
self.filtered_selection[cursor]
|
||||||
}
|
}
|
||||||
|
@ -1020,12 +1024,7 @@ impl CompactListing {
|
||||||
Color::Default
|
Color::Default
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let strings = self.make_entry_string(
|
let strings = self.make_entry_string(&envelope, context, threads, thread_hash);
|
||||||
&envelope,
|
|
||||||
context,
|
|
||||||
&threads[&thread_hash],
|
|
||||||
threads.is_snoozed(thread_hash),
|
|
||||||
);
|
|
||||||
drop(envelope);
|
drop(envelope);
|
||||||
let columns = &mut self.data_columns.columns;
|
let columns = &mut self.data_columns.columns;
|
||||||
let min_width = (
|
let min_width = (
|
||||||
|
|
|
@ -562,7 +562,10 @@ impl ConversationsListing {
|
||||||
subject.truncate_at_boundary(150);
|
subject.truncate_at_boundary(150);
|
||||||
if thread_node.len() > 0 {
|
if thread_node.len() > 0 {
|
||||||
EntryStrings {
|
EntryStrings {
|
||||||
date: DateString(ConversationsListing::format_date(context, thread_node)),
|
date: DateString(ConversationsListing::format_date(
|
||||||
|
context,
|
||||||
|
thread_node.date(),
|
||||||
|
)),
|
||||||
subject: SubjectString(format!("{} ({})", subject, thread_node.len(),)),
|
subject: SubjectString(format!("{} ({})", subject, thread_node.len(),)),
|
||||||
flag: FlagString(format!(
|
flag: FlagString(format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -574,7 +577,10 @@ impl ConversationsListing {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EntryStrings {
|
EntryStrings {
|
||||||
date: DateString(ConversationsListing::format_date(context, thread_node)),
|
date: DateString(ConversationsListing::format_date(
|
||||||
|
context,
|
||||||
|
thread_node.date(),
|
||||||
|
)),
|
||||||
subject: SubjectString(subject),
|
subject: SubjectString(subject),
|
||||||
flag: FlagString(format!(
|
flag: FlagString(format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
|
@ -890,8 +896,8 @@ impl ConversationsListing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn format_date(context: &Context, thread_node: &ThreadNode) -> String {
|
pub(super) fn format_date(context: &Context, epoch: UnixTimestamp) -> String {
|
||||||
let d = std::time::UNIX_EPOCH + std::time::Duration::from_secs(thread_node.date());
|
let d = std::time::UNIX_EPOCH + std::time::Duration::from_secs(epoch);
|
||||||
let now: std::time::Duration = std::time::SystemTime::now()
|
let now: std::time::Duration = std::time::SystemTime::now()
|
||||||
.duration_since(d)
|
.duration_since(d)
|
||||||
.unwrap_or_else(|_| std::time::Duration::new(std::u64::MAX, 0));
|
.unwrap_or_else(|_| std::time::Duration::new(std::u64::MAX, 0));
|
||||||
|
@ -912,7 +918,7 @@ impl ConversationsListing {
|
||||||
if n / (24 * 60 * 60) == 1 { "" } else { "s" }
|
if n / (24 * 60 * 60) == 1 { "" } else { "s" }
|
||||||
),
|
),
|
||||||
_ => melib::datetime::timestamp_to_string(
|
_ => melib::datetime::timestamp_to_string(
|
||||||
thread_node.date(),
|
epoch,
|
||||||
context
|
context
|
||||||
.settings
|
.settings
|
||||||
.listing
|
.listing
|
||||||
|
@ -925,11 +931,20 @@ impl ConversationsListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_thread_under_cursor(&self, cursor: usize, context: &Context) -> ThreadHash {
|
fn get_thread_under_cursor(&self, cursor: usize, context: &Context) -> ThreadHash {
|
||||||
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 self.filter_term.is_empty() {
|
if self.filter_term.is_empty() {
|
||||||
threads.root_set(cursor)
|
*self
|
||||||
|
.order
|
||||||
|
.iter()
|
||||||
|
.find(|(_, &r)| r == cursor)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
debug!("self.order empty ? cursor={} {:#?}", cursor, &self.order);
|
||||||
|
panic!();
|
||||||
|
})
|
||||||
|
.0
|
||||||
|
//threads.root_set(cursor)
|
||||||
} else {
|
} else {
|
||||||
self.filtered_selection[cursor]
|
self.filtered_selection[cursor]
|
||||||
}
|
}
|
||||||
|
|
|
@ -418,9 +418,10 @@ impl Component for MailView {
|
||||||
format!("Subject: {}", envelope.subject())
|
format!("Subject: {}", envelope.subject())
|
||||||
format!("Message-ID: <{}>", envelope.message_id_raw())
|
format!("Message-ID: <{}>", envelope.message_id_raw())
|
||||||
);
|
);
|
||||||
if self.expand_headers && envelope.in_reply_to().is_some() {
|
if self.expand_headers {
|
||||||
|
if let Some(val) = envelope.in_reply_to_display() {
|
||||||
print_header!(
|
print_header!(
|
||||||
format!("In-Reply-To: {}", envelope.in_reply_to_display().unwrap())
|
format!("In-Reply-To: {}", val)
|
||||||
format!(
|
format!(
|
||||||
"References: {}",
|
"References: {}",
|
||||||
envelope
|
envelope
|
||||||
|
@ -432,6 +433,7 @@ impl Component for MailView {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if let Some(list_management::ListActions {
|
if let Some(list_management::ListActions {
|
||||||
ref id,
|
ref id,
|
||||||
ref archive,
|
ref archive,
|
||||||
|
|
Loading…
Reference in New Issue