mirror of
https://git.meli.delivery/meli/meli
synced 2024-11-05 06:00:14 +00:00
ui: hold live entries for each mailbox in CompactListing
This commit is contained in:
parent
0e2e8b09f6
commit
7e80ad2a86
@ -26,10 +26,8 @@ use components::utilities::PageMovement;
|
||||
|
||||
const MAX_COLS: usize = 500;
|
||||
|
||||
/// 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 {
|
||||
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),
|
||||
@ -47,28 +45,13 @@ pub struct CompactListing {
|
||||
movement: Option<PageMovement>,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CompactListing {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CompactListing {
|
||||
impl fmt::Display for MailboxView {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "mail")
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
|
||||
impl CompactListing {
|
||||
impl MailboxView {
|
||||
/// Helper function to format entry strings for CompactListing */
|
||||
/* TODO: Make this configurable */
|
||||
fn make_entry_string(e: &Envelope, len: usize, idx: usize) -> String {
|
||||
@ -76,7 +59,7 @@ impl CompactListing {
|
||||
format!(
|
||||
"{} {} {:.85} ({})",
|
||||
idx,
|
||||
&CompactListing::format_date(e),
|
||||
&MailboxView::format_date(e),
|
||||
e.subject(),
|
||||
len
|
||||
)
|
||||
@ -84,15 +67,15 @@ impl CompactListing {
|
||||
format!(
|
||||
"{} {} {:.85}",
|
||||
idx,
|
||||
&CompactListing::format_date(e),
|
||||
&MailboxView::format_date(e),
|
||||
e.subject(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
fn new() -> Self {
|
||||
let content = CellBuffer::new(0, 0, Cell::with_char(' '));
|
||||
CompactListing {
|
||||
MailboxView {
|
||||
cursor_pos: (0, 1, 0),
|
||||
new_cursor_pos: (0, 0, 0),
|
||||
length: 0,
|
||||
@ -114,7 +97,6 @@ impl CompactListing {
|
||||
if !(self.cursor_pos.0 == self.new_cursor_pos.0
|
||||
&& self.cursor_pos.1 == self.new_cursor_pos.1)
|
||||
{
|
||||
//TODO: store cursor_pos in each folder
|
||||
self.cursor_pos.2 = 0;
|
||||
self.new_cursor_pos.2 = 0;
|
||||
}
|
||||
@ -209,7 +191,7 @@ impl CompactListing {
|
||||
Color::Default
|
||||
};
|
||||
let (x, _) = write_string_to_grid(
|
||||
&CompactListing::make_entry_string(root_envelope, thread_node.len(), idx),
|
||||
&MailboxView::make_entry_string(root_envelope, thread_node.len(), idx),
|
||||
&mut self.content,
|
||||
fg_color,
|
||||
bg_color,
|
||||
@ -377,7 +359,7 @@ impl CompactListing {
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for CompactListing {
|
||||
impl Component for MailboxView {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if !self.unfocused {
|
||||
if !self.is_dirty() {
|
||||
@ -438,47 +420,16 @@ impl Component for CompactListing {
|
||||
}
|
||||
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
|
||||
let folder_length = context.accounts[self.cursor_pos.0].len();
|
||||
let accounts_length = context.accounts.len();
|
||||
match k {
|
||||
'J' if folder_length > 0 => {
|
||||
if self.new_cursor_pos.1 < folder_length - 1 {
|
||||
'J' if folder_length > 0 && self.new_cursor_pos.1 < folder_length - 1 => {
|
||||
self.new_cursor_pos.1 = self.cursor_pos.1 + 1;
|
||||
self.refresh_mailbox(context);
|
||||
} else if accounts_length > 0 && self.new_cursor_pos.0 < accounts_length - 1
|
||||
{
|
||||
self.new_cursor_pos.0 = self.cursor_pos.0 + 1;
|
||||
self.new_cursor_pos.1 = 0;
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
}
|
||||
'K' => {
|
||||
if self.cursor_pos.1 > 0 {
|
||||
'K' if self.cursor_pos.1 > 0 => {
|
||||
self.new_cursor_pos.1 = self.cursor_pos.1 - 1;
|
||||
self.refresh_mailbox(context);
|
||||
} else if self.cursor_pos.0 > 0 {
|
||||
self.new_cursor_pos.0 = self.cursor_pos.0 - 1;
|
||||
self.new_cursor_pos.1 = 0;
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
UIEventType::Input(Key::Char(k @ 'h')) | UIEventType::Input(Key::Char(k @ 'l')) => {
|
||||
let accounts_length = context.accounts.len();
|
||||
match k {
|
||||
'h' if accounts_length > 0 && self.new_cursor_pos.0 < accounts_length - 1 => {
|
||||
self.new_cursor_pos.0 = self.cursor_pos.0 + 1;
|
||||
self.new_cursor_pos.1 = 0;
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
'l' if self.cursor_pos.0 > 0 => {
|
||||
self.new_cursor_pos.0 = self.cursor_pos.0 - 1;
|
||||
self.new_cursor_pos.1 = 0;
|
||||
self.refresh_mailbox(context);
|
||||
}
|
||||
_ => {}
|
||||
_ => return false,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -637,3 +588,178 @@ impl Component for CompactListing {
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
views: Vec<MailboxView>,
|
||||
cursor: usize,
|
||||
dirty: bool,
|
||||
populated: bool,
|
||||
}
|
||||
|
||||
impl ListingTrait for CompactListing {
|
||||
fn coordinates(&self) -> (usize, usize, Option<EnvelopeHash>) {
|
||||
(self.cursor, self.views[self.cursor].cursor_pos.1, None)
|
||||
}
|
||||
fn set_coordinates(&mut self, coordinates: (usize, usize, Option<EnvelopeHash>)) {
|
||||
self.views[self.cursor].new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CompactListing {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "mail")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CompactListing {
|
||||
fn default() -> Self {
|
||||
CompactListing::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CompactListing {
|
||||
pub fn new() -> Self {
|
||||
CompactListing {
|
||||
views: Vec::with_capacity(8),
|
||||
cursor: 0,
|
||||
dirty: true,
|
||||
populated: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for CompactListing {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if !self.populated {
|
||||
eprintln!("populating");
|
||||
for (idx, a) in context.accounts.iter().enumerate() {
|
||||
for (fidx, _) in a.iter_mailboxes().enumerate() {
|
||||
let mut m = MailboxView::new();
|
||||
m.new_cursor_pos = (idx, fidx, 0);
|
||||
self.views.push(m);
|
||||
}
|
||||
}
|
||||
self.populated = true;
|
||||
}
|
||||
|
||||
if self.views.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.views[self.cursor].draw(grid, area, context);
|
||||
}
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
if self.views.is_empty() {
|
||||
return false;
|
||||
}
|
||||
match event.event_type {
|
||||
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
|
||||
let folder_length = context.accounts[self.views[self.cursor].cursor_pos.0].len();
|
||||
match k {
|
||||
'J' if folder_length > 0 => {
|
||||
if self.cursor < self.views.len() - 1 {
|
||||
self.cursor += 1;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
'K' if self.cursor > 0 => {
|
||||
self.cursor -= 1;
|
||||
self.dirty = true;
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
self.views[self.cursor].refresh_mailbox(context);
|
||||
return true;
|
||||
}
|
||||
UIEventType::Input(Key::Char(k @ 'h')) | UIEventType::Input(Key::Char(k @ 'l')) => {
|
||||
let binary_search_account = |entries: &[MailboxView], x: usize| -> Option<usize> {
|
||||
if entries.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut low = 0;
|
||||
let mut high = entries.len() - 1;
|
||||
while low < high {
|
||||
let mid = low + (high - low) / 2;
|
||||
if x > entries[mid].new_cursor_pos.0 {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
return Some(low);
|
||||
};
|
||||
match k {
|
||||
'h' => {
|
||||
if let Some(next) = binary_search_account(
|
||||
&self.views.as_slice()[self.cursor..],
|
||||
self.views[self.cursor].new_cursor_pos.0 + 1,
|
||||
) {
|
||||
self.cursor += next;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
'l' if self.views[self.cursor].cursor_pos.0 > 0 => {
|
||||
if let Some(next) = binary_search_account(
|
||||
&self.views.as_slice()[..self.cursor],
|
||||
self.views[self.cursor].new_cursor_pos.0 - 1,
|
||||
) {
|
||||
self.cursor = next;
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
self.views[self.cursor].refresh_mailbox(context);
|
||||
return true;
|
||||
}
|
||||
_ => {
|
||||
return self.views[self.cursor].process_event(event, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
if self.views.is_empty() {
|
||||
return self.dirty;
|
||||
}
|
||||
self.dirty || self.views[self.cursor].is_dirty()
|
||||
}
|
||||
fn set_dirty(&mut self) {
|
||||
if self.views.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.views[self.cursor].set_dirty();
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
|
||||
if self.views.is_empty() {
|
||||
return Default::default();
|
||||
}
|
||||
let mut map = self.views[self.cursor].get_shortcuts(context);
|
||||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(
|
||||
"prev_account",
|
||||
if let Some(key) = config_map.get("prev_account") {
|
||||
(*key).clone()
|
||||
} else {
|
||||
Key::Char('h')
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
"next_account",
|
||||
if let Some(key) = config_map.get("next_account") {
|
||||
(*key).clone()
|
||||
} else {
|
||||
Key::Char('l')
|
||||
},
|
||||
);
|
||||
|
||||
map
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user