2021-03-09 11:21:23 +00:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
use chrono::{DateTime, Duration, Local, Datelike};
|
|
|
|
use chrono_humanize::HumanTime;
|
2021-03-09 00:26:18 +00:00
|
|
|
use panorama_imap::response::Envelope;
|
2021-03-02 03:39:55 +00:00
|
|
|
use tui::{
|
|
|
|
buffer::Buffer,
|
2021-03-07 00:56:35 +00:00
|
|
|
layout::{Constraint, Direction, Layout, Rect},
|
|
|
|
style::{Color, Modifier, Style},
|
2021-03-08 23:07:44 +00:00
|
|
|
text::{Span, Spans},
|
2021-03-07 00:56:35 +00:00
|
|
|
widgets::*,
|
2021-03-02 03:39:55 +00:00
|
|
|
};
|
2021-03-01 09:50:20 +00:00
|
|
|
|
2021-03-07 00:56:35 +00:00
|
|
|
use super::FrameType;
|
2021-03-01 09:50:20 +00:00
|
|
|
|
2021-03-09 00:26:18 +00:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct MailTabState {
|
|
|
|
pub folders: Vec<String>,
|
2021-03-09 11:21:23 +00:00
|
|
|
pub message_uids: Vec<u32>,
|
|
|
|
pub message_map: HashMap<u32, EmailMetadata>,
|
2021-03-09 00:26:18 +00:00
|
|
|
pub messages: Vec<Envelope>,
|
|
|
|
pub message_list: TableState,
|
|
|
|
}
|
|
|
|
|
2021-03-09 11:21:23 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct EmailMetadata {
|
|
|
|
pub date: DateTime<Local>,
|
|
|
|
pub from: String,
|
|
|
|
pub subject: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn humanize_timestamp(date: DateTime<Local>) -> String {
|
|
|
|
let now = Local::now();
|
|
|
|
let diff = now - date;
|
|
|
|
|
|
|
|
if diff < Duration::days(1) {
|
|
|
|
HumanTime::from(date).to_string()
|
|
|
|
}else if date.year() == now.year() {
|
|
|
|
date.format("%b %e %T").to_string()
|
|
|
|
} else {
|
|
|
|
date.to_rfc2822()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-09 00:26:18 +00:00
|
|
|
impl MailTabState {
|
|
|
|
pub fn render(&mut self, f: &mut FrameType, area: Rect) {
|
|
|
|
let chunks = Layout::default()
|
|
|
|
.direction(Direction::Horizontal)
|
|
|
|
.margin(0)
|
|
|
|
.constraints([Constraint::Length(20), Constraint::Max(5000)])
|
|
|
|
.split(area);
|
|
|
|
|
|
|
|
// folder list
|
|
|
|
let items = self
|
|
|
|
.folders
|
|
|
|
.iter()
|
|
|
|
.map(|s| ListItem::new(s.to_owned()))
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
let dirlist = List::new(items)
|
|
|
|
.block(Block::default().borders(Borders::NONE))
|
|
|
|
.style(Style::default().fg(Color::White))
|
|
|
|
.highlight_style(Style::default().add_modifier(Modifier::ITALIC))
|
|
|
|
.highlight_symbol(">>");
|
|
|
|
|
|
|
|
// message list table
|
|
|
|
let rows = self
|
2021-03-09 11:21:23 +00:00
|
|
|
.message_uids
|
2021-03-09 00:26:18 +00:00
|
|
|
.iter()
|
2021-03-09 11:21:23 +00:00
|
|
|
.map(|id| {
|
|
|
|
let meta = self.message_map.get(id);
|
|
|
|
Row::new(vec![
|
|
|
|
"".to_owned(),
|
|
|
|
id.to_string(),
|
|
|
|
meta.map(|m| humanize_timestamp(m.date)).unwrap_or_default(),
|
|
|
|
"".to_owned(),
|
|
|
|
meta.map(|m| m.subject.clone()).unwrap_or_default(),
|
|
|
|
])
|
|
|
|
})
|
2021-03-09 00:26:18 +00:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
let table = Table::new(rows)
|
|
|
|
.style(Style::default().fg(Color::White))
|
2021-03-09 11:21:23 +00:00
|
|
|
.widths(&[
|
|
|
|
Constraint::Length(1),
|
|
|
|
Constraint::Max(3),
|
|
|
|
Constraint::Min(25),
|
|
|
|
Constraint::Min(20),
|
|
|
|
Constraint::Max(5000),
|
|
|
|
])
|
|
|
|
.header(
|
|
|
|
Row::new(vec!["", "UID", "Date", "From", "Subject"])
|
|
|
|
.style(Style::default().add_modifier(Modifier::BOLD)),
|
|
|
|
)
|
|
|
|
.highlight_style(Style::default().bg(Color::DarkGray));
|
2021-03-09 00:26:18 +00:00
|
|
|
|
|
|
|
f.render_widget(dirlist, chunks[0]);
|
|
|
|
f.render_stateful_widget(table, chunks[1], &mut self.message_list);
|
|
|
|
}
|
2021-03-01 09:50:20 +00:00
|
|
|
}
|