ui: unwrap UIEventType
parent
106744c7ca
commit
9bc76e3bcb
16
src/bin.rs
16
src/bin.rs
|
@ -118,11 +118,11 @@ fn main() {
|
||||||
},
|
},
|
||||||
Key::Char(' ') => {
|
Key::Char(' ') => {
|
||||||
state.mode = UIMode::Execute;
|
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();
|
state.redraw();
|
||||||
}
|
}
|
||||||
key => {
|
key => {
|
||||||
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::Input(key)});
|
state.rcv_event(UIEvent::Input(key));
|
||||||
state.redraw();
|
state.redraw();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -131,11 +131,11 @@ fn main() {
|
||||||
match k {
|
match k {
|
||||||
Key::Char('\n') | Key::Esc => {
|
Key::Char('\n') | Key::Esc => {
|
||||||
state.mode = UIMode::Normal;
|
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();
|
state.redraw();
|
||||||
},
|
},
|
||||||
k => {
|
k => {
|
||||||
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::InsertInput(k)});
|
state.rcv_event(UIEvent::InsertInput(k));
|
||||||
state.redraw();
|
state.redraw();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -144,11 +144,11 @@ fn main() {
|
||||||
match k {
|
match k {
|
||||||
Key::Char('\n') | Key::Esc => {
|
Key::Char('\n') | Key::Esc => {
|
||||||
state.mode = UIMode::Normal;
|
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();
|
state.redraw();
|
||||||
},
|
},
|
||||||
k => {
|
k => {
|
||||||
state.rcv_event(UIEvent { id: 0, event_type: UIEventType::ExInput(k)});
|
state.rcv_event(UIEvent::ExInput(k));
|
||||||
state.redraw();
|
state.redraw();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -162,14 +162,14 @@ fn main() {
|
||||||
state.refresh_event(*event);
|
state.refresh_event(*event);
|
||||||
state.redraw();
|
state.redraw();
|
||||||
},
|
},
|
||||||
ThreadEvent::UIEvent(UIEventType::ChangeMode(f)) => {
|
ThreadEvent::UIEvent(UIEvent::ChangeMode(f)) => {
|
||||||
state.mode = f;
|
state.mode = f;
|
||||||
if f == UIMode::Fork {
|
if f == UIMode::Fork {
|
||||||
break 'inner; // `goto` 'reap loop, and wait on child.
|
break 'inner; // `goto` 'reap loop, and wait on child.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ThreadEvent::UIEvent(e) => {
|
ThreadEvent::UIEvent(e) => {
|
||||||
state.rcv_event(UIEvent { id: 0, event_type: e});
|
state.rcv_event(e);
|
||||||
state.render();
|
state.render();
|
||||||
},
|
},
|
||||||
ThreadEvent::ThreadJoin(id) => {
|
ThreadEvent::ThreadJoin(id) => {
|
||||||
|
|
|
@ -48,7 +48,7 @@ use std::ops::{Deref, DerefMut};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{Key, StatusEvent, UIEvent, UIEventType};
|
use super::{Key, StatusEvent, UIEvent};
|
||||||
/// The upper and lower boundary char.
|
/// The upper and lower boundary char.
|
||||||
const HORZ_BOUNDARY: char = '─';
|
const HORZ_BOUNDARY: char = '─';
|
||||||
/// The left and right boundary char.
|
/// The left and right boundary char.
|
||||||
|
|
|
@ -161,32 +161,25 @@ impl Component for ContactManager {
|
||||||
context.accounts[self.account_pos]
|
context.accounts[self.account_pos]
|
||||||
.address_book
|
.address_book
|
||||||
.add_card(new_card);
|
.add_card(new_card);
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
|
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||||
"Saved.".into(),
|
"Saved.".into(),
|
||||||
)),
|
)));
|
||||||
});
|
context.replies.push_back(UIEvent::ComponentKill(self.id));
|
||||||
context.replies.push_back(UIEvent {
|
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::ComponentKill(self.id),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Some(false) => {
|
Some(false) => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::ComponentKill(self.id));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::ComponentKill(self.id),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Char('\n')) => {
|
UIEvent::Input(Key::Char('\n')) => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent {
|
||||||
id: 0,
|
id: 0,
|
||||||
event_type: UIEventType::ComponentKill(self.id),
|
event_type: UIEvent::ComponentKill(self.id),
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
|
@ -168,10 +168,7 @@ impl ContactList {
|
||||||
impl Component for ContactList {
|
impl Component for ContactList {
|
||||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||||
if let ViewMode::Close(u) = self.mode {
|
if let ViewMode::Close(u) = self.mode {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Action(Tab(Kill(u))));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::Action(Tab(Kill(u))),
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,8 +229,8 @@ impl Component for ContactList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let shortcuts = self.get_shortcuts(context);
|
let shortcuts = self.get_shortcuts(context);
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(ref key) if *key == shortcuts["create_contact"] => {
|
UIEvent::Input(ref key) if *key == shortcuts["create_contact"] => {
|
||||||
let mut manager = ContactManager::default();
|
let mut manager = ContactManager::default();
|
||||||
manager.account_pos = self.account_pos;
|
manager.account_pos = self.account_pos;
|
||||||
let component = Box::new(manager);
|
let component = Box::new(manager);
|
||||||
|
@ -244,7 +241,7 @@ impl Component for ContactList {
|
||||||
return true;
|
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 account = &mut context.accounts[self.account_pos];
|
||||||
let book = &mut account.address_book;
|
let book = &mut account.address_book;
|
||||||
let card = book[&self.id_positions[self.cursor_pos]].clone();
|
let card = book[&self.id_positions[self.cursor_pos]].clone();
|
||||||
|
@ -258,7 +255,7 @@ impl Component for ContactList {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('n')) => {
|
UIEvent::Input(Key::Char('n')) => {
|
||||||
let card = Card::new();
|
let card = Card::new();
|
||||||
let mut manager = ContactManager::default();
|
let mut manager = ContactManager::default();
|
||||||
manager.card = card;
|
manager.card = card;
|
||||||
|
@ -269,17 +266,17 @@ impl Component for ContactList {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
self.new_cursor_pos = self.cursor_pos.saturating_sub(1);
|
self.new_cursor_pos = self.cursor_pos.saturating_sub(1);
|
||||||
return true;
|
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.set_dirty();
|
||||||
self.new_cursor_pos += 1;
|
self.new_cursor_pos += 1;
|
||||||
return true;
|
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.mode = ViewMode::List;
|
||||||
self.view.take();
|
self.view.take();
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
|
|
|
@ -105,14 +105,14 @@ impl Component for Indexer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::RefreshMailbox(_) => {
|
UIEvent::RefreshMailbox(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -128,35 +128,35 @@ impl Component for Index {
|
||||||
if self.content.process_event(event, context) {
|
if self.content.process_event(event, context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
if self.cursor_pos > 0 {
|
if self.cursor_pos > 0 {
|
||||||
self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1);
|
self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1);
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
if self.length > 0 && self.new_cursor_pos < self.length - 1 {
|
if self.length > 0 && self.new_cursor_pos < self.length - 1 {
|
||||||
self.new_cursor_pos += 1;
|
self.new_cursor_pos += 1;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
return true;
|
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.state = IndexState::Unfocused;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
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.state = IndexState::Listing;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -263,25 +263,25 @@ impl Component for AccountMenu {
|
||||||
context.dirty_areas.push_back(area);
|
context.dirty_areas.push_back(area);
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::RefreshMailbox(c) => {
|
UIEvent::RefreshMailbox(c) => {
|
||||||
self.cursor = Some(c);
|
self.cursor = Some(c);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('`')) => {
|
UIEvent::Input(Key::Char('`')) => {
|
||||||
self.visible = !self.visible;
|
self.visible = !self.visible;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::StartupCheck(_) => {
|
UIEvent::StartupCheck(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::MailboxUpdate(_) => {
|
UIEvent::MailboxUpdate(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -49,29 +49,28 @@ impl Component for AccountsPanel {
|
||||||
context.dirty_areas.push_back(area);
|
context.dirty_areas.push_back(area);
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
self.cursor = self.cursor.saturating_sub(1);
|
self.cursor = self.cursor.saturating_sub(1);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
if self.cursor + 1 < context.accounts.len() {
|
if self.cursor + 1 < context.accounts.len() {
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('\n')) => {
|
UIEvent::Input(Key::Char('\n')) => {
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::Action(Tab(TabOpen(Some(Box::new(
|
.push_back(UIEvent::Action(Tab(TabOpen(Some(Box::new(
|
||||||
ContactList::for_account(self.cursor),
|
ContactList::for_account(self.cursor),
|
||||||
))))),
|
))))));
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::MailboxUpdate(_) => {
|
UIEvent::MailboxUpdate(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -431,9 +431,9 @@ impl Component for Composer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
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
|
// 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)), _) => {
|
(ViewMode::Overview, Some((_, ref mut view)), _) => {
|
||||||
if view.process_event(event, context) {
|
if view.process_event(event, context) {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
@ -456,13 +456,13 @@ impl Component for Composer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
/* Switch e-mail From: field to the `left` configured account. */
|
/* 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.account_cursor = self.account_cursor.saturating_sub(1);
|
||||||
self.draft.headers_mut().insert(
|
self.draft.headers_mut().insert(
|
||||||
"From".into(),
|
"From".into(),
|
||||||
|
@ -472,7 +472,7 @@ impl Component for Composer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* Switch e-mail From: field to the `right` configured account. */
|
/* 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() {
|
if self.account_cursor + 1 < context.accounts.len() {
|
||||||
self.account_cursor += 1;
|
self.account_cursor += 1;
|
||||||
self.draft.headers_mut().insert(
|
self.draft.headers_mut().insert(
|
||||||
|
@ -483,19 +483,16 @@ impl Component for Composer {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}*/
|
}*/
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
self.cursor = Cursor::Headers;
|
self.cursor = Cursor::Headers;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
self.cursor = Cursor::Body;
|
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) {
|
match (key, &self.mode) {
|
||||||
('x', ViewMode::Discard(u)) => {
|
('x', ViewMode::Discard(u)) => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Action(Tab(Kill(*u))));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::Action(Tab(Kill(*u))),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
('n', _) => {}
|
('n', _) => {}
|
||||||
|
@ -506,18 +503,12 @@ impl Component for Composer {
|
||||||
if cfg!(feature = "debug_log") {
|
if cfg!(feature = "debug_log") {
|
||||||
eprintln!("{:?} could not save draft", e);
|
eprintln!("{:?} could not save draft", e);
|
||||||
}
|
}
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some("Could not save draft.".into()),
|
||||||
event_type: UIEventType::Notification(
|
e.into(),
|
||||||
Some("Could not save draft.".into()),
|
));
|
||||||
e.into(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Action(Tab(Kill(*u))));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::Action(Tab(Kill(*u))),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -529,18 +520,18 @@ impl Component for Composer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* Switch to Overview mode if we're on Edit mode */
|
/* 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.mode = ViewMode::Overview;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* Switch to Edit mode if we're on Overview mode */
|
/* 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.mode = ViewMode::Edit;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
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::io::Write;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
let settings = &context.settings;
|
let settings = &context.settings;
|
||||||
|
@ -568,31 +559,25 @@ impl Component for Composer {
|
||||||
if cfg!(feature = "debug_log") {
|
if cfg!(feature = "debug_log") {
|
||||||
eprintln!("{:?} could not save sent msg", e);
|
eprintln!("{:?} could not save sent msg", e);
|
||||||
}
|
}
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some("Could not save in 'Sent' folder.".into()),
|
||||||
event_type: UIEventType::Notification(
|
e.into(),
|
||||||
Some("Could not save in 'Sent' folder.".into()),
|
));
|
||||||
e.into(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some("Sent.".into()),
|
||||||
event_type: UIEventType::Notification(
|
format!(
|
||||||
Some("Sent.".into()),
|
"Mailer output: {:#?}",
|
||||||
format!(
|
msmtp
|
||||||
"Mailer output: {:#?}",
|
.wait_with_output()
|
||||||
msmtp
|
.expect("Failed to wait on filter")
|
||||||
.wait_with_output()
|
.stdout
|
||||||
.expect("Failed to wait on filter")
|
|
||||||
.stdout
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
});
|
));
|
||||||
return true;
|
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 */
|
/* Edit draft in $EDITOR */
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
/* Kill input thread so that spawned command can be sole receiver of stdin */
|
/* 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();
|
let result = f.read_to_string();
|
||||||
self.draft = Draft::from_str(result.as_str()).unwrap();
|
self.draft = Draft::from_str(result.as_str()).unwrap();
|
||||||
self.initialized = false;
|
self.initialized = false;
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Fork(ForkType::Finished));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::Fork(ForkType::Finished),
|
|
||||||
});
|
|
||||||
context.restore_input();
|
context.restore_input();
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
|
@ -75,9 +75,9 @@ impl Component for Listing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Resize => self.set_dirty(),
|
UIEvent::Resize => self.set_dirty(),
|
||||||
UIEventType::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
Action::Listing(ListingAction::SetPlain) => {
|
Action::Listing(ListingAction::SetPlain) => {
|
||||||
let new_l = match self {
|
let new_l = match self {
|
||||||
Listing::Plain(_) => {
|
Listing::Plain(_) => {
|
||||||
|
|
|
@ -106,10 +106,10 @@ impl MailboxView {
|
||||||
self.cursor_pos.0 = self.new_cursor_pos.0;
|
self.cursor_pos.0 = self.new_cursor_pos.0;
|
||||||
|
|
||||||
// Inform State that we changed the current folder view.
|
// Inform State that we changed the current folder view.
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::RefreshMailbox((
|
||||||
id: 0,
|
self.cursor_pos.0,
|
||||||
event_type: UIEventType::RefreshMailbox((self.cursor_pos.0, self.cursor_pos.1)),
|
self.cursor_pos.1,
|
||||||
});
|
)));
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
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);
|
let shortcuts = self.get_shortcuts(context);
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
if self.cursor_pos.2 > 0 {
|
if self.cursor_pos.2 > 0 {
|
||||||
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(1);
|
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(1);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
|
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
|
||||||
self.new_cursor_pos.2 += 1;
|
self.new_cursor_pos.2 += 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return 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.view = ThreadView::new(self.cursor_pos, None, context);
|
||||||
self.unfocused = true;
|
self.unfocused = true;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return 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.movement = Some(PageMovement::PageUp);
|
||||||
self.set_dirty();
|
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.movement = Some(PageMovement::PageDown);
|
||||||
self.set_dirty();
|
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.unfocused = false;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return 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();
|
let folder_length = context.accounts[self.cursor_pos.0].len();
|
||||||
match k {
|
match k {
|
||||||
'J' if folder_length > 0 && self.new_cursor_pos.1 < folder_length - 1 => {
|
'J' if folder_length > 0 && self.new_cursor_pos.1 < folder_length - 1 => {
|
||||||
|
@ -435,28 +435,28 @@ impl Component for MailboxView {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::RefreshMailbox(_) => {
|
UIEvent::RefreshMailbox(_) => {
|
||||||
self.dirty = true;
|
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 =>
|
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
self.set_dirty();
|
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) =>
|
if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
Action::ViewMailbox(idx) => {
|
Action::ViewMailbox(idx) => {
|
||||||
self.new_cursor_pos.1 = *idx;
|
self.new_cursor_pos.1 = *idx;
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
|
@ -480,11 +480,10 @@ impl Component for MailboxView {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
UIEventType::Input(Key::Char('m')) if !self.unfocused => {
|
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::Action(Tab(NewDraft(self.cursor_pos.0))),
|
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -665,8 +664,8 @@ impl Component for CompactListing {
|
||||||
if self.views.is_empty() {
|
if self.views.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
match event.event_type {
|
match *event {
|
||||||
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.views[self.cursor].cursor_pos.0].len();
|
let folder_length = context.accounts[self.views[self.cursor].cursor_pos.0].len();
|
||||||
match k {
|
match k {
|
||||||
'J' if folder_length > 0 => {
|
'J' if folder_length > 0 => {
|
||||||
|
@ -684,7 +683,7 @@ impl Component for CompactListing {
|
||||||
self.views[self.cursor].refresh_mailbox(context);
|
self.views[self.cursor].refresh_mailbox(context);
|
||||||
return true;
|
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> {
|
let binary_search_account = |entries: &[MailboxView], x: usize| -> Option<usize> {
|
||||||
if entries.is_empty() {
|
if entries.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -107,10 +107,10 @@ impl PlainListing {
|
||||||
self.cursor_pos.1 = self.new_cursor_pos.1;
|
self.cursor_pos.1 = self.new_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 {
|
context.replies.push_back(UIEvent::RefreshMailbox((
|
||||||
id: 0,
|
self.cursor_pos.0,
|
||||||
event_type: UIEventType::RefreshMailbox((self.cursor_pos.0, self.cursor_pos.1)),
|
self.cursor_pos.1,
|
||||||
});
|
)));
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
|
@ -416,40 +416,39 @@ impl Component for PlainListing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
if self.cursor_pos.2 > 0 {
|
if self.cursor_pos.2 > 0 {
|
||||||
self.new_cursor_pos.2 -= 1;
|
self.new_cursor_pos.2 -= 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
|
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
|
||||||
self.new_cursor_pos.2 += 1;
|
self.new_cursor_pos.2 += 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('\n')) if !self.unfocused => {
|
UIEvent::Input(Key::Char('\n')) if !self.unfocused => {
|
||||||
self.unfocused = true;
|
self.unfocused = true;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('m')) if !self.unfocused => {
|
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::Action(Tab(NewDraft(self.cursor_pos.0))),
|
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::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;
|
||||||
}
|
}
|
||||||
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 folder_length = context.accounts[self.cursor_pos.0].len();
|
||||||
let accounts_length = context.accounts.len();
|
let accounts_length = context.accounts.len();
|
||||||
match k {
|
match k {
|
||||||
|
@ -482,7 +481,7 @@ impl Component for PlainListing {
|
||||||
}
|
}
|
||||||
return true;
|
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();
|
let accounts_length = context.accounts.len();
|
||||||
match k {
|
match k {
|
||||||
'h' if accounts_length > 0 && self.new_cursor_pos.0 < accounts_length - 1 => {
|
'h' if accounts_length > 0 && self.new_cursor_pos.0 < accounts_length - 1 => {
|
||||||
|
@ -501,29 +500,29 @@ impl Component for PlainListing {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::RefreshMailbox(_) => {
|
UIEvent::RefreshMailbox(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.view = None;
|
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 =>
|
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
self.set_dirty();
|
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) =>
|
if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
Action::ViewMailbox(idx) => {
|
Action::ViewMailbox(idx) => {
|
||||||
self.new_cursor_pos.1 = *idx;
|
self.new_cursor_pos.1 = *idx;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
|
@ -105,10 +105,10 @@ impl ThreadListing {
|
||||||
self.cursor_pos.0 = self.new_cursor_pos.0;
|
self.cursor_pos.0 = self.new_cursor_pos.0;
|
||||||
|
|
||||||
// Inform State that we changed the current folder view.
|
// Inform State that we changed the current folder view.
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::RefreshMailbox((
|
||||||
id: 0,
|
self.cursor_pos.0,
|
||||||
event_type: UIEventType::RefreshMailbox((self.cursor_pos.0, self.cursor_pos.1)),
|
self.cursor_pos.1,
|
||||||
});
|
)));
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) {
|
||||||
|
@ -578,40 +578,39 @@ impl Component for ThreadListing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
if self.cursor_pos.2 > 0 {
|
if self.cursor_pos.2 > 0 {
|
||||||
self.new_cursor_pos.2 -= 1;
|
self.new_cursor_pos.2 -= 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
|
if self.length > 0 && self.new_cursor_pos.2 < self.length - 1 {
|
||||||
self.new_cursor_pos.2 += 1;
|
self.new_cursor_pos.2 += 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('\n')) if !self.unfocused => {
|
UIEvent::Input(Key::Char('\n')) if !self.unfocused => {
|
||||||
self.unfocused = true;
|
self.unfocused = true;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('m')) if !self.unfocused => {
|
UIEvent::Input(Key::Char('m')) if !self.unfocused => {
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::Action(Tab(NewDraft(self.cursor_pos.0))),
|
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0))));
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::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;
|
||||||
}
|
}
|
||||||
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 folder_length = context.accounts[self.cursor_pos.0].len();
|
||||||
let accounts_length = context.accounts.len();
|
let accounts_length = context.accounts.len();
|
||||||
match k {
|
match k {
|
||||||
|
@ -644,7 +643,7 @@ impl Component for ThreadListing {
|
||||||
}
|
}
|
||||||
return true;
|
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();
|
let accounts_length = context.accounts.len();
|
||||||
match k {
|
match k {
|
||||||
'h' if accounts_length > 0 && self.new_cursor_pos.0 < accounts_length - 1 => {
|
'h' if accounts_length > 0 && self.new_cursor_pos.0 < accounts_length - 1 => {
|
||||||
|
@ -663,29 +662,29 @@ impl Component for ThreadListing {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::RefreshMailbox(_) => {
|
UIEvent::RefreshMailbox(_) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.view = None;
|
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 =>
|
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
self.set_dirty();
|
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) =>
|
if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
|
||||||
{
|
{
|
||||||
self.refresh_mailbox(context);
|
self.refresh_mailbox(context);
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
Action::ViewMailbox(idx_m) => {
|
Action::ViewMailbox(idx_m) => {
|
||||||
self.new_cursor_pos.1 = *idx_m;
|
self.new_cursor_pos.1 = *idx_m;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
|
@ -140,16 +140,13 @@ impl MailView {
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn();
|
.spawn();
|
||||||
if command_obj.is_err() {
|
if command_obj.is_err() {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some(format!(
|
||||||
event_type: UIEventType::Notification(
|
"Failed to start html filter process: {}",
|
||||||
Some(format!(
|
filter_invocation,
|
||||||
"Failed to start html filter process: {}",
|
)),
|
||||||
filter_invocation,
|
String::new(),
|
||||||
)),
|
));
|
||||||
String::new(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,8 +447,8 @@ impl Component for MailView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Char('c')) => {
|
UIEvent::Input(Key::Char('c')) => {
|
||||||
if let ViewMode::ContactSelector(_) = self.mode {
|
if let ViewMode::ContactSelector(_) = self.mode {
|
||||||
if let ViewMode::ContactSelector(s) =
|
if let ViewMode::ContactSelector(s) =
|
||||||
std::mem::replace(&mut self.mode, ViewMode::Normal)
|
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.mode = ViewMode::ContactSelector(Selector::new(entries, true));
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Alt('')) => {
|
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt('')) => {
|
||||||
self.cmd_buf.clear();
|
self.cmd_buf.clear();
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
|
.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);
|
self.cmd_buf.push(c);
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufSet(self.cmd_buf.clone())),
|
.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 =>
|
if self.mode == ViewMode::Normal || self.mode == ViewMode::Raw =>
|
||||||
{
|
{
|
||||||
self.mode = if self.mode == ViewMode::Raw {
|
self.mode = if self.mode == ViewMode::Raw {
|
||||||
|
@ -530,22 +527,21 @@ impl Component for MailView {
|
||||||
};
|
};
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('r'))
|
UIEvent::Input(Key::Char('r'))
|
||||||
if self.mode.is_attachment() || self.mode == ViewMode::Subview =>
|
if self.mode.is_attachment() || self.mode == ViewMode::Subview =>
|
||||||
{
|
{
|
||||||
self.mode = ViewMode::Normal;
|
self.mode = ViewMode::Normal;
|
||||||
self.subview.take();
|
self.subview.take();
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('a'))
|
UIEvent::Input(Key::Char('a'))
|
||||||
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Normal =>
|
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Normal =>
|
||||||
{
|
{
|
||||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||||
self.cmd_buf.clear();
|
self.cmd_buf.clear();
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||||
});
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let accounts = &context.accounts;
|
let accounts = &context.accounts;
|
||||||
|
@ -571,12 +567,9 @@ impl Component for MailView {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!("{}", e)),
|
||||||
event_type: UIEventType::StatusEvent(
|
));
|
||||||
StatusEvent::DisplayMessage(format!("{}", e)),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -587,15 +580,11 @@ impl Component for MailView {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
ContentType::Multipart { .. } => {
|
ContentType::Multipart { .. } => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(
|
||||||
event_type: UIEventType::StatusEvent(
|
"Multipart attachments are not supported yet.".to_string(),
|
||||||
StatusEvent::DisplayMessage(
|
|
||||||
"Multipart attachments are not supported yet."
|
|
||||||
.to_string(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
});
|
));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ContentType::Unsupported { .. } => {
|
ContentType::Unsupported { .. } => {
|
||||||
|
@ -613,39 +602,35 @@ impl Component for MailView {
|
||||||
});
|
});
|
||||||
context.temp_files.push(p);
|
context.temp_files.push(p);
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!(
|
||||||
event_type: UIEventType::StatusEvent(
|
"Couldn't find a default application for type {}",
|
||||||
StatusEvent::DisplayMessage(format!(
|
attachment_type
|
||||||
"Couldn't find a default application for type {}",
|
)),
|
||||||
attachment_type
|
));
|
||||||
)),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!(
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
|
"Attachment `{}` not found.",
|
||||||
format!("Attachment `{}` not found.", lidx),
|
lidx
|
||||||
)),
|
)),
|
||||||
});
|
));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('g'))
|
UIEvent::Input(Key::Char('g'))
|
||||||
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Url =>
|
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Url =>
|
||||||
{
|
{
|
||||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||||
self.cmd_buf.clear();
|
self.cmd_buf.clear();
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||||
});
|
|
||||||
let url = {
|
let url = {
|
||||||
let accounts = &context.accounts;
|
let accounts = &context.accounts;
|
||||||
let mailbox = &accounts[self.coordinates.0][self.coordinates.1]
|
let mailbox = &accounts[self.coordinates.0][self.coordinates.1]
|
||||||
|
@ -662,12 +647,9 @@ impl Component for MailView {
|
||||||
if let Some(u) = links.get(lidx) {
|
if let Some(u) = links.get(lidx) {
|
||||||
u.as_str().to_string()
|
u.as_str().to_string()
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!("Link `{}` not found.", lidx)),
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
|
));
|
||||||
format!("Link `{}` not found.", lidx),
|
|
||||||
)),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -679,7 +661,7 @@ impl Component for MailView {
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("Failed to start xdg_open");
|
.expect("Failed to start xdg_open");
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('u')) => {
|
UIEvent::Input(Key::Char('u')) => {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
ViewMode::Normal => self.mode = ViewMode::Url,
|
ViewMode::Normal => self.mode = ViewMode::Url,
|
||||||
ViewMode::Url => self.mode = ViewMode::Normal,
|
ViewMode::Url => self.mode = ViewMode::Normal,
|
||||||
|
@ -687,9 +669,7 @@ impl Component for MailView {
|
||||||
}
|
}
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::EnvelopeRename(_, old_hash, new_hash)
|
UIEvent::EnvelopeRename(_, old_hash, new_hash) if old_hash == self.coordinates.2 => {
|
||||||
if old_hash == self.coordinates.2 =>
|
|
||||||
{
|
|
||||||
self.coordinates.2 = new_hash;
|
self.coordinates.2 = new_hash;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,16 +107,13 @@ impl EnvelopeView {
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn();
|
.spawn();
|
||||||
if command_obj.is_err() {
|
if command_obj.is_err() {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some(format!(
|
||||||
event_type: UIEventType::Notification(
|
"Failed to start html filter process: {}",
|
||||||
Some(format!(
|
filter_invocation,
|
||||||
"Failed to start html filter process: {}",
|
)),
|
||||||
filter_invocation,
|
String::new(),
|
||||||
)),
|
));
|
||||||
String::new(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,20 +369,19 @@ impl Component for EnvelopeView {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Esc) | UIEventType::Input(Key::Alt('')) => {
|
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt('')) => {
|
||||||
self.cmd_buf.clear();
|
self.cmd_buf.clear();
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||||
});
|
|
||||||
return true;
|
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);
|
self.cmd_buf.push(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('r'))
|
UIEvent::Input(Key::Char('r'))
|
||||||
if self.mode == ViewMode::Normal || self.mode == ViewMode::Raw =>
|
if self.mode == ViewMode::Normal || self.mode == ViewMode::Raw =>
|
||||||
{
|
{
|
||||||
self.mode = if self.mode == ViewMode::Raw {
|
self.mode = if self.mode == ViewMode::Raw {
|
||||||
|
@ -396,7 +392,7 @@ impl Component for EnvelopeView {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('r'))
|
UIEvent::Input(Key::Char('r'))
|
||||||
if self.mode.is_attachment() || self.mode == ViewMode::Subview =>
|
if self.mode.is_attachment() || self.mode == ViewMode::Subview =>
|
||||||
{
|
{
|
||||||
self.mode = ViewMode::Normal;
|
self.mode = ViewMode::Normal;
|
||||||
|
@ -404,15 +400,14 @@ impl Component for EnvelopeView {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('a'))
|
UIEvent::Input(Key::Char('a'))
|
||||||
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Normal =>
|
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Normal =>
|
||||||
{
|
{
|
||||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||||
self.cmd_buf.clear();
|
self.cmd_buf.clear();
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||||
});
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let envelope: &Envelope = self.wrapper.envelope();
|
let envelope: &Envelope = self.wrapper.envelope();
|
||||||
|
@ -437,15 +432,11 @@ impl Component for EnvelopeView {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
ContentType::Multipart { .. } => {
|
ContentType::Multipart { .. } => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(
|
||||||
event_type: UIEventType::StatusEvent(
|
"Multipart attachments are not supported yet.".to_string(),
|
||||||
StatusEvent::DisplayMessage(
|
|
||||||
"Multipart attachments are not supported yet."
|
|
||||||
.to_string(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
});
|
));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ContentType::Unsupported { .. } => {
|
ContentType::Unsupported { .. } => {
|
||||||
|
@ -463,40 +454,36 @@ impl Component for EnvelopeView {
|
||||||
});
|
});
|
||||||
context.temp_files.push(p);
|
context.temp_files.push(p);
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!(
|
||||||
event_type: UIEventType::StatusEvent(
|
"Couldn't find a default application for type {}",
|
||||||
StatusEvent::DisplayMessage(format!(
|
attachment_type
|
||||||
"Couldn't find a default application for type {}",
|
)),
|
||||||
attachment_type
|
));
|
||||||
)),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!(
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
|
"Attachment `{}` not found.",
|
||||||
format!("Attachment `{}` not found.", lidx),
|
lidx
|
||||||
)),
|
)),
|
||||||
});
|
));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('g'))
|
UIEvent::Input(Key::Char('g'))
|
||||||
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Url =>
|
if !self.cmd_buf.is_empty() && self.mode == ViewMode::Url =>
|
||||||
{
|
{
|
||||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||||
self.cmd_buf.clear();
|
self.cmd_buf.clear();
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::BufClear),
|
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||||
});
|
|
||||||
let url = {
|
let url = {
|
||||||
let envelope: &Envelope = self.wrapper.envelope();
|
let envelope: &Envelope = self.wrapper.envelope();
|
||||||
let finder = LinkFinder::new();
|
let finder = LinkFinder::new();
|
||||||
|
@ -508,12 +495,9 @@ impl Component for EnvelopeView {
|
||||||
if let Some(u) = links.get(lidx) {
|
if let Some(u) = links.get(lidx) {
|
||||||
u.as_str().to_string()
|
u.as_str().to_string()
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::StatusEvent(
|
||||||
id: 0,
|
StatusEvent::DisplayMessage(format!("Link `{}` not found.", lidx)),
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
|
));
|
||||||
format!("Link `{}` not found.", lidx),
|
|
||||||
)),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -526,7 +510,7 @@ impl Component for EnvelopeView {
|
||||||
.expect("Failed to start xdg_open");
|
.expect("Failed to start xdg_open");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('u')) => {
|
UIEvent::Input(Key::Char('u')) => {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
ViewMode::Normal => self.mode = ViewMode::Url,
|
ViewMode::Normal => self.mode = ViewMode::Url,
|
||||||
ViewMode::Url => self.mode = ViewMode::Normal,
|
ViewMode::Url => self.mode = ViewMode::Normal,
|
||||||
|
|
|
@ -43,16 +43,13 @@ impl HtmlView {
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn();
|
.spawn();
|
||||||
if command_obj.is_err() {
|
if command_obj.is_err() {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some(format!(
|
||||||
event_type: UIEventType::Notification(
|
"Failed to start html filter process: {}",
|
||||||
Some(format!(
|
filter_invocation
|
||||||
"Failed to start html filter process: {}",
|
)),
|
||||||
filter_invocation
|
String::new(),
|
||||||
)),
|
));
|
||||||
String::new(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
let pager = Pager::from_string(
|
let pager = Pager::from_string(
|
||||||
String::from_utf8_lossy(&bytes).to_string(),
|
String::from_utf8_lossy(&bytes).to_string(),
|
||||||
None,
|
None,
|
||||||
|
@ -102,15 +99,12 @@ impl HtmlView {
|
||||||
let pager = Pager::from_string(display_text, None, None, None);
|
let pager = Pager::from_string(display_text, None, None, None);
|
||||||
HtmlView { pager, bytes, id }
|
HtmlView { pager, bytes, id }
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Notification(
|
||||||
id: 0,
|
Some(format!(
|
||||||
event_type: UIEventType::Notification(
|
"Failed to find any application to use as html filter"
|
||||||
Some(format!(
|
)),
|
||||||
"Failed to find any application to use as html filter"
|
String::new(),
|
||||||
)),
|
));
|
||||||
String::new(),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
let pager = Pager::from_string(
|
let pager = Pager::from_string(
|
||||||
String::from_utf8_lossy(&bytes).to_string(),
|
String::from_utf8_lossy(&bytes).to_string(),
|
||||||
None,
|
None,
|
||||||
|
@ -139,7 +133,7 @@ impl Component for HtmlView {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let UIEventType::Input(Key::Char('v')) = event.event_type {
|
if let UIEvent::Input(Key::Char('v')) = event {
|
||||||
// TODO: Optional filter that removes outgoing resource requests (images and
|
// TODO: Optional filter that removes outgoing resource requests (images and
|
||||||
// scripts)
|
// scripts)
|
||||||
let binary = query_default_app("text/html");
|
let binary = query_default_app("text/html");
|
||||||
|
@ -153,12 +147,11 @@ impl Component for HtmlView {
|
||||||
.unwrap_or_else(|_| panic!("Failed to start {}", binary.display()));
|
.unwrap_or_else(|_| panic!("Failed to start {}", binary.display()));
|
||||||
context.temp_files.push(p);
|
context.temp_files.push(p);
|
||||||
} else {
|
} else {
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::StatusEvent(StatusEvent::DisplayMessage(
|
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||||
"Couldn't find a default application for html files.".to_string(),
|
"Couldn't find a default application for html files.".to_string(),
|
||||||
)),
|
)));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -847,18 +847,15 @@ impl Component for ThreadView {
|
||||||
if self.mailview.process_event(event, context) {
|
if self.mailview.process_event(event, context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Char('R')) => {
|
UIEvent::Input(Key::Char('R')) => {
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Action(Tab(Reply(
|
||||||
id: 0,
|
self.coordinates,
|
||||||
event_type: UIEventType::Action(Tab(Reply(
|
self.entries[self.expanded_pos].index.1,
|
||||||
self.coordinates,
|
))));
|
||||||
self.entries[self.expanded_pos].index.1,
|
|
||||||
))),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('e')) => {
|
UIEvent::Input(Key::Char('e')) => {
|
||||||
{
|
{
|
||||||
let mailbox = &context.accounts[self.coordinates.0][self.coordinates.1]
|
let mailbox = &context.accounts[self.coordinates.0][self.coordinates.1]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -884,29 +881,26 @@ impl Component for ThreadView {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.replies.push_back(UIEvent {
|
context.replies.push_back(UIEvent::Action(Tab(Edit(
|
||||||
id: 0,
|
self.coordinates,
|
||||||
event_type: UIEventType::Action(Tab(Edit(
|
self.entries[self.expanded_pos].index.1,
|
||||||
self.coordinates,
|
))));
|
||||||
self.entries[self.expanded_pos].index.1,
|
|
||||||
))),
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
if self.cursor_pos > 0 {
|
if self.cursor_pos > 0 {
|
||||||
self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1);
|
self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) => {
|
UIEvent::Input(Key::Down) => {
|
||||||
let height = self.visible_entries.iter().flat_map(|v| v.iter()).count();
|
let height = self.visible_entries.iter().flat_map(|v| v.iter()).count();
|
||||||
if height > 0 && self.new_cursor_pos + 1 < height {
|
if height > 0 && self.new_cursor_pos + 1 < height {
|
||||||
self.new_cursor_pos += 1;
|
self.new_cursor_pos += 1;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('\n')) => {
|
UIEvent::Input(Key::Char('\n')) => {
|
||||||
if self.entries.len() < 2 {
|
if self.entries.len() < 2 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -916,13 +910,13 @@ impl Component for ThreadView {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('p')) => {
|
UIEvent::Input(Key::Char('p')) => {
|
||||||
self.show_mailview = !self.show_mailview;
|
self.show_mailview = !self.show_mailview;
|
||||||
self.initiated = false;
|
self.initiated = false;
|
||||||
self.mailview.set_dirty();
|
self.mailview.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Ctrl('r')) => {
|
UIEvent::Input(Key::Ctrl('r')) => {
|
||||||
self.reversed = !self.reversed;
|
self.reversed = !self.reversed;
|
||||||
let expanded_pos = self.expanded_pos;
|
let expanded_pos = self.expanded_pos;
|
||||||
self.initiate(Some(expanded_pos), context);
|
self.initiate(Some(expanded_pos), context);
|
||||||
|
@ -930,7 +924,7 @@ impl Component for ThreadView {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('h')) => {
|
UIEvent::Input(Key::Char('h')) => {
|
||||||
let current_pos = self.current_pos();
|
let current_pos = self.current_pos();
|
||||||
self.entries[current_pos].hidden = !self.entries[current_pos].hidden;
|
self.entries[current_pos].hidden = !self.entries[current_pos].hidden;
|
||||||
self.entries[current_pos].dirty = true;
|
self.entries[current_pos].dirty = true;
|
||||||
|
@ -960,7 +954,7 @@ impl Component for ThreadView {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl fmt::Display for XDGNotifications {
|
||||||
impl Component for XDGNotifications {
|
impl Component for XDGNotifications {
|
||||||
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||||
if let UIEventType::Notification(ref title, ref body) = event.event_type {
|
if let UIEvent::Notification(ref title, ref body) = event {
|
||||||
notify_Notification::new()
|
notify_Notification::new()
|
||||||
.appname("meli")
|
.appname("meli")
|
||||||
.icon("mail-message-new")
|
.icon("mail-message-new")
|
||||||
|
@ -121,7 +121,7 @@ impl fmt::Display for NotificationFilter {
|
||||||
impl Component for NotificationFilter {
|
impl Component for NotificationFilter {
|
||||||
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||||
if let UIEventType::Notification(ref title, ref body) = event.event_type {
|
if let UIEvent::Notification(ref title, ref body) = event {
|
||||||
if let Some(ref bin) = context.runtime_settings.notifications.script {
|
if let Some(ref bin) = context.runtime_settings.notifications.script {
|
||||||
if let Err(v) = Command::new(bin)
|
if let Err(v) = Command::new(bin)
|
||||||
.arg(title.as_ref().map(|v| v.as_str()).unwrap_or("Event"))
|
.arg(title.as_ref().map(|v| v.as_str()).unwrap_or("Event"))
|
||||||
|
|
|
@ -499,32 +499,32 @@ impl Component for Pager {
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||||
let shortcuts = self.get_shortcuts(context);
|
let shortcuts = self.get_shortcuts(context);
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(ref key) if *key == shortcuts["scroll_up"] => {
|
UIEvent::Input(ref key) if *key == shortcuts["scroll_up"] => {
|
||||||
if self.cursor_pos > 0 {
|
if self.cursor_pos > 0 {
|
||||||
self.cursor_pos -= 1;
|
self.cursor_pos -= 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::Input(ref key) if *key == shortcuts["scroll_down"] => {
|
UIEvent::Input(ref key) if *key == shortcuts["scroll_down"] => {
|
||||||
if self.height > 0 && self.cursor_pos + 1 < self.height {
|
if self.height > 0 && self.cursor_pos + 1 < self.height {
|
||||||
self.cursor_pos += 1;
|
self.cursor_pos += 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::Input(ref key) if *key == shortcuts["page_up"] => {
|
UIEvent::Input(ref key) if *key == shortcuts["page_up"] => {
|
||||||
self.movement = Some(PageMovement::PageUp);
|
self.movement = Some(PageMovement::PageUp);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(ref key) if *key == shortcuts["page_down"] => {
|
UIEvent::Input(ref key) if *key == shortcuts["page_down"] => {
|
||||||
self.movement = Some(PageMovement::PageDown);
|
self.movement = Some(PageMovement::PageDown);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.max_cursor_pos = None;
|
self.max_cursor_pos = None;
|
||||||
return false;
|
return false;
|
||||||
|
@ -690,8 +690,8 @@ impl Component for StatusBar {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
match &event.event_type {
|
match &event {
|
||||||
UIEventType::RefreshMailbox((ref idx_a, ref idx_f)) => {
|
UIEvent::RefreshMailbox((ref idx_a, ref idx_f)) => {
|
||||||
match context.accounts[*idx_a].status(*idx_f) {
|
match context.accounts[*idx_a].status(*idx_f) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -708,7 +708,7 @@ impl Component for StatusBar {
|
||||||
);
|
);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(m) => {
|
UIEvent::ChangeMode(m) => {
|
||||||
let offset = self.status.find('|').unwrap_or_else(|| self.status.len());
|
let offset = self.status.find('|').unwrap_or_else(|| self.status.len());
|
||||||
self.status.replace_range(..offset, &format!("{} ", m));
|
self.status.replace_range(..offset, &format!("{} ", m));
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
@ -717,10 +717,9 @@ impl Component for StatusBar {
|
||||||
UIMode::Normal => {
|
UIMode::Normal => {
|
||||||
self.height = 1;
|
self.height = 1;
|
||||||
if !self.ex_buffer.is_empty() {
|
if !self.ex_buffer.is_empty() {
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::Command(self.ex_buffer.clone()),
|
.push_back(UIEvent::Command(self.ex_buffer.clone()));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
self.ex_buffer.clear()
|
self.ex_buffer.clear()
|
||||||
}
|
}
|
||||||
|
@ -730,33 +729,33 @@ impl Component for StatusBar {
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
UIEventType::ExInput(Key::Char(c)) => {
|
UIEvent::ExInput(Key::Char(c)) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.ex_buffer.push(*c);
|
self.ex_buffer.push(*c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::ExInput(Key::Ctrl('u')) => {
|
UIEvent::ExInput(Key::Ctrl('u')) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.ex_buffer.clear();
|
self.ex_buffer.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::ExInput(Key::Backspace) | UIEventType::ExInput(Key::Ctrl('h')) => {
|
UIEvent::ExInput(Key::Backspace) | UIEvent::ExInput(Key::Ctrl('h')) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.ex_buffer.pop();
|
self.ex_buffer.pop();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Resize => {
|
UIEvent::Resize => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::StatusEvent(StatusEvent::DisplayMessage(s)) => {
|
UIEvent::StatusEvent(StatusEvent::DisplayMessage(s)) => {
|
||||||
self.notifications.push_back(s.clone());
|
self.notifications.push_back(s.clone());
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::StatusEvent(StatusEvent::BufClear) => {
|
UIEvent::StatusEvent(StatusEvent::BufClear) => {
|
||||||
self.display_buffer.clear();
|
self.display_buffer.clear();
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
UIEventType::StatusEvent(StatusEvent::BufSet(s)) => {
|
UIEvent::StatusEvent(StatusEvent::BufSet(s)) => {
|
||||||
self.display_buffer = s.clone();
|
self.display_buffer = s.clone();
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -1016,42 +1015,42 @@ impl Component for Tabbed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Char('T')) => {
|
UIEvent::Input(Key::Char('T')) => {
|
||||||
self.cursor_pos = (self.cursor_pos + 1) % self.children.len();
|
self.cursor_pos = (self.cursor_pos + 1) % self.children.len();
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('?')) => {
|
UIEvent::Input(Key::Char('?')) => {
|
||||||
self.show_shortcuts = !self.show_shortcuts;
|
self.show_shortcuts = !self.show_shortcuts;
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(Tab(NewDraft(account_idx))) => {
|
UIEvent::Action(Tab(NewDraft(account_idx))) => {
|
||||||
self.add_component(Box::new(Composer::new(account_idx)));
|
self.add_component(Box::new(Composer::new(account_idx)));
|
||||||
self.cursor_pos = self.children.len() - 1;
|
self.cursor_pos = self.children.len() - 1;
|
||||||
self.children[self.cursor_pos].set_dirty();
|
self.children[self.cursor_pos].set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(Tab(Reply(coordinates, msg))) => {
|
UIEvent::Action(Tab(Reply(coordinates, msg))) => {
|
||||||
self.add_component(Box::new(Composer::with_context(coordinates, msg, context)));
|
self.add_component(Box::new(Composer::with_context(coordinates, msg, context)));
|
||||||
self.cursor_pos = self.children.len() - 1;
|
self.cursor_pos = self.children.len() - 1;
|
||||||
self.children[self.cursor_pos].set_dirty();
|
self.children[self.cursor_pos].set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(Tab(Edit(coordinates, msg))) => {
|
UIEvent::Action(Tab(Edit(coordinates, msg))) => {
|
||||||
self.add_component(Box::new(Composer::edit(coordinates, msg, context)));
|
self.add_component(Box::new(Composer::edit(coordinates, msg, context)));
|
||||||
self.cursor_pos = self.children.len() - 1;
|
self.cursor_pos = self.children.len() - 1;
|
||||||
self.children[self.cursor_pos].set_dirty();
|
self.children[self.cursor_pos].set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(Tab(TabOpen(ref mut e))) if e.is_some() => {
|
UIEvent::Action(Tab(TabOpen(ref mut e))) if e.is_some() => {
|
||||||
self.add_component(e.take().unwrap());
|
self.add_component(e.take().unwrap());
|
||||||
self.cursor_pos = self.children.len() - 1;
|
self.cursor_pos = self.children.len() - 1;
|
||||||
self.children[self.cursor_pos].set_dirty();
|
self.children[self.cursor_pos].set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(Tab(Close)) => {
|
UIEvent::Action(Tab(Close)) => {
|
||||||
if self.pinned > self.cursor_pos {
|
if self.pinned > self.cursor_pos {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1060,11 +1059,11 @@ impl Component for Tabbed {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Action(Tab(Kill(ref id))) => {
|
UIEvent::Action(Tab(Kill(id))) => {
|
||||||
if self.pinned > self.cursor_pos {
|
if self.pinned > self.cursor_pos {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if let Some(c_idx) = self.children.iter().position(|x| x.id() == *id) {
|
if let Some(c_idx) = self.children.iter().position(|x| x.id() == id) {
|
||||||
self.children.remove(c_idx);
|
self.children.remove(c_idx);
|
||||||
self.cursor_pos = self.cursor_pos.saturating_sub(1);
|
self.cursor_pos = self.cursor_pos.saturating_sub(1);
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
|
@ -1126,8 +1125,8 @@ impl Component for Selector {
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||||
let (width, height) = self.content.size();
|
let (width, height) = self.content.size();
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Char('\t')) => {
|
UIEvent::Input(Key::Char('\t')) => {
|
||||||
self.entries[self.cursor].1 = !self.entries[self.cursor].1;
|
self.entries[self.cursor].1 = !self.entries[self.cursor].1;
|
||||||
if self.entries[self.cursor].1 {
|
if self.entries[self.cursor].1 {
|
||||||
write_string_to_grid(
|
write_string_to_grid(
|
||||||
|
@ -1151,12 +1150,12 @@ impl Component for Selector {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Up) if self.cursor > 0 => {
|
UIEvent::Input(Key::Up) if self.cursor > 0 => {
|
||||||
self.cursor -= 1;
|
self.cursor -= 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) if self.cursor < height.saturating_sub(1) => {
|
UIEvent::Input(Key::Down) if self.cursor < height.saturating_sub(1) => {
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -107,7 +107,7 @@ impl Component for Field {
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||||
if let Text(ref mut s, Some((_, auto_complete))) = self {
|
if let Text(ref mut s, Some((_, auto_complete))) = self {
|
||||||
if let UIEventType::InsertInput(Key::Char('\t')) = event.event_type {
|
if let UIEvent::InsertInput(Key::Char('\t')) = event {
|
||||||
if let Some(suggestion) = auto_complete.get_suggestion() {
|
if let Some(suggestion) = auto_complete.get_suggestion() {
|
||||||
*s = UText::new(suggestion);
|
*s = UText::new(suggestion);
|
||||||
let len = s.as_str().len().saturating_sub(1);
|
let len = s.as_str().len().saturating_sub(1);
|
||||||
|
@ -117,22 +117,22 @@ impl Component for Field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::InsertInput(Key::Up) => {
|
UIEvent::InsertInput(Key::Up) => {
|
||||||
if let Text(_, Some((_, auto_complete))) = self {
|
if let Text(_, Some((_, auto_complete))) = self {
|
||||||
auto_complete.dec_cursor();
|
auto_complete.dec_cursor();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Down) => {
|
UIEvent::InsertInput(Key::Down) => {
|
||||||
if let Text(_, Some((_, auto_complete))) = self {
|
if let Text(_, Some((_, auto_complete))) = self {
|
||||||
auto_complete.inc_cursor();
|
auto_complete.inc_cursor();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Right) => match self {
|
UIEvent::InsertInput(Key::Right) => match self {
|
||||||
Text(ref mut s, _) => {
|
Text(ref mut s, _) => {
|
||||||
s.cursor_inc();
|
s.cursor_inc();
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ impl Component for Field {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UIEventType::InsertInput(Key::Left) => match self {
|
UIEvent::InsertInput(Key::Left) => match self {
|
||||||
Text(ref mut s, _) => {
|
Text(ref mut s, _) => {
|
||||||
s.cursor_dec();
|
s.cursor_dec();
|
||||||
}
|
}
|
||||||
|
@ -156,19 +156,19 @@ impl Component for Field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UIEventType::InsertInput(Key::Char(k)) => {
|
UIEvent::InsertInput(Key::Char(k)) => {
|
||||||
if let Text(ref mut s, _) = self {
|
if let Text(ref mut s, _) = self {
|
||||||
s.insert_char(k);
|
s.insert_char(k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Paste(ref p)) => {
|
UIEvent::InsertInput(Key::Paste(ref p)) => {
|
||||||
if let Text(ref mut s, _) = self {
|
if let Text(ref mut s, _) = self {
|
||||||
for c in p.chars() {
|
for c in p.chars() {
|
||||||
s.insert_char(c);
|
s.insert_char(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Backspace) => {
|
UIEvent::InsertInput(Key::Backspace) => {
|
||||||
if let Text(ref mut s, auto_complete) = self {
|
if let Text(ref mut s, auto_complete) = self {
|
||||||
s.backspace();
|
s.backspace();
|
||||||
if let Some(ac) = auto_complete.as_mut() {
|
if let Some(ac) = auto_complete.as_mut() {
|
||||||
|
@ -373,64 +373,62 @@ impl Component for FormWidget {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Up) if self.focus == FormFocus::Buttons => {
|
UIEvent::Input(Key::Up) if self.focus == FormFocus::Buttons => {
|
||||||
self.focus = FormFocus::Fields;
|
self.focus = FormFocus::Fields;
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Up) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(Key::Up) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
field.process_event(event, context);
|
field.process_event(event, context);
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Up) => {
|
UIEvent::Input(Key::Up) => {
|
||||||
self.cursor = self.cursor.saturating_sub(1);
|
self.cursor = self.cursor.saturating_sub(1);
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Down) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(Key::Down) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
field.process_event(event, context);
|
field.process_event(event, context);
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) if self.cursor < self.layout.len().saturating_sub(1) => {
|
UIEvent::Input(Key::Down) if self.cursor < self.layout.len().saturating_sub(1) => {
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Down) if self.focus == FormFocus::Fields => {
|
UIEvent::Input(Key::Down) if self.focus == FormFocus::Fields => {
|
||||||
self.focus = FormFocus::Buttons;
|
self.focus = FormFocus::Buttons;
|
||||||
if self.hide_buttons {
|
if self.hide_buttons {
|
||||||
self.set_dirty();
|
self.set_dirty();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Char('\t')) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(Key::Char('\t')) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
field.process_event(event, context);
|
field.process_event(event, context);
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Char('\n')) if self.focus == FormFocus::Fields => {
|
UIEvent::Input(Key::Char('\n')) if self.focus == FormFocus::Fields => {
|
||||||
self.focus = FormFocus::TextInput;
|
self.focus = FormFocus::TextInput;
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::ChangeMode(UIMode::Insert),
|
.push_back(UIEvent::ChangeMode(UIMode::Insert));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Right) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(Key::Right) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
field.process_event(event, context);
|
field.process_event(event, context);
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Left) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(Key::Left) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
if !field.process_event(event, context) {
|
if !field.process_event(event, context) {
|
||||||
self.focus = FormFocus::Fields;
|
self.focus = FormFocus::Fields;
|
||||||
context.replies.push_back(UIEvent {
|
context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::ChangeMode(UIMode::Normal),
|
.push_back(UIEvent::ChangeMode(UIMode::Normal));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(UIMode::Normal) if self.focus == FormFocus::TextInput => {
|
UIEvent::ChangeMode(UIMode::Normal) if self.focus == FormFocus::TextInput => {
|
||||||
self.focus = FormFocus::Fields;
|
self.focus = FormFocus::Fields;
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(Key::Backspace) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(Key::Backspace) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
field.process_event(event, context);
|
field.process_event(event, context);
|
||||||
}
|
}
|
||||||
UIEventType::InsertInput(_) if self.focus == FormFocus::TextInput => {
|
UIEvent::InsertInput(_) if self.focus == FormFocus::TextInput => {
|
||||||
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
let field = self.fields.get_mut(&self.layout[self.cursor]).unwrap();
|
||||||
field.process_event(event, context);
|
field.process_event(event, context);
|
||||||
}
|
}
|
||||||
|
@ -531,8 +529,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||||
match event.event_type {
|
match *event {
|
||||||
UIEventType::Input(Key::Char('\n')) => {
|
UIEvent::Input(Key::Char('\n')) => {
|
||||||
self.result = Some(
|
self.result = Some(
|
||||||
self.buttons
|
self.buttons
|
||||||
.remove(&self.layout[self.cursor])
|
.remove(&self.layout[self.cursor])
|
||||||
|
@ -540,11 +538,11 @@ where
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Left) => {
|
UIEvent::Input(Key::Left) => {
|
||||||
self.cursor = self.cursor.saturating_sub(1);
|
self.cursor = self.cursor.saturating_sub(1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEventType::Input(Key::Right) if self.cursor < self.layout.len().saturating_sub(1) => {
|
UIEvent::Input(Key::Right) if self.cursor < self.layout.len().saturating_sub(1) => {
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::UIEventType::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification};
|
use types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification};
|
||||||
|
|
||||||
pub type Worker = Option<Async<Result<Mailbox>>>;
|
pub type Worker = Option<Async<Result<Mailbox>>>;
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ impl Account {
|
||||||
notify_fn.notify(hash);
|
notify_fn.notify(hash);
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
pub fn reload(&mut self, event: RefreshEvent, idx: usize) -> Option<UIEventType> {
|
pub fn reload(&mut self, event: RefreshEvent, idx: usize) -> Option<UIEvent> {
|
||||||
let kind = event.kind();
|
let kind = event.kind();
|
||||||
{
|
{
|
||||||
//let mailbox: &mut Mailbox = self.folders[idx].as_mut().unwrap().as_mut().unwrap();
|
//let mailbox: &mut Mailbox = self.folders[idx].as_mut().unwrap().as_mut().unwrap();
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl InputHandler {
|
||||||
tx.send(ThreadEvent::Input(k));
|
tx.send(ThreadEvent::Input(k));
|
||||||
},
|
},
|
||||||
|| {
|
|| {
|
||||||
tx.send(ThreadEvent::UIEvent(UIEventType::ChangeMode(UIMode::Fork)));
|
tx.send(ThreadEvent::UIEvent(UIEvent::ChangeMode(UIMode::Fork)));
|
||||||
},
|
},
|
||||||
&rx,
|
&rx,
|
||||||
)
|
)
|
||||||
|
@ -104,10 +104,8 @@ impl Context {
|
||||||
pub fn account_status(&mut self, idx_a: usize, idx_m: usize) -> result::Result<(), usize> {
|
pub fn account_status(&mut self, idx_a: usize, idx_m: usize) -> result::Result<(), usize> {
|
||||||
match self.accounts[idx_a].status(idx_m) {
|
match self.accounts[idx_a].status(idx_m) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
self.replies.push_back(UIEvent {
|
self.replies
|
||||||
id: 0,
|
.push_back(UIEvent::MailboxUpdate((idx_a, idx_m)));
|
||||||
event_type: UIEventType::MailboxUpdate((idx_a, idx_m)),
|
|
||||||
});
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(n) => Err(n),
|
Err(n) => Err(n),
|
||||||
|
@ -186,7 +184,7 @@ impl State {
|
||||||
a_s.clone(),
|
a_s.clone(),
|
||||||
&backends,
|
&backends,
|
||||||
NotifyFn::new(Box::new(move |f: FolderHash| {
|
NotifyFn::new(Box::new(move |f: FolderHash| {
|
||||||
sender.send(ThreadEvent::UIEvent(UIEventType::StartupCheck(f)))
|
sender.send(ThreadEvent::UIEvent(UIEvent::StartupCheck(f)))
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -279,21 +277,15 @@ impl State {
|
||||||
if let Some(notification) = self.context.accounts[idxa].reload(event, idxm) {
|
if let Some(notification) = self.context.accounts[idxa].reload(event, idxm) {
|
||||||
self.context
|
self.context
|
||||||
.sender
|
.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEventType::StartupCheck(hash)));
|
.send(ThreadEvent::UIEvent(UIEvent::StartupCheck(hash)));
|
||||||
self.context
|
self.context
|
||||||
.sender
|
.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEventType::MailboxUpdate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((idxa, idxm))));
|
||||||
idxa, idxm,
|
self.context.replies.push_back(notification);
|
||||||
))));
|
|
||||||
self.context.replies.push_back(UIEvent {
|
|
||||||
id: 0,
|
|
||||||
event_type: notification,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
self.context.replies.push_back(UIEvent {
|
self.context
|
||||||
id: 0,
|
.replies
|
||||||
event_type: UIEventType::MailboxUpdate((idxa, idxm)),
|
.push_back(UIEvent::MailboxUpdate((idxa, idxm)));
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"BUG: mailbox with hash {} not found in mailbox_hashes.",
|
"BUG: mailbox with hash {} not found in mailbox_hashes.",
|
||||||
|
@ -365,10 +357,7 @@ impl State {
|
||||||
self.rows = termrows.unwrap_or(120) as usize;
|
self.rows = termrows.unwrap_or(120) as usize;
|
||||||
self.grid.resize(self.cols, self.rows, Cell::with_char(' '));
|
self.grid.resize(self.cols, self.rows, Cell::with_char(' '));
|
||||||
|
|
||||||
self.rcv_event(UIEvent {
|
self.rcv_event(UIEvent::Resize);
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::Resize,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Invalidate dirty areas.
|
// Invalidate dirty areas.
|
||||||
self.context.dirty_areas.clear();
|
self.context.dirty_areas.clear();
|
||||||
|
@ -463,22 +452,19 @@ impl State {
|
||||||
let result = parse_command(&cmd.as_bytes()).to_full_result();
|
let result = parse_command(&cmd.as_bytes()).to_full_result();
|
||||||
|
|
||||||
if let Ok(v) = result {
|
if let Ok(v) = result {
|
||||||
self.rcv_event(UIEvent {
|
self.rcv_event(UIEvent::Action(v));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::Action(v),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The application's main loop sends `UIEvents` to state via this method.
|
/// The application's main loop sends `UIEvents` to state via this method.
|
||||||
pub fn rcv_event(&mut self, mut event: UIEvent) {
|
pub fn rcv_event(&mut self, mut event: UIEvent) {
|
||||||
match event.event_type {
|
match event {
|
||||||
// Command type is handled only by State.
|
// Command type is handled only by State.
|
||||||
UIEventType::Command(cmd) => {
|
UIEvent::Command(cmd) => {
|
||||||
self.parse_command(&cmd);
|
self.parse_command(&cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UIEventType::Fork(child) => {
|
UIEvent::Fork(child) => {
|
||||||
self.mode = UIMode::Fork;
|
self.mode = UIMode::Fork;
|
||||||
self.child = Some(child);
|
self.child = Some(child);
|
||||||
if let Some(ForkType::Finished) = self.child {
|
if let Some(ForkType::Finished) = self.child {
|
||||||
|
@ -492,10 +478,10 @@ impl State {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UIEventType::ChangeMode(m) => {
|
UIEvent::ChangeMode(m) => {
|
||||||
self.context
|
self.context
|
||||||
.sender
|
.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEventType::ChangeMode(m)));
|
.send(ThreadEvent::UIEvent(UIEvent::ChangeMode(m)));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -523,10 +509,7 @@ impl State {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if flag {
|
if flag {
|
||||||
self.rcv_event(UIEvent {
|
self.rcv_event(UIEvent::RefreshMailbox((account_idx, folder_idx)));
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::RefreshMailbox((account_idx, folder_idx)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub enum ThreadEvent {
|
||||||
Input(Key),
|
Input(Key),
|
||||||
/// A watched folder has been refreshed.
|
/// A watched folder has been refreshed.
|
||||||
RefreshMailbox(Box<RefreshEvent>),
|
RefreshMailbox(Box<RefreshEvent>),
|
||||||
UIEvent(UIEventType),
|
UIEvent(UIEvent),
|
||||||
//Decode { _ }, // For gpg2 signature check
|
//Decode { _ }, // For gpg2 signature check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ pub enum ForkType {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UIEventType {
|
pub enum UIEvent {
|
||||||
Input(Key),
|
Input(Key),
|
||||||
ExInput(Key),
|
ExInput(Key),
|
||||||
InsertInput(Key),
|
InsertInput(Key),
|
||||||
|
@ -94,20 +94,10 @@ pub enum UIEventType {
|
||||||
|
|
||||||
impl From<RefreshEvent> for UIEvent {
|
impl From<RefreshEvent> for UIEvent {
|
||||||
fn from(event: RefreshEvent) -> Self {
|
fn from(event: RefreshEvent) -> Self {
|
||||||
UIEvent {
|
UIEvent::RefreshEvent(Box::new(event))
|
||||||
id: 0,
|
|
||||||
event_type: UIEventType::RefreshEvent(Box::new(event)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An event passed from `State` to its Entities.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct UIEvent {
|
|
||||||
pub id: u64,
|
|
||||||
pub event_type: UIEventType,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
pub enum UIMode {
|
pub enum UIMode {
|
||||||
Normal,
|
Normal,
|
||||||
|
|
Loading…
Reference in New Issue