Browse Source

ui: unwrap UIEventType

tags/pre-alpha-0.0
Manos Pitsidianakis 1 year ago
parent
commit
9bc76e3bcb
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS. GPG Key ID: 73627C2F690DF710
23 changed files with 378 additions and 489 deletions
  1. +8
    -8
      src/bin.rs
  2. +1
    -1
      ui/src/components.rs
  3. +9
    -16
      ui/src/components/contacts.rs
  4. +8
    -11
      ui/src/components/contacts/contact_list.rs
  5. +4
    -4
      ui/src/components/indexer.rs
  6. +7
    -7
      ui/src/components/indexer/index.rs
  7. +7
    -7
      ui/src/components/mail.rs
  8. +9
    -10
      ui/src/components/mail/accounts.rs
  9. +33
    -51
      ui/src/components/mail/compose.rs
  10. +3
    -3
      ui/src/components/mail/listing.rs
  11. +25
    -26
      ui/src/components/mail/listing/compact.rs
  12. +21
    -22
      ui/src/components/mail/listing/plain.rs
  13. +21
    -22
      ui/src/components/mail/listing/thread.rs
  14. +52
    -72
      ui/src/components/mail/view.rs
  15. +42
    -58
      ui/src/components/mail/view/envelope.rs
  16. +18
    -25
      ui/src/components/mail/view/html.rs
  17. +18
    -24
      ui/src/components/mail/view/thread.rs
  18. +2
    -2
      ui/src/components/notifications.rs
  19. +34
    -35
      ui/src/components/utilities.rs
  20. +33
    -35
      ui/src/components/utilities/widgets.rs
  21. +2
    -2
      ui/src/conf/accounts.rs
  22. +18
    -35
      ui/src/state.rs
  23. +3
    -13
      ui/src/types.rs

+ 8
- 8
src/bin.rs View File

