/*
* meli - ui crate.
*
* Copyright 2017-2018 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use super::*;
use crate::components::utilities::PageMovement;
use std::cmp;
use std::ops::{Deref, DerefMut};
//use melib::mailbox::backends::BackendOp;
const MAX_COLS: usize = 500;
macro_rules! address_list {
(($name:expr) as comma_sep_list) => {{
let mut ret: String =
$name
.into_iter()
.fold(String::new(), |mut s: String, n: &Address| {
s.extend(n.to_string().chars());
s.push_str(", ");
s
});
ret.pop();
ret.pop();
ret
}};
}
macro_rules! column_str {
(
struct $name:ident(String)) => {
pub struct $name(String);
impl Deref for $name {
type Target = String;
fn deref(&self) -> &String {
&self.0
}
}
impl DerefMut for $name {
fn deref_mut(&mut self) -> &mut String {
&mut self.0
}
}
};
}
column_str!(struct IndexNoString(String));
column_str!(struct DateString(String));
column_str!(struct FromString(String));
column_str!(struct SubjectString(String));
column_str!(struct FlagString(String));
/// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a
/// `ThreadView`.
#[derive(Debug)]
pub struct CompactListing {
/// (x, y, z): x is accounts, y is folders, z is index inside a folder.
cursor_pos: (usize, usize, usize),
new_cursor_pos: (usize, usize, usize),
length: usize,
sort: (SortField, SortOrder),
subsort: (SortField, SortOrder),
order: FnvHashMap<EnvelopeHash, usize>,
/// Cache current view.
data_columns: DataColumns,
/// If we must redraw on next redraw event
dirty: bool,
/// If `self.view` exists or not.
unfocused: bool,
view: ThreadView,
row_updates: StackVec<EnvelopeHash>,
movement: Option<PageMovement>,
id: ComponentId,
}
impl ListingTrait for CompactListing {
fn coordinates(&self) -> (usize, usize, Option<EnvelopeHash>) {
(self.cursor_pos.0, self.cursor_pos.1, None)
}
fn set_coordinates(&mut self, coordinates: (usize, usize, Option<EnvelopeHash>)) {
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.unfocused = false;
}
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context) {
let is_seen = {
if self.length == 0 {
return;
}
let account = &context.accounts[self.cursor_pos.0];
let mailbox = account[self.cursor_pos.1].as_ref().unwrap();
let threads = &account.collection.threads[&mailbox.folder.hash()];
let thread_node = threads.root_set(idx);
let thread_node = &threads.thread_nodes()[&thread_node];
let i = if let Some(i) = thread_node.message() {
i
} else {
let mut iter_ptr = thread_node.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_envelope: &Envelope = &account.get_env(&i);
root_envelope.is_seen()
};
let fg_color = if !is_seen {
Color::Byte(0)
} else {
Color::Default
};