listing/offline.rs: add in-progress messages while connecting in IMAP

137-memory-eating
Manos Pitsidianakis 2022-09-11 15:00:30 +03:00
parent 9cbbf71e0f
commit 388d4e35d6
10 changed files with 392 additions and 48 deletions

View File

@ -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>)
}

View File

@ -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 {

View File

@ -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)?;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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 });

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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),