ui: reassign listing shortcuts

after `312011c ui: move account menu functions to Listing`, shortcuts like prev_folder etc should be generic over all listing types.
embed
Manos Pitsidianakis 2019-04-29 10:54:40 +03:00
parent 69031e66f9
commit 4ae8cbadbf
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
6 changed files with 130 additions and 236 deletions

View File

@ -20,7 +20,6 @@
*/ */
use super::*; use super::*;
use std::ops::{Deref, DerefMut};
mod compact; mod compact;
pub use self::compact::*; pub use self::compact::*;
@ -74,7 +73,7 @@ pub struct Listing {
accounts: Vec<AccountMenuEntry>, accounts: Vec<AccountMenuEntry>,
dirty: bool, dirty: bool,
visible: bool, visible: bool,
cursor: (usize, usize), cursor_pos: (usize, usize),
id: ComponentId, id: ComponentId,
show_divider: bool, show_divider: bool,
@ -152,26 +151,34 @@ impl Component for Listing {
return true; return true;
} }
let shortcuts = self.get_shortcuts(context);
match *event { match *event {
UIEvent::Input(Key::Char(k @ 'J')) | UIEvent::Input(Key::Char(k @ 'K')) => { UIEvent::Input(ref k)
let folder_length = context.accounts[self.cursor.0].len(); if k == shortcuts["next_folder"] || k == shortcuts["prev_folder"] =>
{
let folder_length = context.accounts[self.cursor_pos.0].len();
match k { match k {
'J' if folder_length > 0 => { k if k == shortcuts["next_folder"] && folder_length > 0 => {
if self.cursor.1 < folder_length - 1 { if self.cursor_pos.1 < folder_length - 1 {
self.cursor.1 += 1; self.cursor_pos.1 += 1;
self.component self.component.set_coordinates((
.set_coordinates((self.cursor.0, self.cursor.1, None)); self.cursor_pos.0,
self.cursor_pos.1,
None,
));
self.set_dirty(); self.set_dirty();
} else { } else {
return true; return true;
} }
} }
'K' => { k if k == shortcuts["prev_folder"] => {
if self.cursor.1 > 0 { if self.cursor_pos.1 > 0 {
self.cursor.1 -= 1; self.cursor_pos.1 -= 1;
let coors = self.component.coordinates(); self.component.set_coordinates((
self.component self.cursor_pos.0,
.set_coordinates((self.cursor.0, self.cursor.1, None)); self.cursor_pos.1,
None,
));
self.set_dirty(); self.set_dirty();
} else { } else {
return true; return true;
@ -179,28 +186,31 @@ impl Component for Listing {
} }
_ => return false, _ => return false,
} }
let folder_hash = context.accounts[self.cursor.0].folders_order[self.cursor.1]; let folder_hash =
context.accounts[self.cursor_pos.0].folders_order[self.cursor_pos.1];
// Inform State that we changed the current folder view. // Inform State that we changed the current folder view.
context context
.replies .replies
.push_back(UIEvent::RefreshMailbox((self.cursor.0, folder_hash))); .push_back(UIEvent::RefreshMailbox((self.cursor_pos.0, folder_hash)));
return true; return true;
} }
UIEvent::Input(Key::Char(k @ 'h')) | UIEvent::Input(Key::Char(k @ 'l')) => { UIEvent::Input(ref k)
if k == shortcuts["next_account"] || k == shortcuts["prev_account"] =>
{
match k { match k {
'h' => { k if k == shortcuts["next_account"] => {
if self.cursor.0 < self.accounts.len() - 1 { if self.cursor_pos.0 < self.accounts.len() - 1 {
self.cursor = (self.cursor.0 + 1, 0); self.cursor_pos = (self.cursor_pos.0 + 1, 0);
self.component.set_coordinates((self.cursor.0, 0, None)); self.component.set_coordinates((self.cursor_pos.0, 0, None));
self.set_dirty(); self.set_dirty();
} else { } else {
return true; return true;
} }
} }
'l' => { k if k == shortcuts["prev_account"] => {
if self.cursor.0 > 0 { if self.cursor_pos.0 > 0 {
self.cursor = (self.cursor.0 - 1, 0); self.cursor_pos = (self.cursor_pos.0 - 1, 0);
self.component.set_coordinates((self.cursor.0, 0, None)); self.component.set_coordinates((self.cursor_pos.0, 0, None));
self.set_dirty(); self.set_dirty();
} else { } else {
return true; return true;
@ -208,12 +218,12 @@ impl Component for Listing {
} }
_ => return false, _ => return false,
} }
let folder_hash = context.accounts[self.cursor.0].folders_order[self.cursor.1]; let folder_hash =
context.accounts[self.cursor_pos.0].folders_order[self.cursor_pos.1];
// Inform State that we changed the current folder view. // Inform State that we changed the current folder view.
context.replies.push_back(UIEvent::RefreshMailbox(( context
self.cursor.0, .replies
std::dbg!(folder_hash), .push_back(UIEvent::RefreshMailbox((self.cursor_pos.0, folder_hash)));
)));
return true; return true;
} }
UIEvent::Action(ref action) => match action { UIEvent::Action(ref action) => match action {
@ -277,7 +287,7 @@ impl Component for Listing {
_ => {} _ => {}
}, },
UIEvent::RefreshMailbox((idxa, folder_hash)) => { UIEvent::RefreshMailbox((idxa, folder_hash)) => {
self.cursor = ( self.cursor_pos = (
idxa, idxa,
context.accounts[idxa] context.accounts[idxa]
.folders_order .folders_order
@ -293,10 +303,16 @@ impl Component for Listing {
UIEvent::Resize => { UIEvent::Resize => {
self.dirty = true; self.dirty = true;
} }
UIEvent::Input(Key::Char('`')) => { UIEvent::Input(ref k) if k == shortcuts["toggle-menu-visibility"] => {
self.menu_visibility = !self.menu_visibility; self.menu_visibility = !self.menu_visibility;
self.set_dirty(); self.set_dirty();
} }
UIEvent::Input(ref k) if k == shortcuts["new_mail"] => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
UIEvent::StartupCheck(_) => { UIEvent::StartupCheck(_) => {
self.dirty = true; self.dirty = true;
} }
@ -330,9 +346,48 @@ impl Component for Listing {
Plain(ref l) => l.get_shortcuts(context), Plain(ref l) => l.get_shortcuts(context),
Threaded(ref l) => l.get_shortcuts(context), Threaded(ref l) => l.get_shortcuts(context),
}; };
map.insert("Toggle account menu visibility", Key::Char('`')); let config_map = context.settings.shortcuts.listing.key_values();
map.insert("prev_account", Key::Char('h')); map.insert(
map.insert("next_account", Key::Char('l')); "new_mail",
if let Some(key) = config_map.get("new_mail") {
(*key).clone()
} else {
Key::Char('m')
},
);
map.insert(
"prev_folder",
if let Some(key) = config_map.get("prev_folder") {
(*key).clone()
} else {
Key::Char('J')
},
);
map.insert(
"next_folder",
if let Some(key) = config_map.get("next_folder") {
(*key).clone()
} else {
Key::Char('K')
},
);
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.insert("toggle-menu-visibility", Key::Char('`'));
map map
} }
@ -378,7 +433,7 @@ impl Listing {
accounts, accounts,
visible: true, visible: true,
dirty: true, dirty: true,
cursor: (0, 0), cursor_pos: (0, 0),
id: ComponentId::new_v4(), id: ComponentId::new_v4(),
show_divider: false, show_divider: false,
menu_visibility: true, menu_visibility: true,
@ -435,7 +490,7 @@ impl Listing {
let upper_left = upper_left!(area); let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area); let bottom_right = bottom_right!(area);
let highlight = self.cursor.0 == a.index; let highlight = self.cursor_pos.0 == a.index;
let mut inc = 0; let mut inc = 0;
let mut depth = String::from(""); let mut depth = String::from("");
@ -530,7 +585,7 @@ impl Listing {
} }
let s = lines[idx].to_string(); let s = lines[idx].to_string();
let (color_fg, color_bg) = if highlight { let (color_fg, color_bg) = if highlight {
if self.cursor.1 + 1 == idx { if self.cursor_pos.1 + 1 == idx {
(Color::Byte(233), Color::Byte(15)) (Color::Byte(233), Color::Byte(15))
} else { } else {
(Color::Byte(15), Color::Byte(233)) (Color::Byte(15), Color::Byte(233))
@ -570,7 +625,7 @@ impl Listing {
} }
} }
if highlight && idx > 1 && self.cursor.1 == idx - 1 { if highlight && idx > 1 && self.cursor_pos.1 == idx - 1 {
change_colors(grid, ((x, y), (get_x(bottom_right), y)), color_fg, color_bg); change_colors(grid, ((x, y), (get_x(bottom_right), y)), color_fg, color_bg);
} else { } else {
change_colors(grid, ((x, y), set_y(bottom_right, y)), color_fg, color_bg); change_colors(grid, ((x, y), set_y(bottom_right, y)), color_fg, color_bg);

View File

@ -481,12 +481,6 @@ impl Component for MailboxView {
} }
_ => {} _ => {}
}, },
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
_ => {} _ => {}
} }
false false
@ -546,46 +540,6 @@ impl Component for MailboxView {
Key::Char('i') Key::Char('i')
}, },
); );
map.insert(
"prev_folder",
if let Some(key) = config_map.get("prev_folder") {
(*key).clone()
} else {
Key::Char('J')
},
);
map.insert(
"next_folder",
if let Some(key) = config_map.get("next_folder") {
(*key).clone()
} else {
Key::Char('K')
},
);
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.insert(
"new_mail",
if let Some(key) = config_map.get("new_mail") {
(*key).clone()
} else {
Key::Char('m')
},
);
map map
} }
@ -703,27 +657,7 @@ impl Component for CompactListing {
if self.views.is_empty() { if self.views.is_empty() {
return Default::default(); return Default::default();
} }
let mut map = self.views[self.cursor].get_shortcuts(context); 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
} }
fn id(&self) -> ComponentId { fn id(&self) -> ComponentId {

View File

@ -434,70 +434,12 @@ impl Component for PlainListing {
self.dirty = true; self.dirty = true;
return true; return true;
} }
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
UIEvent::Input(Key::Char('i')) if self.unfocused => { UIEvent::Input(Key::Char('i')) if self.unfocused => {
self.unfocused = false; self.unfocused = false;
self.dirty = true; self.dirty = true;
self.view = None; self.view = None;
return true; return true;
} }
UIEvent::Input(Key::Char(k @ 'J')) | UIEvent::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 {
self.new_cursor_pos.1 = self.cursor_pos.1 + 1;
self.dirty = true;
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.dirty = true;
self.refresh_mailbox(context);
}
}
'K' => {
if self.cursor_pos.1 > 0 {
self.new_cursor_pos.1 = self.cursor_pos.1 - 1;
self.dirty = true;
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.dirty = true;
self.refresh_mailbox(context);
}
}
_ => {}
}
return true;
}
UIEvent::Input(Key::Char(k @ 'h')) | UIEvent::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.dirty = true;
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.dirty = true;
self.refresh_mailbox(context);
}
_ => {}
}
return true;
}
UIEvent::RefreshMailbox(_) => { UIEvent::RefreshMailbox(_) => {
self.dirty = true; self.dirty = true;
self.view = None; self.view = None;

View File

@ -599,70 +599,12 @@ impl Component for ThreadListing {
self.dirty = true; self.dirty = true;
return true; return true;
} }
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
UIEvent::Input(Key::Char('i')) if self.unfocused => { UIEvent::Input(Key::Char('i')) if self.unfocused => {
self.unfocused = false; self.unfocused = false;
self.dirty = true; self.dirty = true;
self.view = None; self.view = None;
return true; return true;
} }
UIEvent::Input(Key::Char(k @ 'J')) | UIEvent::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 {
self.new_cursor_pos.1 = self.cursor_pos.1 + 1;
self.dirty = true;
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.dirty = true;
self.refresh_mailbox(context);
}
}
'K' => {
if self.cursor_pos.1 > 0 {
self.new_cursor_pos.1 = self.cursor_pos.1 - 1;
self.dirty = true;
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.dirty = true;
self.refresh_mailbox(context);
}
}
_ => {}
}
return true;
}
UIEvent::Input(Key::Char(k @ 'h')) | UIEvent::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.dirty = true;
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.dirty = true;
self.refresh_mailbox(context);
}
_ => {}
}
return true;
}
UIEvent::RefreshMailbox(_) => { UIEvent::RefreshMailbox(_) => {
self.dirty = true; self.dirty = true;
self.view = None; self.view = None;

View File

@ -4,6 +4,8 @@ use fnv::FnvHashMap;
#[derive(Debug, Clone, Default, Deserialize)] #[derive(Debug, Clone, Default, Deserialize)]
pub struct Shortcuts { pub struct Shortcuts {
#[serde(flatten)]
pub listing: ListingShortcuts,
#[serde(flatten)] #[serde(flatten)]
pub compact_listing: CompactListingShortcuts, pub compact_listing: CompactListingShortcuts,
#[serde(flatten)] #[serde(flatten)]
@ -45,19 +47,12 @@ macro_rules! shortcut_key_values {
} }
} }
shortcut_key_values! { "compact-listing", shortcut_key_values! { "compact_listing",
/// Shortcut listing for a mail listing in compact mode. /// Shortcut listing for a mail listing in compact mode.
pub struct CompactListingShortcuts { pub struct CompactListingShortcuts {
open_thread: Key |> "Open thread.", open_thread: Key |> "Open thread.",
exit_thread: Key |> "Exit thread view.", exit_thread: Key |> "Exit thread view."
prev_page: Key |> "Go to previous page.", }
next_page: Key |> "Go to next page.",
prev_folder: Key |> "Go to previous folder.",
next_folder: Key |> "Go to next folder.",
prev_account: Key |> "Go to previous account.",
next_account: Key |> "Go to next account.",
new_mail: Key |> "Start new mail draft in new tab."
}
} }
impl Default for CompactListingShortcuts { impl Default for CompactListingShortcuts {
@ -65,6 +60,26 @@ impl Default for CompactListingShortcuts {
CompactListingShortcuts { CompactListingShortcuts {
open_thread: Key::Char('\n'), open_thread: Key::Char('\n'),
exit_thread: Key::Char('i'), exit_thread: Key::Char('i'),
}
}
}
shortcut_key_values! { "listing",
/// Shortcut listing for a mail listing.
pub struct ListingShortcuts {
prev_page: Key |> "Go to previous page.",
next_page: Key |> "Go to next page.",
prev_folder: Key |> "Go to previous folder.",
next_folder: Key |> "Go to next folder.",
prev_account: Key |> "Go to previous account.",
next_account: Key |> "Go to next account.",
new_mail: Key |> "Start new mail draft in new tab."
}
}
impl Default for ListingShortcuts {
fn default() -> Self {
ListingShortcuts {
prev_page: Key::PageUp, prev_page: Key::PageUp,
next_page: Key::PageDown, next_page: Key::PageDown,
prev_folder: Key::Char('J'), prev_folder: Key::Char('J'),

View File

@ -129,6 +129,12 @@ impl From<TermionKey> for Key {
} }
} }
impl PartialEq<Key> for &Key {
fn eq(&self, other: &Key) -> bool {
**self == *other
}
}
#[derive(PartialEq)] #[derive(PartialEq)]
enum InputMode { enum InputMode {
Normal, Normal,