/*
* 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 components::utilities::PageMovement;
use std::cmp;
use std::ops::{Deref, DerefMut};
//use melib::mailbox::backends::BackendOp;
const MAX_COLS: usize = 500;
#[derive(Debug)]
struct MailboxView {
/// (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.
content: CellBuffer,
/// 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,
}
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));
impl fmt::Display for MailboxView {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", MailboxView::DESCRIPTION)
}
}
impl MailboxView {
const DESCRIPTION: &'static str = "";
/// Helper function to format entry strings for CompactListing */
/* TODO: Make this configurable */
fn make_entry_string(
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,
if is_snoozed { " 💤" } else { "" }
)),
)
} else {
(
IndexNoString(idx.to_string()),
FromString(address_list!((e.from()) as comma_sep_list)),
DateString(MailboxView::format_date(e)),
SubjectString(format!(
"{}{}",
e.subject(),
if is_snoozed { " 💤" } else { "" }
)),
)
}
}
fn new() -> Self {
let content = CellBuffer::new(0, 0, Cell::with_char(' '));
MailboxView {
cursor_pos: (0, 1, 0),
new_cursor_pos: (0, 0, 0),
length: 0,
sort: (Default::default(), Default::default()),
subsort: (SortField::Date, SortOrder::Desc),
order: FnvHashMap::default(),
row_updates: StackVec::new(),
content,
dirty: true,
unfocused: false,
view: ThreadView::default(),
movement: None,
id: ComponentId::new_v4(),
}
}
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
/// chosen.
fn refresh_mailbox(&mut self, context: &mut Context) {
self.dirty = true;
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
{
self.cursor_pos.2 = 0;
self.new_cursor_pos.2 = 0;
}
self.cursor_pos.1 = self.new_cursor_pos.1;
self.cursor_pos.0 =