@ -118,11 +118,11 @@ fn main() {
},
Key::Char(' ') => {
state.mode = UIMode::Execute;
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::ChangeMode(UIMode::Execute)});
state.rcv_event(UIEvent::ChangeMode(UIMode::Execute));
state.redraw();
}
key => {
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::Input(key)});
state.rcv_event(UIEvent::Input(key));
state.redraw();
},
}
@ -131,11 +131,11 @@ fn main() {
match k {
Key::Char('\n') | Key::Esc => {
state.mode = UIMode::Normal;
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::ChangeMode(UIMode::Normal)});
state.rcv_event(UIEvent::ChangeMode(UIMode::Normal));
state.redraw();
},
k => {
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::InsertInput(k)});
state.rcv_event(UIEvent::InsertInput(k));
state.redraw();
},
}
@ -144,11 +144,11 @@ fn main() {
match k {
Key::Char('\n') | Key::Esc => {
state.mode = UIMode::Normal;
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::ChangeMode(UIMode::Normal)});
state.rcv_event(UIEvent::ChangeMode(UIMode::Normal));
state.redraw();
},
k => {
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::ExInput(k)});
state.rcv_event(UIEvent::ExInput(k));
state.redraw();
},
}
@ -162,14 +162,14 @@ fn main() {
state.refresh_event(*event);
state.redraw();
},
ThreadEvent::UIEvent(UIEventType::ChangeMode(f)) => {
ThreadEvent::UIEvent(UIEvent::ChangeMode(f)) => {
state.mode = f;
if f == UIMode::Fork {
break 'inner; // `goto` 'reap loop, and wait on child.
}
}
ThreadEvent::UIEvent(e) => {
state.rcv_event(UIEvent { id: 0, event_type: e});
state.rcv_event(e);
state.render();
},
ThreadEvent::ThreadJoin(id) => {

+ 1
- 1
ui/src/components.rs View File

@ -48,7 +48,7 @@ use std::ops::{Deref, DerefMut};
use fnv::FnvHashMap;
use uuid::Uuid;
use super::{Key, StatusEvent, UIEvent, UIEventType};
use super::{Key, StatusEvent, UIEvent};
/// The upper and lower boundary char.
const HORZ_BOUNDARY: char = 'โ”€';
/// The left and right boundary char.

+ 9
- 16
ui/src/components/contacts.rs View File

@ -161,32 +161,25 @@ impl Component for ContactManager {
context.accounts[self.account_pos]
.address_book
.add_card(new_card);
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
"Saved.".into(),
)),
});
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::ComponentKill(self.id),
});
)));
context.replies.push_back(UIEvent::ComponentKill(self.id));
}
Some(false) => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::ComponentKill(self.id),
});
context.replies.push_back(UIEvent::ComponentKill(self.id));
}
}
return true;
}
/*
match event.event_type {
UIEventType::Input(Key::Char('\n')) => {
match *event {
UIEvent::Input(Key::Char('\n')) => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::ComponentKill(self.id),
event_type: UIEvent::ComponentKill(self.id),
});
return true;
},

+ 8
- 11
ui/src/components/contacts/contact_list.rs View File

@ -168,10 +168,7 @@ impl ContactList {
impl Component for ContactList {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if let ViewMode::Close(u) = self.mode {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(Kill(u))),
});
context.replies.push_back(UIEvent::Action(Tab(Kill(u))));
return;
}
@ -232,8 +229,8 @@ impl Component for ContactList {
}
}
let shortcuts = self.get_shortcuts(context);
match event.event_type {
UIEventType::Input(ref key) if *key == shortcuts["create_contact"] => {
match *event {
UIEvent::Input(ref key) if *key == shortcuts["create_contact"] => {
let mut manager = ContactManager::default();
manager.account_pos = self.account_pos;
let component = Box::new(manager);
@ -244,7 +241,7 @@ impl Component for ContactList {
return true;
}
UIEventType::Input(ref key) if *key == shortcuts["edit_contact"] && self.length > 0 => {
UIEvent::Input(ref key) if *key == shortcuts["edit_contact"] && self.length > 0 => {
let account = &mut context.accounts[self.account_pos];
let book = &mut account.address_book;
let card = book[&self.id_positions[self.cursor_pos]].clone();
@ -258,7 +255,7 @@ impl Component for ContactList {
return true;
}
UIEventType::Input(Key::Char('n')) => {
UIEvent::Input(Key::Char('n')) => {
let card = Card::new();
let mut manager = ContactManager::default();
manager.card = card;
@ -269,17 +266,17 @@ impl Component for ContactList {
return true;
}
UIEventType::Input(Key::Up) => {
UIEvent::Input(Key::Up) => {
self.set_dirty();
self.new_cursor_pos = self.cursor_pos.saturating_sub(1);
return true;
}
UIEventType::Input(Key::Down) if self.cursor_pos < self.length.saturating_sub(1) => {
UIEvent::Input(Key::Down) if self.cursor_pos < self.length.saturating_sub(1) => {
self.set_dirty();
self.new_cursor_pos += 1;
return true;
}
UIEventType::ComponentKill(ref kill_id) if self.mode == ViewMode::View(*kill_id) => {
UIEvent::ComponentKill(ref kill_id) if self.mode == ViewMode::View(*kill_id) => {
self.mode = ViewMode::List;
self.view.take();
self.set_dirty();

+ 4
- 4
ui/src/components/indexer.rs View File

@ -105,14 +105,14 @@ impl Component for Indexer {
}
}
match event.event_type {
UIEventType::RefreshMailbox(_) => {
match *event {
UIEvent::RefreshMailbox(_) => {
self.dirty = true;
}
UIEventType::ChangeMode(UIMode::Normal) => {
UIEvent::ChangeMode(UIMode::Normal) => {
self.dirty = true;
}
UIEventType::Resize => {
UIEvent::Resize => {
self.dirty = true;
}
_ => {}

+ 7
- 7
ui/src/components/indexer/index.rs View File

@ -128,35 +128,35 @@ impl Component for Index {
if self.content.process_event(event, context) {
return true;
}
match event.event_type {
UIEventType::Input(Key::Up) => {
match *event {
UIEvent::Input(Key::Up) => {
if self.cursor_pos > 0 {
self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1);
self.set_dirty();
}
return true;
}
UIEventType::Input(Key::Down) => {
UIEvent::Input(Key::Down) => {
if self.length > 0 && self.new_cursor_pos < self.length - 1 {
self.new_cursor_pos += 1;
self.set_dirty();
}
return true;
}
UIEventType::Input(Key::Char('\n')) if self.state == IndexState::Listing => {
UIEvent::Input(Key::Char('\n')) if self.state == IndexState::Listing => {
self.state = IndexState::Unfocused;
self.set_dirty();
return true;
}
UIEventType::Input(Key::Char('i')) if self.state == IndexState::Unfocused => {
UIEvent::Input(Key::Char('i')) if self.state == IndexState::Unfocused => {
self.state = IndexState::Listing;
self.set_dirty();
return true;
}
UIEventType::ChangeMode(UIMode::Normal) => {
UIEvent::ChangeMode(UIMode::Normal) => {
self.set_dirty();
}
UIEventType::Resize => {
UIEvent::Resize => {
self.set_dirty();
}
_ => {}

+ 7
- 7
ui/src/components/mail.rs View File

@ -263,25 +263,25 @@ impl Component for AccountMenu {
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
match event.event_type {
UIEventType::RefreshMailbox(c) => {
match *event {
UIEvent::RefreshMailbox(c) => {
self.cursor = Some(c);
self.dirty = true;
}
UIEventType::ChangeMode(UIMode::Normal) => {
UIEvent::ChangeMode(UIMode::Normal) => {
self.dirty = true;
}
UIEventType::Resize => {
UIEvent::Resize => {
self.dirty = true;
}
UIEventType::Input(Key::Char('`')) => {
UIEvent::Input(Key::Char('`')) => {
self.visible = !self.visible;
self.dirty = true;
}
UIEventType::StartupCheck(_) => {
UIEvent::StartupCheck(_) => {
self.dirty = true;
}
UIEventType::MailboxUpdate(_) => {
UIEvent::MailboxUpdate(_) => {
self.dirty = true;
}
_ => {}

+ 9
- 10
ui/src/components/mail/accounts.rs View File

@ -49,29 +49,28 @@ impl Component for AccountsPanel {
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event.event_type {
UIEventType::Input(Key::Up) => {
match *event {
UIEvent::Input(Key::Up) => {
self.cursor = self.cursor.saturating_sub(1);
self.dirty = true;
return true;
}
UIEventType::Input(Key::Down) => {
UIEvent::Input(Key::Down) => {
if self.cursor + 1 < context.accounts.len() {
self.cursor += 1;
self.dirty = true;
}
return true;
}
UIEventType::Input(Key::Char('\n')) => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(TabOpen(Some(Box::new(
UIEvent::Input(Key::Char('\n')) => {
context
.replies
.push_back(UIEvent::Action(Tab(TabOpen(Some(Box::new(
ContactList::for_account(self.cursor),
))))),
});
))))));
return true;
}
UIEventType::MailboxUpdate(_) => {
UIEvent::MailboxUpdate(_) => {
self.dirty = true;
}
_ => {}

+ 33
- 51
ui/src/components/mail/compose.rs View File

@ -431,9 +431,9 @@ impl Component for Composer {
}
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match (&mut self.mode, &mut self.reply_context, &event.event_type) {
match (&mut self.mode, &mut self.reply_context, &event) {
// don't pass Reply command to thread view in reply_context
(_, _, UIEventType::Input(Key::Char('R'))) => {}
(_, _, UIEvent::Input(Key::Char('R'))) => {}
(ViewMode::Overview, Some((_, ref mut view)), _) => {
if view.process_event(event, context) {
self.dirty = true;
@ -456,13 +456,13 @@ impl Component for Composer {
return true;
}
match event.event_type {
UIEventType::Resize => {
match *event {
UIEvent::Resize => {
self.set_dirty();
}
/*
/* Switch e-mail From: field to the `left` configured account. */
UIEventType::Input(Key::Left) if self.cursor == Cursor::From => {
UIEvent::Input(Key::Left) if self.cursor == Cursor::From => {
self.account_cursor = self.account_cursor.saturating_sub(1);
self.draft.headers_mut().insert(
"From".into(),
@ -472,7 +472,7 @@ impl Component for Composer {
return true;
}
/* Switch e-mail From: field to the `right` configured account. */
UIEventType::Input(Key::Right) if self.cursor == Cursor::From => {
UIEvent::Input(Key::Right) if self.cursor == Cursor::From => {
if self.account_cursor + 1 < context.accounts.len() {
self.account_cursor += 1;
self.draft.headers_mut().insert(
@ -483,19 +483,16 @@ impl Component for Composer {
}
return true;
}*/
UIEventType::Input(Key::Up) => {
UIEvent::Input(Key::Up) => {
self.cursor = Cursor::Headers;
}
UIEventType::Input(Key::Down) => {
UIEvent::Input(Key::Down) => {
self.cursor = Cursor::Body;
}
UIEventType::Input(Key::Char(key)) if self.mode.is_discard() => {
UIEvent::Input(Key::Char(key)) if self.mode.is_discard() => {
match (key, &self.mode) {
('x', ViewMode::Discard(u)) => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(Kill(*u))),
});
context.replies.push_back(UIEvent::Action(Tab(Kill(*u))));
return true;
}
('n', _) => {}
@ -506,18 +503,12 @@ impl Component for Composer {
if cfg!(feature = "debug_log") {
eprintln!("{:?} could not save draft", e);
}
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Notification(
Some("Could not save draft.".into()),
e.into(),
),
});
context.replies.push_back(UIEvent::Notification(
Some("Could not save draft.".into()),
e.into(),
));
}
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(Kill(*u))),
});
context.replies.push_back(UIEvent::Action(Tab(Kill(*u))));
return true;
}
_ => {
@ -529,18 +520,18 @@ impl Component for Composer {
return true;
}
/* Switch to Overview mode if we're on Edit mode */
UIEventType::Input(Key::Char('v')) if self.mode.is_edit() => {
UIEvent::Input(Key::Char('v')) if self.mode.is_edit() => {
self.mode = ViewMode::Overview;
self.set_dirty();
return true;
}
/* Switch to Edit mode if we're on Overview mode */
UIEventType::Input(Key::Char('o')) if self.mode.is_overview() => {
UIEvent::Input(Key::Char('o')) if self.mode.is_overview() => {
self.mode = ViewMode::Edit;
self.set_dirty();
return true;
}
UIEventType::Input(Key::Char('s')) if self.mode.is_overview() => {
UIEvent::Input(Key::Char('s')) if self.mode.is_overview() => {
use std::io::Write;
use std::process::{Command, Stdio};
let settings = &context.settings;
@ -568,31 +559,25 @@ impl Component for Composer {
if cfg!(feature = "debug_log") {
eprintln!("{:?} could not save sent msg", e);
}
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Notification(
Some("Could not save in 'Sent' folder.".into()),
e.into(),
),
});
context.replies.push_back(UIEvent::Notification(
Some("Could not save in 'Sent' folder.".into()),
e.into(),
));
}
}
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Notification(
Some("Sent.".into()),
format!(
"Mailer output: {:#?}",
msmtp
.wait_with_output()
.expect("Failed to wait on filter")
.stdout
),
context.replies.push_back(UIEvent::Notification(
Some("Sent.".into()),
format!(
"Mailer output: {:#?}",
msmtp
.wait_with_output()
.expect("Failed to wait on filter")
.stdout
),
});
));
return true;
}
UIEventType::Input(Key::Char('e')) if self.cursor == Cursor::Body => {
UIEvent::Input(Key::Char('e')) if self.cursor == Cursor::Body => {
/* Edit draft in $EDITOR */
use std::process::{Command, Stdio};
/* Kill input thread so that spawned command can be sole receiver of stdin */
@ -616,10 +601,7 @@ impl Component for Composer {
let result = f.read_to_string();
self.draft = Draft::from_str(result.as_str()).unwrap();
self.initialized = false;
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Fork(ForkType::Finished),
});
context.replies.push_back(UIEvent::Fork(ForkType::Finished));
context.restore_input();
/*

+ 3
- 3
ui/src/components/mail/listing.rs View File

@ -75,9 +75,9 @@ impl Component for Listing {
return true;
}
match event.event_type {
UIEventType::Resize => self.set_dirty(),
UIEventType::Action(ref action) => match action {
match *event {
UIEvent::Resize => self.set_dirty(),
UIEvent::Action(ref action) => match action {
Action::Listing(ListingAction::SetPlain) => {
let new_l = match self {
Listing::Plain(_) => {

+ 25
- 26
ui/src/components/mail/listing/compact.rs View File

@ -106,10 +106,10 @@ impl MailboxView {
self.cursor_pos.0 = self.new_cursor_pos.0;
// Inform State that we changed the current folder view.
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::RefreshMailbox((self.cursor_pos.0, self.cursor_pos.1)),
});
context.replies.push_back(UIEvent::RefreshMailbox((
self.cursor_pos.0,
self.cursor_pos.1,
)));
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
@ -386,41 +386,41 @@ impl Component for MailboxView {
}
let shortcuts = self.get_shortcuts(context);
match event.event_type {
UIEventType::Input(Key::Up) => {
match *event {
UIEvent::Input(Key::Up) => {
if self.cursor_pos.2 > 0 {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(1);
self.dirty = true;
}
return true;
}
UIEventType::Input(Key::Down) => {
UIEvent::Input(Key::Down) => {
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
self.new_cursor_pos.2 += 1;
self.dirty = true;
}
return true;
}
UIEventType::Input(ref k) if !self.unfocused && *k == shortcuts["open_thread"] => {
UIEvent::Input(ref k) if !self.unfocused && *k == shortcuts["open_thread"] => {
self.view = ThreadView::new(self.cursor_pos, None, context);
self.unfocused = true;
self.dirty = true;
return true;
}
UIEventType::Input(ref key) if *key == shortcuts["prev_page"] => {
UIEvent::Input(ref key) if *key == shortcuts["prev_page"] => {
self.movement = Some(PageMovement::PageUp);
self.set_dirty();
}
UIEventType::Input(ref key) if *key == shortcuts["next_page"] => {
UIEvent::Input(ref key) if *key == shortcuts["next_page"] => {
self.movement = Some(PageMovement::PageDown);
self.set_dirty();
}
UIEventType::Input(ref k) if self.unfocused && *k == shortcuts["exit_thread"] => {
UIEvent::Input(ref k) if self.unfocused && *k == shortcuts["exit_thread"] => {
self.unfocused = false;
self.dirty = true;
return true;
}
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
UIEvent::Input(Key::Char(k @ 'J')) | UIEvent::Input(Key::Char(k @ 'K')) => {
let folder_length = context.accounts[self.cursor_pos.0].len();
match k {
'J' if folder_length > 0 && self.new_cursor_pos.1 < folder_length - 1 => {
@ -435,28 +435,28 @@ impl Component for MailboxView {
}
return true;
}
UIEventType::RefreshMailbox(_) => {
UIEvent::RefreshMailbox(_) => {
self.dirty = true;
}
UIEventType::MailboxUpdate((ref idxa, ref idxf))
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 =>
{
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::StartupCheck(ref f)
UIEvent::StartupCheck(ref f)
if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
{
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::ChangeMode(UIMode::Normal) => {
UIEvent::ChangeMode(UIMode::Normal) => {
self.dirty = true;
}
UIEventType::Resize => {
UIEvent::Resize => {
self.dirty = true;
}
UIEventType::Action(ref action) => match action {
UIEvent::Action(ref action) => match action {
Action::ViewMailbox(idx) => {
self.new_cursor_pos.1 = *idx;
self.refresh_mailbox(context);
@ -480,11 +480,10 @@ impl Component for MailboxView {
}
_ => {}
},
UIEventType::Input(Key::Char('m')) if !self.unfocused => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(NewDraft(self.cursor_pos.0))),
});
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
_ => {}
@ -665,8 +664,8 @@ impl Component for CompactListing {
if self.views.is_empty() {
return false;
}
match event.event_type {
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
match *event {
UIEvent::Input(Key::Char(k @ 'J')) | UIEvent::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 => {
@ -684,7 +683,7 @@ impl Component for CompactListing {
self.views[self.cursor].refresh_mailbox(context);
return true;
}
UIEventType::Input(Key::Char(k @ 'h')) | UIEventType::Input(Key::Char(k @ 'l')) => {
UIEvent::Input(Key::Char(k @ 'h')) | UIEvent::Input(Key::Char(k @ 'l')) => {
let binary_search_account = |entries: &[MailboxView], x: usize| -> Option<usize> {
if entries.is_empty() {
return None;

+ 21
- 22
ui/src/components/mail/listing/plain.rs View File

@ -107,10 +107,10 @@ impl PlainListing {
self.cursor_pos.1 = self.new_cursor_pos.1;
// Inform State that we changed the current folder view.
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::RefreshMailbox((self.cursor_pos.0, self.cursor_pos.1)),
});
context.replies.push_back(UIEvent::RefreshMailbox((
self.cursor_pos.0,
self.cursor_pos.1,
)));
// Get mailbox as a reference.
//
// Get mailbox as a reference.
@ -416,40 +416,39 @@ impl Component for PlainListing {
return true;
}
}
match event.event_type {
UIEventType::Input(Key::Up) => {
match *event {
UIEvent::Input(Key::Up) => {
if self.cursor_pos.2 > 0 {
self.new_cursor_pos.2 -= 1;
self.dirty = true;
}
return true;
}
UIEventType::Input(Key::Down) => {
UIEvent::Input(Key::Down) => {
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
self.new_cursor_pos.2 += 1;
self.dirty = true;
}
return true;
}
UIEventType::Input(Key::Char('\n')) if !self.unfocused => {
UIEvent::Input(Key::Char('\n')) if !self.unfocused => {
self.unfocused = true;
self.dirty = true;
return true;
}
UIEventType::Input(Key::Char('m')) if !self.unfocused => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(NewDraft(self.cursor_pos.0))),
});
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
UIEventType::Input(Key::Char('i')) if self.unfocused => {
UIEvent::Input(Key::Char('i')) if self.unfocused => {
self.unfocused = false;
self.dirty = true;
self.view = None;
return true;
}
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
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 {
@ -482,7 +481,7 @@ impl Component for PlainListing {
}
return true;
}
UIEventType::Input(Key::Char(k @ 'h')) | UIEventType::Input(Key::Char(k @ 'l')) => {
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 => {
@ -501,29 +500,29 @@ impl Component for PlainListing {
}
return true;
}
UIEventType::RefreshMailbox(_) => {
UIEvent::RefreshMailbox(_) => {
self.dirty = true;
self.view = None;
}
UIEventType::MailboxUpdate((ref idxa, ref idxf))
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 =>
{
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::StartupCheck(ref f)
UIEvent::StartupCheck(ref f)
if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
{
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::ChangeMode(UIMode::Normal) => {
UIEvent::ChangeMode(UIMode::Normal) => {
self.dirty = true;
}
UIEventType::Resize => {
UIEvent::Resize => {
self.dirty = true;
}
UIEventType::Action(ref action) => match action {
UIEvent::Action(ref action) => match action {
Action::ViewMailbox(idx) => {
self.new_cursor_pos.1 = *idx;
self.dirty = true;

+ 21
- 22
ui/src/components/mail/listing/thread.rs View File

@ -105,10 +105,10 @@ impl ThreadListing {
self.cursor_pos.0 = self.new_cursor_pos.0;
// Inform State that we changed the current folder view.
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::RefreshMailbox((self.cursor_pos.0, self.cursor_pos.1)),
});
context.replies.push_back(UIEvent::RefreshMailbox((
self.cursor_pos.0,
self.cursor_pos.1,
)));
// Get mailbox as a reference.
//
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
@ -578,40 +578,39 @@ impl Component for ThreadListing {
return true;
}
}
match event.event_type {
UIEventType::Input(Key::Up) => {
match *event {
UIEvent::Input(Key::Up) => {
if self.cursor_pos.2 > 0 {
self.new_cursor_pos.2 -= 1;
self.dirty = true;
}
return true;
}
UIEventType::Input(Key::Down) => {
UIEvent::Input(Key::Down) => {
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
self.new_cursor_pos.2 += 1;
self.dirty = true;
}
return true;
}
UIEventType::Input(Key::Char('\n')) if !self.unfocused => {
UIEvent::Input(Key::Char('\n')) if !self.unfocused => {
self.unfocused = true;
self.dirty = true;
return true;
}
UIEventType::Input(Key::Char('m')) if !self.unfocused => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(NewDraft(self.cursor_pos.0))),
});
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
context
.replies
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
return true;
}
UIEventType::Input(Key::Char('i')) if self.unfocused => {
UIEvent::Input(Key::Char('i')) if self.unfocused => {
self.unfocused = false;
self.dirty = true;
self.view = None;
return true;
}
UIEventType::Input(Key::Char(k @ 'J')) | UIEventType::Input(Key::Char(k @ 'K')) => {
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 {
@ -644,7 +643,7 @@ impl Component for ThreadListing {
}
return true;
}
UIEventType::Input(Key::Char(k @ 'h')) | UIEventType::Input(Key::Char(k @ 'l')) => {
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 => {
@ -663,29 +662,29 @@ impl Component for ThreadListing {
}
return true;
}
UIEventType::RefreshMailbox(_) => {
UIEvent::RefreshMailbox(_) => {
self.dirty = true;
self.view = None;
}
UIEventType::MailboxUpdate((ref idxa, ref idxf))
UIEvent::MailboxUpdate((ref idxa, ref idxf))
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 =>
{
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::StartupCheck(ref f)
UIEvent::StartupCheck(ref f)
if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
{
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::ChangeMode(UIMode::Normal) => {
UIEvent::ChangeMode(UIMode::Normal) => {
self.dirty = true;
}
UIEventType::Resize => {
UIEvent::Resize => {
self.dirty = true;
}
UIEventType::Action(ref action) => match action {
UIEvent::Action(ref action) => match action {
Action::ViewMailbox(idx_m) => {
self.new_cursor_pos.1 = *idx_m;
self.dirty = true;

+ 52
- 72
ui/src/components/mail/view.rs View File

@ -140,16 +140,13 @@ impl MailView {
.stdout(Stdio::piped())
.spawn();
if command_obj.is_err() {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Notification(
Some(format!(
"Failed to start html filter process: {}",
filter_invocation,
)),
String::new(),
),
});
context.replies.push_back(UIEvent::Notification(
Some(format!(
"Failed to start html filter process: {}",
filter_invocation,
)),
String::new(),
));
return;
}
@ -450,8 +447,8 @@ impl Component for MailView {
}
}
match event.event_type {
UIEventType::Input(Key::Char('c')) => {
match *event {
UIEvent::Input(Key::Char('c')) => {
if let ViewMode::ContactSelector(_) = self.mode {
if let ViewMode::ContactSelector(s) =
std::mem::replace(&mut self.mode, ViewMode::Normal)
@ -506,21 +503,21 @@ impl Component for MailView {
self.mode = ViewMode::ContactSelector(Selector::new(entries, true));
self.dirty = true;
}
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Alt('')) => {
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt('')) => {
self.cmd_buf.clear();
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
});
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
}
UIEventType::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
UIEvent::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
self.cmd_buf.push(c);
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::BufSet(self.cmd_buf.clone())),
});
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::BufSet(
self.cmd_buf.clone(),
)));
}
UIEventType::Input(Key::Char('r'))
UIEvent::Input(Key::Char('r'))
if self.mode == ViewMode::Normal || self.mode == ViewMode::Raw =>
{
self.mode = if self.mode == ViewMode::Raw {
@ -530,22 +527,21 @@ impl Component for MailView {
};
self.dirty = true;
}
UIEventType::Input(Key::Char('r'))
UIEvent::Input(Key::Char('r'))
if self.mode.is_attachment() || self.mode == ViewMode::Subview =>
{
self.mode = ViewMode::Normal;
self.subview.take();
self.dirty = true;
}
UIEventType::Input(Key::Char('a'))
UIEvent::Input(Key::Char('a'))
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Normal =>
{
let lidx = self.cmd_buf.parse::<usize>().unwrap();
self.cmd_buf.clear();
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
});
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
{
let accounts = &context.accounts;
@ -571,12 +567,9 @@ impl Component for MailView {
)));
}
Err(e) => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(
StatusEvent::DisplayMessage(format!("{}", e)),
),
});
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!("{}", e)),
));
}
}
return true;
@ -587,15 +580,11 @@ impl Component for MailView {
self.dirty = true;
}
ContentType::Multipart { .. } => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(
StatusEvent::DisplayMessage(
"Multipart attachments are not supported yet."
.to_string(),
),
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(
"Multipart attachments are not supported yet.".to_string(),
),
});
));
return true;
}
ContentType::Unsupported { .. } => {
@ -613,39 +602,35 @@ impl Component for MailView {
});
context.temp_files.push(p);
} else {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Couldn't find a default application for type {}",
attachment_type
)),
),
});
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Couldn't find a default application for type {}",
attachment_type
)),
));
return true;
}
}
}
} else {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
format!("Attachment `{}` not found.", lidx),
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Attachment `{}` not found.",
lidx
)),
});
));
return true;
}
};
}
UIEventType::Input(Key::Char('g'))
UIEvent::Input(Key::Char('g'))
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Url =>
{
let lidx = self.cmd_buf.parse::<usize>().unwrap();
self.cmd_buf.clear();
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
});
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
let url = {
let accounts = &context.accounts;
let mailbox = &accounts[self.coordinates.0][self.coordinates.1]
@ -662,12 +647,9 @@ impl Component for MailView {
if let Some(u) = links.get(lidx) {
u.as_str().to_string()
} else {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
format!("Link `{}` not found.", lidx),
)),
});
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!("Link `{}` not found.", lidx)),
));
return true;
}
};
@ -679,7 +661,7 @@ impl Component for MailView {
.spawn()
.expect("Failed to start xdg_open");
}
UIEventType::Input(Key::Char('u')) => {
UIEvent::Input(Key::Char('u')) => {
match self.mode {
ViewMode::Normal => self.mode = ViewMode::Url,
ViewMode::Url => self.mode = ViewMode::Normal,
@ -687,9 +669,7 @@ impl Component for MailView {
}
self.dirty = true;
}
UIEventType::EnvelopeRename(_, old_hash, new_hash)
if old_hash == self.coordinates.2 =>
{
UIEvent::EnvelopeRename(_, old_hash, new_hash) if old_hash == self.coordinates.2 => {
self.coordinates.2 = new_hash;
self.set_dirty();
}

+ 42
- 58
ui/src/components/mail/view/envelope.rs View File

@ -107,16 +107,13 @@ impl EnvelopeView {
.stdout(Stdio::piped())
.spawn();
if command_obj.is_err() {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Notification(
Some(format!(
"Failed to start html filter process: {}",
filter_invocation,
)),
String::new(),
),
});
context.replies.push_back(UIEvent::Notification(
Some(format!(
"Failed to start html filter process: {}",
filter_invocation,
)),
String::new(),
));
return;
}
@ -372,20 +369,19 @@ impl Component for EnvelopeView {
return true;
}
}
match event.event_type {
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Alt('')) => {
match *event {
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt('')) => {
self.cmd_buf.clear();
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
});
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
return true;
}
UIEventType::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
UIEvent::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
self.cmd_buf.push(c);
return true;
}
UIEventType::Input(Key::Char('r'))
UIEvent::Input(Key::Char('r'))
if self.mode == ViewMode::Normal || self.mode == ViewMode::Raw =>
{
self.mode = if self.mode == ViewMode::Raw {
@ -396,7 +392,7 @@ impl Component for EnvelopeView {
self.dirty = true;
return true;
}
UIEventType::Input(Key::Char('r'))
UIEvent::Input(Key::Char('r'))
if self.mode.is_attachment() || self.mode == ViewMode::Subview =>
{
self.mode = ViewMode::Normal;
@ -404,15 +400,14 @@ impl Component for EnvelopeView {
self.dirty = true;
return true;
}
UIEventType::Input(Key::Char('a'))
UIEvent::Input(Key::Char('a'))
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Normal =>
{
let lidx = self.cmd_buf.parse::<usize>().unwrap();
self.cmd_buf.clear();
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
});
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
{
let envelope: &Envelope = self.wrapper.envelope();
@ -437,15 +432,11 @@ impl Component for EnvelopeView {
self.dirty = true;
}
ContentType::Multipart { .. } => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(
StatusEvent::DisplayMessage(
"Multipart attachments are not supported yet."
.to_string(),
),
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(
"Multipart attachments are not supported yet.".to_string(),
),
});
));
return true;
}
ContentType::Unsupported { .. } => {
@ -463,40 +454,36 @@ impl Component for EnvelopeView {
});
context.temp_files.push(p);
} else {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Couldn't find a default application for type {}",
attachment_type
)),
),
});
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Couldn't find a default application for type {}",
attachment_type
)),
));
return true;
}
}
}
} else {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
format!("Attachment `{}` not found.", lidx),
context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Attachment `{}` not found.",
lidx
)),
});
));
return true;
}
};
return true;
}
UIEventType::Input(Key::Char('g'))