From 388d4e35d65f8f770526c4c5f44767c55eda23f8 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 11 Sep 2022 15:00:30 +0300 Subject: [PATCH] listing/offline.rs: add in-progress messages while connecting in IMAP --- melib/src/backends.rs | 14 +- melib/src/backends/imap/connection.rs | 27 ++- melib/src/error.rs | 2 +- src/components/mail/listing.rs | 35 ++-- src/components/mail/listing/offline.rs | 57 ++++-- src/conf/accounts.rs | 7 +- src/conf/themes.rs | 17 +- src/state.rs | 14 +- src/terminal/color.rs | 264 +++++++++++++++++++++++++ src/types.rs | 3 +- 10 files changed, 392 insertions(+), 48 deletions(-) diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 4410cd7c5..855b43a45 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -57,18 +57,17 @@ use self::maildir::MaildirType; #[cfg(feature = "mbox_backend")] use self::mbox::MboxType; use super::email::{Envelope, EnvelopeHash, Flag}; +use futures::stream::Stream; use std::any::Any; +use std::borrow::Cow; use std::collections::BTreeSet; +use std::collections::HashMap; use std::fmt; use std::fmt::Debug; -use std::ops::Deref; -use std::sync::{Arc, RwLock}; - -use futures::stream::Stream; use std::future::Future; +use std::ops::Deref; use std::pin::Pin; - -use std::collections::HashMap; +use std::sync::{Arc, RwLock}; #[macro_export] macro_rules! get_path_hash { @@ -265,6 +264,9 @@ pub enum BackendEvent { level: crate::LoggingLevel, }, Refresh(RefreshEvent), + AccountStateChange { + message: Cow<'static, str>, + }, //Job(Box> + Send + 'static>) } diff --git a/melib/src/backends/imap/connection.rs b/melib/src/backends/imap/connection.rs index a929b558b..7dfb00ddd 100644 --- a/melib/src/backends/imap/connection.rs +++ b/melib/src/backends/imap/connection.rs @@ -115,12 +115,19 @@ pub struct ImapConnection { impl ImapStream { pub async fn new_connection( server_conf: &ImapServerConf, + uid_store: &UIDStore, ) -> Result<(Capabilities, ImapStream)> { use std::net::TcpStream; let path = &server_conf.server_hostname; let cmd_id = 1; let stream = if server_conf.use_tls { + (uid_store.event_consumer)( + uid_store.account_hash, + crate::backends::BackendEvent::AccountStateChange { + message: "Establishing TLS connection.".into(), + }, + ); let mut connector = TlsConnector::builder(); if server_conf.danger_accept_invalid_certs { connector.danger_accept_invalid_certs(true); @@ -312,6 +319,12 @@ impl ImapStream { return Ok((Default::default(), ret)); } + (uid_store.event_consumer)( + uid_store.account_hash, + crate::backends::BackendEvent::AccountStateChange { + message: "Negotiating server capabilities.".into(), + }, + ); ret.send_command(b"CAPABILITY").await?; ret.read_response(&mut res).await?; let capabilities: std::result::Result, _> = res @@ -353,6 +366,12 @@ impl ImapStream { .set_err_kind(crate::error::ErrorKind::Authentication)); } + (uid_store.event_consumer)( + uid_store.account_hash, + crate::backends::BackendEvent::AccountStateChange { + message: "Attempting authentication.".into(), + }, + ); match server_conf.protocol { ImapProtocol::IMAP { extension_use: ImapExtensionUse { oauth2, .. }, @@ -601,7 +620,11 @@ impl ImapConnection { if SystemTime::now().duration_since(time).unwrap_or_default() >= IMAP_PROTOCOL_TIMEOUT { - let err = MeliError::new("Connection timed out").set_kind(ErrorKind::Timeout); + let err = MeliError::new(format!( + "Connection timed out after {} seconds", + IMAP_PROTOCOL_TIMEOUT.as_secs() + )) + .set_kind(ErrorKind::Timeout); *status = Err(err.clone()); self.stream = Err(err); } @@ -624,7 +647,7 @@ impl ImapConnection { return Ok(()); } } - let new_stream = ImapStream::new_connection(&self.server_conf).await; + let new_stream = ImapStream::new_connection(&self.server_conf, &self.uid_store).await; if let Err(err) = new_stream.as_ref() { self.uid_store.is_online.lock().unwrap().1 = Err(err.clone()); } else { diff --git a/melib/src/error.rs b/melib/src/error.rs index 09c582341..229633757 100644 --- a/melib/src/error.rs +++ b/melib/src/error.rs @@ -206,7 +206,7 @@ impl MeliError { impl fmt::Display for MeliError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - writeln!(f, "Summary: {}", self.summary)?; + writeln!(f, "{}", self.summary)?; if let Some(details) = self.details.as_ref() { write!(f, "{}", details)?; } diff --git a/src/components/mail/listing.rs b/src/components/mail/listing.rs index a4143616c..0b0f1d89b 100644 --- a/src/components/mail/listing.rs +++ b/src/components/mail/listing.rs @@ -703,13 +703,10 @@ impl Component for Listing { let account_hash = self.accounts[self.cursor_pos.0].hash; if right_component_width == total_cols { - if context.is_online(account_hash).is_err() { - match self.component { - ListingComponent::Offline(_) => {} - _ => { - self.component = Offline(OfflineListing::new((account_hash, 0))); - } - } + if context.is_online(account_hash).is_err() + && !matches!(self.component, ListingComponent::Offline(_)) + { + self.component = Offline(OfflineListing::new((account_hash, 0))); } if let Some(s) = self.status.as_mut() { @@ -725,13 +722,10 @@ impl Component for Listing { (upper_left, (mid.saturating_sub(1), get_y(bottom_right))), context, ); - if context.is_online(account_hash).is_err() { - match self.component { - ListingComponent::Offline(_) => {} - _ => { - self.component = Offline(OfflineListing::new((account_hash, 0))); - } - } + if context.is_online(account_hash).is_err() + && !matches!(self.component, ListingComponent::Offline(_)) + { + self.component = Offline(OfflineListing::new((account_hash, 0))); } if let Some(s) = self.status.as_mut() { s.draw(grid, (set_x(upper_left, mid + 1), bottom_right), context); @@ -776,7 +770,7 @@ impl Component for Listing { ); } } - UIEvent::AccountStatusChange(account_hash) => { + UIEvent::AccountStatusChange(account_hash, msg) => { let account_index: usize = context .accounts .get_index_of(account_hash) @@ -821,11 +815,11 @@ impl Component for Listing { self.menu_content.empty(); context .replies - .push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus( - self.get_status(context), - ))); + .push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(match msg { + Some(msg) => format!("{} {}", self.get_status(context), msg), + None => self.get_status(context), + }))); } - return true; } UIEvent::MailboxDelete((account_hash, mailbox_hash)) | UIEvent::MailboxCreate((account_hash, mailbox_hash)) => { @@ -2348,8 +2342,7 @@ impl Listing { let index_style = mailbox_settings!(context[account_hash][mailbox_hash].listing.index_style); self.component.set_style(*index_style); - } else { - /* Set to dummy */ + } else if !matches!(self.component, ListingComponent::Offline(_)) { self.component = Offline(OfflineListing::new((account_hash, 0))); } self.status = None; diff --git a/src/components/mail/listing/offline.rs b/src/components/mail/listing/offline.rs index 940f5ae96..e4bfd0db9 100644 --- a/src/components/mail/listing/offline.rs +++ b/src/components/mail/listing/offline.rs @@ -21,12 +21,14 @@ use super::*; use crate::components::PageMovement; +use std::borrow::Cow; #[derive(Debug)] pub struct OfflineListing { cursor_pos: (AccountHash, MailboxHash), _row_updates: SmallVec<[ThreadHash; 8]>, _selection: HashMap, + messages: Vec>, dirty: bool, id: ComponentId, } @@ -104,6 +106,7 @@ impl OfflineListing { cursor_pos, _row_updates: SmallVec::new(), _selection: HashMap::default(), + messages: vec![], dirty: true, id: ComponentId::new_v4(), }) @@ -117,26 +120,50 @@ impl Component for OfflineListing { } self.dirty = false; let theme_default = conf::value(context, "theme_default"); + let text_unfocused = conf::value(context, "text.unfocused"); + let error_message = conf::value(context, "error_message"); clear_area(grid, area, theme_default); if let Err(err) = context.is_online(self.cursor_pos.0) { let (x, _) = write_string_to_grid( "offline: ", grid, - conf::value(context, "error_message").fg, - conf::value(context, "error_message").bg, - conf::value(context, "error_message").attrs, + error_message.fg, + error_message.bg, + error_message.attrs, area, None, ); write_string_to_grid( &err.to_string(), grid, - Color::Red, - theme_default.bg, - theme_default.attrs, + error_message.fg, + error_message.bg, + error_message.attrs, (set_x(upper_left!(area), x + 1), bottom_right!(area)), None, ); + if let Some(msg) = self.messages.last() { + write_string_to_grid( + msg, + grid, + text_unfocused.fg, + text_unfocused.bg, + Attr::BOLD, + (pos_inc((0, 1), upper_left!(area)), bottom_right!(area)), + None, + ); + } + for (i, msg) in self.messages.iter().rev().skip(1).enumerate() { + write_string_to_grid( + msg, + grid, + text_unfocused.fg, + text_unfocused.bg, + text_unfocused.attrs, + (pos_inc((0, 2 + i), upper_left!(area)), bottom_right!(area)), + None, + ); + } } else { let (_, mut y) = write_string_to_grid( "loading...", @@ -156,9 +183,9 @@ impl Component for OfflineListing { write_string_to_grid( &format!("{}: {:?}", job_id, j), grid, - theme_default.fg, - theme_default.bg, - theme_default.attrs, + text_unfocused.fg, + text_unfocused.bg, + text_unfocused.attrs, (set_y(upper_left!(area), y + 1), bottom_right!(area)), None, ); @@ -167,19 +194,26 @@ impl Component for OfflineListing { context .replies - .push_back(UIEvent::AccountStatusChange(self.cursor_pos.0)); + .push_back(UIEvent::AccountStatusChange(self.cursor_pos.0, None)); } context.dirty_areas.push_back(area); } + fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool { match event { - UIEvent::AccountStatusChange(account_hash) if *account_hash == self.cursor_pos.0 => { + UIEvent::AccountStatusChange(account_hash, msg) + if *account_hash == self.cursor_pos.0 => + { + if let Some(msg) = msg.clone() { + self.messages.push(msg); + } self.dirty = true } _ => {} } false } + fn is_dirty(&self) -> bool { self.dirty } @@ -191,6 +225,7 @@ impl Component for OfflineListing { fn id(&self) -> ComponentId { self.id } + fn set_id(&mut self, id: ComponentId) { self.id = id; } diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs index 2429dcbb8..977ce8da1 100644 --- a/src/conf/accounts.rs +++ b/src/conf/accounts.rs @@ -1612,6 +1612,7 @@ impl Account { self.sender .send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange( self.hash, + Some("Loaded mailboxes.".into()), ))) .unwrap(); if let Err(err) = mailboxes.and_then(|mailboxes| self.init(mailboxes)) { @@ -1730,7 +1731,7 @@ impl Account { if let Ok(Some(is_online)) = handle.chan.try_recv() { self.sender .send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange( - self.hash, + self.hash, None, ))) .unwrap(); if is_online.is_ok() { @@ -1785,7 +1786,7 @@ impl Account { self.is_online = Ok(()); self.sender .send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange( - self.hash, + self.hash, None, ))) .unwrap(); } @@ -1805,7 +1806,7 @@ impl Account { self.is_online = Err(err); self.sender .send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange( - self.hash, + self.hash, None, ))) .unwrap(); } diff --git a/src/conf/themes.rs b/src/conf/themes.rs index 315c1bcee..15bd9e050 100644 --- a/src/conf/themes.rs +++ b/src/conf/themes.rs @@ -236,6 +236,10 @@ fn unlink_attrs<'k, 't: 'k>(theme: &'t Theme, mut key: &'k str) -> Attr { const DEFAULT_KEYS: &[&str] = &[ "theme_default", + "text.normal", + "text.unfocused", + "text.error", + "text.highlight", "error_message", "email_header", "highlight", @@ -1295,11 +1299,22 @@ impl Default for Themes { light.insert($key.into(), ThemeAttributeInner::default()); dark.insert($key.into(), ThemeAttributeInner::default()); }; + ($key:literal, $copy_from:literal) => { + light.insert($key.into(), light[$copy_from].clone()); + dark.insert($key.into(), dark[$copy_from].clone()); + }; } add!("theme_default", dark = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Default, bg: Color::Default, attrs: Attr::DEFAULT }); - add!("error_message", dark = { fg: Color::Byte(243), bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Byte(243), bg: Color::Default, attrs: Attr::DEFAULT }); + add!("error_message", dark = { fg: Color::Red, bg: "theme_default", attrs: "theme_default" }, light = { fg: Color::Red, bg: "theme_default", attrs: "theme_default" }); + /* text palettes */ + add!("text.normal", "theme_default"); + add!("text.unfocused", dark = { fg: Color::GREY, bg: "theme_default", attrs: Attr::DIM }, light = { fg: Color::GREY, bg: "theme_default", attrs: Attr::DIM }); + add!("text.error", "error_message"); + add!("text.highlight", dark = { fg: Color::Blue, bg: "theme_default", attrs: Attr::REVERSE }, light = { fg: Color::Blue, bg: "theme_default", attrs: Attr::REVERSE }); + + /* rest */ add!("email_header", dark = { fg: Color::Byte(33), bg: Color::Default, attrs: Attr::DEFAULT }, light = { fg: Color::Byte(33), bg: Color::Default, attrs: Attr::DEFAULT }); add!("highlight", dark = { fg: Color::Byte(240), bg: Color::Byte(237), attrs: Attr::BOLD }, light = { fg: Color::Byte(240), bg: Color::Byte(237), attrs: Attr::BOLD }); diff --git a/src/state.rs b/src/state.rs index 434c95bfe..a67e2faca 100644 --- a/src/state.rs +++ b/src/state.rs @@ -145,10 +145,16 @@ impl Context { } accounts[account_pos].watch(); - replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash())); + replies.push_back(UIEvent::AccountStatusChange( + accounts[account_pos].hash(), + None, + )); } if ret.is_ok() != was_online { - replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash())); + replies.push_back(UIEvent::AccountStatusChange( + accounts[account_pos].hash(), + None, + )); } ret } @@ -1015,6 +1021,10 @@ impl State { ))); return; } + UIEvent::BackendEvent(account_hash, BackendEvent::AccountStateChange { message }) => { + self.rcv_event(UIEvent::AccountStatusChange(account_hash, Some(message))); + return; + } UIEvent::BackendEvent(_, BackendEvent::Refresh(refresh_event)) => { self.refresh_event(refresh_event); return; diff --git a/src/terminal/color.rs b/src/terminal/color.rs index 37cdf67d1..2a94a588c 100644 --- a/src/terminal/color.rs +++ b/src/terminal/color.rs @@ -754,3 +754,267 @@ impl Serialize for Color { } } } + +pub use aliases::*; +pub mod aliases { + use super::Color; + + impl Color { + pub const BLACK: Color = Color::Black; + pub const MAROON: Color = Color::Byte(1); + pub const GREEN: Color = Color::Green; + pub const OLIVE: Color = Color::Byte(3); + pub const NAVY: Color = Color::Byte(4); + pub const PURPLE: Color = Color::Magenta; + pub const TEAL: Color = Color::Cyan; + pub const SILVER: Color = Color::Byte(7); + pub const GREY: Color = Color::Byte(8); + pub const RED: Color = Color::Byte(9); + pub const LIME: Color = Color::Byte(10); + pub const YELLOW: Color = Color::Byte(11); + pub const BLUE: Color = Color::Byte(12); + pub const FUCHSIA: Color = Color::Byte(13); + pub const AQUA: Color = Color::Byte(14); + pub const WHITE: Color = Color::Byte(15); + pub const GREY0: Color = Color::Byte(16); + pub const NAVYBLUE: Color = Color::Byte(17); + pub const DARKBLUE: Color = Color::Byte(18); + pub const BLUE3: Color = Color::Byte(19); + pub const BLUE3_: Color = Color::Byte(20); + pub const BLUE1: Color = Color::Byte(21); + pub const DARKGREEN: Color = Color::Byte(22); + pub const DEEPSKYBLUE4: Color = Color::Byte(23); + pub const DEEPSKYBLUE4_: Color = Color::Byte(24); + pub const DEEPSKYBLUE4__: Color = Color::Byte(25); + pub const DODGERBLUE3: Color = Color::Byte(26); + pub const DODGERBLUE2: Color = Color::Byte(27); + pub const GREEN4: Color = Color::Byte(28); + pub const SPRINGGREEN4: Color = Color::Byte(29); + pub const TURQUOISE4: Color = Color::Byte(30); + pub const DEEPSKYBLUE3: Color = Color::Byte(31); + pub const DEEPSKYBLUE3_: Color = Color::Byte(32); + pub const DODGERBLUE1: Color = Color::Byte(33); + pub const GREEN3: Color = Color::Byte(34); + pub const SPRINGGREEN3: Color = Color::Byte(35); + pub const DARKCYAN: Color = Color::Byte(36); + pub const LIGHTSEAGREEN: Color = Color::Byte(37); + pub const DEEPSKYBLUE2: Color = Color::Byte(38); + pub const DEEPSKYBLUE1: Color = Color::Byte(39); + pub const GREEN3_: Color = Color::Byte(40); + pub const SPRINGGREEN3_: Color = Color::Byte(41); + pub const SPRINGGREEN2: Color = Color::Byte(42); + pub const CYAN3: Color = Color::Byte(43); + pub const DARKTURQUOISE: Color = Color::Byte(44); + pub const TURQUOISE2: Color = Color::Byte(45); + pub const GREEN1: Color = Color::Byte(46); + pub const SPRINGGREEN2_: Color = Color::Byte(47); + pub const SPRINGGREEN1: Color = Color::Byte(48); + pub const MEDIUMSPRINGGREEN: Color = Color::Byte(49); + pub const CYAN2: Color = Color::Byte(50); + pub const CYAN1: Color = Color::Byte(51); + pub const DARKRED: Color = Color::Byte(52); + pub const DEEPPINK4: Color = Color::Byte(53); + pub const PURPLE4: Color = Color::Byte(54); + pub const PURPLE4_: Color = Color::Byte(55); + pub const PURPLE3: Color = Color::Byte(56); + pub const BLUEVIOLET: Color = Color::Byte(57); + pub const ORANGE4: Color = Color::Byte(58); + pub const GREY37: Color = Color::Byte(59); + pub const MEDIUMPURPLE4: Color = Color::Byte(60); + pub const SLATEBLUE3: Color = Color::Byte(61); + pub const SLATEBLUE3_: Color = Color::Byte(62); + pub const ROYALBLUE1: Color = Color::Byte(63); + pub const CHARTREUSE4: Color = Color::Byte(64); + pub const DARKSEAGREEN4: Color = Color::Byte(65); + pub const PALETURQUOISE4: Color = Color::Byte(66); + pub const STEELBLUE: Color = Color::Byte(67); + pub const STEELBLUE3: Color = Color::Byte(68); + pub const CORNFLOWERBLUE: Color = Color::Byte(69); + pub const CHARTREUSE3: Color = Color::Byte(70); + pub const DARKSEAGREEN4_: Color = Color::Byte(71); + pub const CADETBLUE: Color = Color::Byte(72); + pub const CADETBLUE_: Color = Color::Byte(73); + pub const SKYBLUE3: Color = Color::Byte(74); + pub const STEELBLUE1: Color = Color::Byte(75); + pub const CHARTREUSE3_: Color = Color::Byte(76); + pub const PALEGREEN3: Color = Color::Byte(77); + pub const SEAGREEN3: Color = Color::Byte(78); + pub const AQUAMARINE3: Color = Color::Byte(79); + pub const MEDIUMTURQUOISE: Color = Color::Byte(80); + pub const STEELBLUE1_: Color = Color::Byte(81); + pub const CHARTREUSE2: Color = Color::Byte(82); + pub const SEAGREEN2: Color = Color::Byte(83); + pub const SEAGREEN1: Color = Color::Byte(84); + pub const SEAGREEN1_: Color = Color::Byte(85); + pub const AQUAMARINE1: Color = Color::Byte(86); + pub const DARKSLATEGRAY2: Color = Color::Byte(87); + pub const DARKRED_: Color = Color::Byte(88); + pub const DEEPPINK4_: Color = Color::Byte(89); + pub const DARKMAGENTA: Color = Color::Byte(90); + pub const DARKMAGENTA_: Color = Color::Byte(91); + pub const DARKVIOLET: Color = Color::Byte(92); + pub const PURPLE_: Color = Color::Byte(93); + pub const ORANGE4_: Color = Color::Byte(94); + pub const LIGHTPINK4: Color = Color::Byte(95); + pub const PLUM4: Color = Color::Byte(96); + pub const MEDIUMPURPLE3: Color = Color::Byte(97); + pub const MEDIUMPURPLE3_: Color = Color::Byte(98); + pub const SLATEBLUE1: Color = Color::Byte(99); + pub const YELLOW4: Color = Color::Byte(100); + pub const WHEAT4: Color = Color::Byte(101); + pub const GREY53: Color = Color::Byte(102); + pub const LIGHTSLATEGREY: Color = Color::Byte(103); + pub const MEDIUMPURPLE: Color = Color::Byte(104); + pub const LIGHTSLATEBLUE: Color = Color::Byte(105); + pub const YELLOW4_: Color = Color::Byte(106); + pub const DARKOLIVEGREEN3: Color = Color::Byte(107); + pub const DARKSEAGREEN: Color = Color::Byte(108); + pub const LIGHTSKYBLUE3: Color = Color::Byte(109); + pub const LIGHTSKYBLUE3_: Color = Color::Byte(110); + pub const SKYBLUE2: Color = Color::Byte(111); + pub const CHARTREUSE2_: Color = Color::Byte(112); + pub const DARKOLIVEGREEN3_: Color = Color::Byte(113); + pub const PALEGREEN3_: Color = Color::Byte(114); + pub const DARKSEAGREEN3: Color = Color::Byte(115); + pub const DARKSLATEGRAY3: Color = Color::Byte(116); + pub const SKYBLUE1: Color = Color::Byte(117); + pub const CHARTREUSE1: Color = Color::Byte(118); + pub const LIGHTGREEN: Color = Color::Byte(119); + pub const LIGHTGREEN_: Color = Color::Byte(120); + pub const PALEGREEN1: Color = Color::Byte(121); + pub const AQUAMARINE1_: Color = Color::Byte(122); + pub const DARKSLATEGRAY1: Color = Color::Byte(123); + pub const RED3: Color = Color::Byte(124); + pub const DEEPPINK4__: Color = Color::Byte(125); + pub const MEDIUMVIOLETRED: Color = Color::Byte(126); + pub const MAGENTA3: Color = Color::Byte(127); + pub const DARKVIOLET_: Color = Color::Byte(128); + pub const PURPLE__: Color = Color::Byte(129); + pub const DARKORANGE3: Color = Color::Byte(130); + pub const INDIANRED: Color = Color::Byte(131); + pub const HOTPINK3: Color = Color::Byte(132); + pub const MEDIUMORCHID3: Color = Color::Byte(133); + pub const MEDIUMORCHID: Color = Color::Byte(134); + pub const MEDIUMPURPLE2: Color = Color::Byte(135); + pub const DARKGOLDENROD: Color = Color::Byte(136); + pub const LIGHTSALMON3: Color = Color::Byte(137); + pub const ROSYBROWN: Color = Color::Byte(138); + pub const GREY63: Color = Color::Byte(139); + pub const MEDIUMPURPLE2_: Color = Color::Byte(140); + pub const MEDIUMPURPLE1: Color = Color::Byte(141); + pub const GOLD3: Color = Color::Byte(142); + pub const DARKKHAKI: Color = Color::Byte(143); + pub const NAVAJOWHITE3: Color = Color::Byte(144); + pub const GREY69: Color = Color::Byte(145); + pub const LIGHTSTEELBLUE3: Color = Color::Byte(146); + pub const LIGHTSTEELBLUE: Color = Color::Byte(147); + pub const YELLOW3: Color = Color::Byte(148); + pub const DARKOLIVEGREEN3__: Color = Color::Byte(149); + pub const DARKSEAGREEN3_: Color = Color::Byte(150); + pub const DARKSEAGREEN2: Color = Color::Byte(151); + pub const LIGHTCYAN3: Color = Color::Byte(152); + pub const LIGHTSKYBLUE1: Color = Color::Byte(153); + pub const GREENYELLOW: Color = Color::Byte(154); + pub const DARKOLIVEGREEN2: Color = Color::Byte(155); + pub const PALEGREEN1_: Color = Color::Byte(156); + pub const DARKSEAGREEN2_: Color = Color::Byte(157); + pub const DARKSEAGREEN1: Color = Color::Byte(158); + pub const PALETURQUOISE1: Color = Color::Byte(159); + pub const RED3_: Color = Color::Byte(160); + pub const DEEPPINK3: Color = Color::Byte(161); + pub const DEEPPINK3_: Color = Color::Byte(162); + pub const MAGENTA3_: Color = Color::Byte(163); + pub const MAGENTA3__: Color = Color::Byte(164); + pub const MAGENTA2: Color = Color::Byte(165); + pub const DARKORANGE3_: Color = Color::Byte(166); + pub const INDIANRED_: Color = Color::Byte(167); + pub const HOTPINK3_: Color = Color::Byte(168); + pub const HOTPINK2: Color = Color::Byte(169); + pub const ORCHID: Color = Color::Byte(170); + pub const MEDIUMORCHID1: Color = Color::Byte(171); + pub const ORANGE3: Color = Color::Byte(172); + pub const LIGHTSALMON3_: Color = Color::Byte(173); + pub const LIGHTPINK3: Color = Color::Byte(174); + pub const PINK3: Color = Color::Byte(175); + pub const PLUM3: Color = Color::Byte(176); + pub const VIOLET: Color = Color::Byte(177); + pub const GOLD3_: Color = Color::Byte(178); + pub const LIGHTGOLDENROD3: Color = Color::Byte(179); + pub const TAN: Color = Color::Byte(180); + pub const MISTYROSE3: Color = Color::Byte(181); + pub const THISTLE3: Color = Color::Byte(182); + pub const PLUM2: Color = Color::Byte(183); + pub const YELLOW3_: Color = Color::Byte(184); + pub const KHAKI3: Color = Color::Byte(185); + pub const LIGHTGOLDENROD2: Color = Color::Byte(186); + pub const LIGHTYELLOW3: Color = Color::Byte(187); + pub const GREY84: Color = Color::Byte(188); + pub const LIGHTSTEELBLUE1: Color = Color::Byte(189); + pub const YELLOW2: Color = Color::Byte(190); + pub const DARKOLIVEGREEN1: Color = Color::Byte(191); + pub const DARKOLIVEGREEN1_: Color = Color::Byte(192); + pub const DARKSEAGREEN1_: Color = Color::Byte(193); + pub const HONEYDEW2: Color = Color::Byte(194); + pub const LIGHTCYAN1: Color = Color::Byte(195); + pub const RED1: Color = Color::Byte(196); + pub const DEEPPINK2: Color = Color::Byte(197); + pub const DEEPPINK1: Color = Color::Byte(198); + pub const DEEPPINK1_: Color = Color::Byte(199); + pub const MAGENTA2_: Color = Color::Byte(200); + pub const MAGENTA1: Color = Color::Byte(201); + pub const ORANGERED1: Color = Color::Byte(202); + pub const INDIANRED1: Color = Color::Byte(203); + pub const INDIANRED1_: Color = Color::Byte(204); + pub const HOTPINK: Color = Color::Byte(205); + pub const HOTPINK_: Color = Color::Byte(206); + pub const MEDIUMORCHID1_: Color = Color::Byte(207); + pub const DARKORANGE: Color = Color::Byte(208); + pub const SALMON1: Color = Color::Byte(209); + pub const LIGHTCORAL: Color = Color::Byte(210); + pub const PALEVIOLETRED1: Color = Color::Byte(211); + pub const ORCHID2: Color = Color::Byte(212); + pub const ORCHID1: Color = Color::Byte(213); + pub const ORANGE1: Color = Color::Byte(214); + pub const SANDYBROWN: Color = Color::Byte(215); + pub const LIGHTSALMON1: Color = Color::Byte(216); + pub const LIGHTPINK1: Color = Color::Byte(217); + pub const PINK1: Color = Color::Byte(218); + pub const PLUM1: Color = Color::Byte(219); + pub const GOLD1: Color = Color::Byte(220); + pub const LIGHTGOLDENROD2_: Color = Color::Byte(221); + pub const LIGHTGOLDENROD2__: Color = Color::Byte(222); + pub const NAVAJOWHITE1: Color = Color::Byte(223); + pub const MISTYROSE1: Color = Color::Byte(224); + pub const THISTLE1: Color = Color::Byte(225); + pub const YELLOW1: Color = Color::Byte(226); + pub const LIGHTGOLDENROD1: Color = Color::Byte(227); + pub const KHAKI1: Color = Color::Byte(228); + pub const WHEAT1: Color = Color::Byte(229); + pub const CORNSILK1: Color = Color::Byte(230); + pub const GREY100: Color = Color::Byte(231); + pub const GREY3: Color = Color::Byte(232); + pub const GREY7: Color = Color::Byte(233); + pub const GREY11: Color = Color::Byte(234); + pub const GREY15: Color = Color::Byte(235); + pub const GREY19: Color = Color::Byte(236); + pub const GREY23: Color = Color::Byte(237); + pub const GREY27: Color = Color::Byte(238); + pub const GREY30: Color = Color::Byte(239); + pub const GREY35: Color = Color::Byte(240); + pub const GREY39: Color = Color::Byte(241); + pub const GREY42: Color = Color::Byte(242); + pub const GREY46: Color = Color::Byte(243); + pub const GREY50: Color = Color::Byte(244); + pub const GREY54: Color = Color::Byte(245); + pub const GREY58: Color = Color::Byte(246); + pub const GREY62: Color = Color::Byte(247); + pub const GREY66: Color = Color::Byte(248); + pub const GREY70: Color = Color::Byte(249); + pub const GREY74: Color = Color::Byte(250); + pub const GREY78: Color = Color::Byte(251); + pub const GREY82: Color = Color::Byte(252); + pub const GREY85: Color = Color::Byte(253); + pub const GREY89: Color = Color::Byte(254); + pub const GREY93: Color = Color::Byte(255); + } +} diff --git a/src/types.rs b/src/types.rs index 158d82819..3e545a25a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -39,6 +39,7 @@ use super::command::Action; use super::jobs::{JobExecutor, JobId}; use super::terminal::*; use crate::components::{Component, ComponentId, ScrollUpdate}; +use std::borrow::Cow; use std::sync::Arc; use melib::backends::{AccountHash, BackendEvent, MailboxHash}; @@ -134,7 +135,7 @@ pub enum UIEvent { MailboxUpdate((AccountHash, MailboxHash)), // (account_idx, mailbox_idx) MailboxDelete((AccountHash, MailboxHash)), MailboxCreate((AccountHash, MailboxHash)), - AccountStatusChange(AccountHash), + AccountStatusChange(AccountHash, Option>), ComponentKill(Uuid), BackendEvent(AccountHash, BackendEvent), StartupCheck(MailboxHash),