summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2022-09-11 15:00:30 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2022-09-11 15:00:30 +0300
commit388d4e35d65f8f770526c4c5f44767c55eda23f8 (patch)
tree49dcb5dd6adab173b44d65fb0b0f08edabd0ed78
parent9cbbf71e0f8f9115e9e043982f20045cfc550eb7 (diff)
downloadmeli-388d4e35d65f8f770526c4c5f44767c55eda23f8.zip
listing/offline.rs: add in-progress messages while connecting in IMAP
-rw-r--r--melib/src/backends.rs14
-rw-r--r--melib/src/backends/imap/connection.rs27
-rw-r--r--melib/src/error.rs2
-rw-r--r--src/components/mail/listing.rs35
-rw-r--r--src/components/mail/listing/offline.rs57
-rw-r--r--src/conf/accounts.rs7
-rw-r--r--src/conf/themes.rs17
-rw-r--r--src/state.rs14
-rw-r--r--src/terminal/color.rs264
-rw-r--r--src/types.rs3
10 files changed, 392 insertions, 48 deletions
diff --git a/melib/src/backends.rs b/melib/src/backends.rs
index 4410cd7c..855b43a4 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<Future<Output = Result<()>> + Send + 'static>)
}
diff --git a/melib/src/backends/imap/connection.rs b/melib/src/backends/imap/connection.rs
index a929b558..7dfb00dd 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<Vec<&[u8]>, _> = 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 09c58234..22963375 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 a4143616..0b0f1d89 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 940f5ae9..e4bfd0db 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<ThreadHash, bool>,
+ messages: Vec<Cow<'static, str>>,
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 2429dcbb..977ce8da 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 315c1bce..15bd9e05 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 434c95bf..a67e2fac 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 37cdf67d..2a94a588 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 158d8281..3e545a25 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<Cow<'static, str>>),
ComponentKill(Uuid),
BackendEvent(AccountHash, BackendEvent),
StartupCheck(MailboxHash),