diff --git a/melib/src/addressbook.rs b/melib/src/addressbook.rs index 543f3a4a7..86022008c 100644 --- a/melib/src/addressbook.rs +++ b/melib/src/addressbook.rs @@ -24,7 +24,7 @@ use fnv::FnvHashMap; use std::ops::Deref; -type CardId = Uuid; +pub type CardId = Uuid; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct AddressBook { diff --git a/ui/src/components.rs b/ui/src/components.rs index f6a160d92..6fbe2ddbc 100644 --- a/ui/src/components.rs +++ b/ui/src/components.rs @@ -136,8 +136,8 @@ impl Entity { &self.id } /// Pass events to child component. - pub fn rcv_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { - self.component.process_event(&event, context) + pub fn rcv_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { + self.component.process_event(event, context) } } @@ -146,7 +146,7 @@ impl Entity { /// fields (eg self.dirty = false) and act upon that in their `draw` implementation. pub trait Component: Display + Debug + Send { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context); - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool; + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool; fn is_dirty(&self) -> bool { true } diff --git a/ui/src/components/contacts.rs b/ui/src/components/contacts.rs index db8be6e58..138bf88f0 100644 --- a/ui/src/components/contacts.rs +++ b/ui/src/components/contacts.rs @@ -123,7 +123,7 @@ impl Component for ContactManager { context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if self.form.process_event(event, context) { match self.form.buttons_result() { None => {}, diff --git a/ui/src/components/contacts/contact_list.rs b/ui/src/components/contacts/contact_list.rs index 0c8cbf999..728fd87d7 100644 --- a/ui/src/components/contacts/contact_list.rs +++ b/ui/src/components/contacts/contact_list.rs @@ -1,11 +1,13 @@ use super::*; +use melib::CardId; + const MAX_COLS: usize = 500; #[derive(Debug, PartialEq)] enum ViewMode { List, - View(EntityId), + View(CardId), } #[derive(Debug)] @@ -16,7 +18,7 @@ pub struct ContactList { length: usize, content: CellBuffer, - id_positions: Vec, + id_positions: Vec, mode: ViewMode, dirty: bool, @@ -51,6 +53,13 @@ impl ContactList { } } + pub fn for_account(pos: usize) -> Self { + ContactList { + account_pos: pos, + ..Self::new() + } + } + fn initialize(&mut self, context: &mut Context) { let account = &mut context.accounts[self.account_pos]; let book = &mut account.address_book; @@ -106,13 +115,23 @@ impl Component for ContactList { self.cursor_pos = self.new_cursor_pos; } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if let Some(ref mut v) = self.view { if v.process_event(event, context) { return true; } } match event.event_type { + UIEventType::Input(Key::Char('c')) => { + let mut manager = ContactManager::default(); + manager.account_pos = self.account_pos; + let entity = Entity::from(Box::new(manager)); + + self.mode = ViewMode::View(*entity.id()); + self.view = Some(entity); + + return true; + }, UIEventType::Input(Key::Char('e')) if self.length > 0 => { let account = &mut context.accounts[self.account_pos]; let book = &mut account.address_book; diff --git a/ui/src/components/indexer.rs b/ui/src/components/indexer.rs index eb804bae0..30da0f5e2 100644 --- a/ui/src/components/indexer.rs +++ b/ui/src/components/indexer.rs @@ -91,7 +91,7 @@ impl Component for Indexer { context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool { if !self.entries[self.cursor[0]] .index .process_event(event, _context) diff --git a/ui/src/components/indexer/index.rs b/ui/src/components/indexer/index.rs index 15c5a0349..d636a9a0d 100644 --- a/ui/src/components/indexer/index.rs +++ b/ui/src/components/indexer/index.rs @@ -123,7 +123,7 @@ impl Component for Index { return; } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if self.content.process_event(event, context) { return true; } diff --git a/ui/src/components/mail.rs b/ui/src/components/mail.rs index 144683c22..fcfd7aa5e 100644 --- a/ui/src/components/mail.rs +++ b/ui/src/components/mail.rs @@ -257,7 +257,7 @@ impl Component for AccountMenu { context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool { match event.event_type { UIEventType::RefreshMailbox(c) => { self.cursor = Some(c); diff --git a/ui/src/components/mail/accounts.rs b/ui/src/components/mail/accounts.rs index 13c759448..56c710959 100644 --- a/ui/src/components/mail/accounts.rs +++ b/ui/src/components/mail/accounts.rs @@ -119,7 +119,7 @@ impl Component for AccountsPanel { copy_area(grid, &self.content, area, ((0, 0), (width - 1, height - 1))); context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match event.event_type { UIEventType::Input(Key::Up) => { self.cursor = self.cursor.saturating_sub(1); @@ -133,6 +133,13 @@ impl Component for AccountsPanel { } return true; }, + UIEventType::Input(Key::Char('\n')) => { + context.replies.push_back(UIEvent { + id: 0, + event_type: UIEventType::Action(Tab(TabOpen(Some(Box::new(ContactList::for_account(self.cursor))) + )))}); + return true; + }, _ => {}, } diff --git a/ui/src/components/mail/accounts/contacts.rs b/ui/src/components/mail/accounts/contacts.rs index ccd5d4be2..61b8cbaa6 100644 --- a/ui/src/components/mail/accounts/contacts.rs +++ b/ui/src/components/mail/accounts/contacts.rs @@ -45,7 +45,7 @@ impl Component for ContactsPanel { copy_area(grid, &self.content, area, ((0, 0), (width - 1, height - 1))); context.dirty_areas.push_back(area); } - fn process_event(&mut self, _event: &UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool { false } fn is_dirty(&self) -> bool { diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs index c541a842a..e6fc9d317 100644 --- a/ui/src/components/mail/compose.rs +++ b/ui/src/components/mail/compose.rs @@ -387,7 +387,7 @@ impl Component for Composer { context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &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) { (ViewMode::Pager, _) => { /* Cannot mutably borrow in pattern guard, pah! */ diff --git a/ui/src/components/mail/listing.rs b/ui/src/components/mail/listing.rs index 326d78414..15381b2cc 100644 --- a/ui/src/components/mail/listing.rs +++ b/ui/src/components/mail/listing.rs @@ -61,7 +61,7 @@ impl Component for Listing { Listing::Threaded(l) => l.draw(grid, area, context), } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if match self { Listing::Plain(l) => l.process_event(event, context), Listing::Compact(l) => l.process_event(event, context), diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index 3c5123e91..f1b5f6c74 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -381,7 +381,7 @@ impl Component for CompactListing { } self.dirty = false; } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if let Some(ref mut v) = self.view { if v.process_event(event, context) { return true; diff --git a/ui/src/components/mail/listing/plain.rs b/ui/src/components/mail/listing/plain.rs index 90c100457..6e7f53dbc 100644 --- a/ui/src/components/mail/listing/plain.rs +++ b/ui/src/components/mail/listing/plain.rs @@ -417,7 +417,7 @@ impl Component for PlainListing { self.dirty = false; } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if let Some(ref mut v) = self.view { if v.process_event(event, context) { return true; diff --git a/ui/src/components/mail/listing/thread.rs b/ui/src/components/mail/listing/thread.rs index 25fd52c94..d6e186614 100644 --- a/ui/src/components/mail/listing/thread.rs +++ b/ui/src/components/mail/listing/thread.rs @@ -550,7 +550,7 @@ impl Component for ThreadListing { self.dirty = false; } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if let Some(ref mut v) = self.view { if v.process_event(event, context) { return true; diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs index 335609854..31d334ddc 100644 --- a/ui/src/components/mail/view.rs +++ b/ui/src/components/mail/view.rs @@ -360,7 +360,7 @@ impl Component for MailView { } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match self.mode { ViewMode::Subview => { if let Some(s) = self.subview.as_mut() { @@ -414,7 +414,7 @@ impl Component for MailView { let envelope: &Envelope = &mailbox.collection[&self.coordinates.2]; let mut entries = Vec::new(); entries.push((envelope.from()[0].get_email().into_bytes(), format!("{}", envelope.from()[0]))); - entries.push((String::from("foo@bar.de").into_bytes(), String::from("Johann de Vir "))); + entries.push((envelope.to()[0].get_email().into_bytes(), format!("{}", envelope.to()[0]))); self.mode = ViewMode::ContactSelector(Selector::new(entries, true)); self.dirty = true; //context.accounts.context(self.coordinates.0).address_book.add_card(new_card); diff --git a/ui/src/components/mail/view/envelope.rs b/ui/src/components/mail/view/envelope.rs index caf78dc5f..f08c90187 100644 --- a/ui/src/components/mail/view/envelope.rs +++ b/ui/src/components/mail/view/envelope.rs @@ -315,7 +315,7 @@ impl Component for EnvelopeView { } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if let Some(ref mut sub) = self.subview { if sub.process_event(event, context) { return true; diff --git a/ui/src/components/mail/view/html.rs b/ui/src/components/mail/view/html.rs index d802a2bf7..bed8e2167 100644 --- a/ui/src/components/mail/view/html.rs +++ b/ui/src/components/mail/view/html.rs @@ -66,7 +66,7 @@ impl Component for HtmlView { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { self.pager.draw(grid, area, context); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if self.pager.process_event(event, context) { return true; } diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs index 7027065e3..5b1069388 100644 --- a/ui/src/components/mail/view/thread.rs +++ b/ui/src/components/mail/view/thread.rs @@ -540,7 +540,7 @@ impl Component for ThreadView { self.draw_horz(grid, area, context); } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if self.mailview.process_event(event, context) { return true; } diff --git a/ui/src/components/notifications.rs b/ui/src/components/notifications.rs index 40a3650a7..7fd846ede 100644 --- a/ui/src/components/notifications.rs +++ b/ui/src/components/notifications.rs @@ -39,7 +39,7 @@ impl fmt::Display for XDGNotifications { impl Component for XDGNotifications { fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {} - fn process_event(&mut self, event: &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 { notify_Notification::new() .appname("meli") diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs index 3205b8231..801dfa766 100644 --- a/ui/src/components/utilities.rs +++ b/ui/src/components/utilities.rs @@ -88,7 +88,7 @@ impl Component for HSplit { context, ); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { self.top.rcv_event(event, context) || self.bottom.rcv_event(event, context) } fn is_dirty(&self) -> bool { @@ -175,7 +175,7 @@ impl Component for VSplit { .component .draw(grid, ((mid + 1, get_y(upper_left)), bottom_right), context); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { (self.left.rcv_event(event, context) || self.right.rcv_event(event, context)) } fn is_dirty(&self) -> bool { @@ -380,7 +380,7 @@ impl Component for Pager { } context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match event.event_type { UIEventType::Input(Key::Char('k')) => { if self.cursor_pos > 0 { @@ -547,7 +547,7 @@ impl Component for StatusBar { _ => {} } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if self.container.rcv_event(event, context) { return true; } @@ -655,7 +655,7 @@ impl fmt::Display for TextBox { impl Component for TextBox { fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {} - fn process_event(&mut self, _event: &UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool { false } fn set_dirty(&mut self) {} @@ -708,7 +708,7 @@ impl Component for Progress { fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) { unimplemented!() } - fn process_event(&mut self, _event: &UIEvent, _context: &mut Context) -> bool { + fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool { false } fn set_dirty(&mut self) {} @@ -792,7 +792,7 @@ impl Component for Tabbed { self.children[self.cursor_pos].draw(grid, area, context); } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match event.event_type { UIEventType::Input(Key::Char('T')) => { self.cursor_pos = (self.cursor_pos + 1) % self.children.len(); @@ -811,6 +811,12 @@ impl Component for Tabbed { self.children[self.cursor_pos].set_dirty(); return true; } + UIEventType::Action(Tab(TabOpen(ref mut e))) if e.is_some() => { + self.add_component(e.take().unwrap()); + self.cursor_pos = self.children.len() - 1; + self.children[self.cursor_pos].set_dirty(); + return true; + } UIEventType::Action(Tab(Close)) => { let id = *self.children[self.cursor_pos].id(); self.children[self.cursor_pos].kill(id); @@ -874,7 +880,7 @@ impl Component for Selector { ); context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { let (width, height) = self.content.size(); match event.event_type { UIEventType::Input(Key::Char(' ')) => { diff --git a/ui/src/components/utilities/widgets.rs b/ui/src/components/utilities/widgets.rs index 971ae11d4..78b8e9313 100644 --- a/ui/src/components/utilities/widgets.rs +++ b/ui/src/components/utilities/widgets.rs @@ -120,7 +120,7 @@ impl Component for FormWidget { self.dirty = false; context.dirty_areas.push_back(area); } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { if self.focus == FormFocus::Buttons { if self.buttons.process_event(event, context) { return true; @@ -256,7 +256,7 @@ impl Component for ButtonWidget where T: std::fmt::Debug + Default + Send len += cur_len + 3; } } - fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool { + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match event.event_type { UIEventType::Input(Key::Char('\n')) => { self.result = Some(self.buttons.remove(&self.layout[self.cursor]).unwrap_or_default()); diff --git a/ui/src/execute/actions.rs b/ui/src/execute/actions.rs index cd80b0a3d..a6b08f36e 100644 --- a/ui/src/execute/actions.rs +++ b/ui/src/execute/actions.rs @@ -24,7 +24,7 @@ */ pub use melib::mailbox::{SortField, SortOrder}; -use components::Entity; +use components::Component; extern crate uuid; use uuid::Uuid; @@ -38,7 +38,7 @@ pub enum ListingAction { #[derive(Debug, )] pub enum TabAction { - EntityOpen(Entity), + TabOpen(Option>), NewDraft, Reply((usize, usize, usize), usize), // thread coordinates (account, mailbox, root_set idx) and message idx Close, diff --git a/ui/src/state.rs b/ui/src/state.rs index 73187339b..8a672415a 100644 --- a/ui/src/state.rs +++ b/ui/src/state.rs @@ -453,7 +453,7 @@ impl State { } /// The application's main loop sends `UIEvents` to state via this method. - pub fn rcv_event(&mut self, event: UIEvent) { + pub fn rcv_event(&mut self, mut event: UIEvent) { match event.event_type { // Command type is handled only by State. UIEventType::Command(cmd) => { @@ -483,7 +483,7 @@ impl State { } /* inform each entity */ for i in 0..self.entities.len() { - self.entities[i].rcv_event(&event, &mut self.context); + self.entities[i].rcv_event(&mut event, &mut self.context); } if !self.context.replies.is_empty() {