Preserve Account order from configuration file
Use IndexMap to preserve the order of accounts in the UI from the account definitions.memfd
parent
dede8d2a9e
commit
8a6bf3b217
|
@ -678,6 +678,7 @@ checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -902,6 +903,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"futures",
|
"futures",
|
||||||
|
"indexmap",
|
||||||
"libc",
|
"libc",
|
||||||
"linkify",
|
"linkify",
|
||||||
"melib",
|
"melib",
|
||||||
|
|
|
@ -37,6 +37,7 @@ serde = "1.0.71"
|
||||||
serde_derive = "1.0.71"
|
serde_derive = "1.0.71"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
toml = { version = "0.5.6", features = ["preserve_order", ] }
|
toml = { version = "0.5.6", features = ["preserve_order", ] }
|
||||||
|
indexmap = { version = "^1.5", features = ["serde-1", ] }
|
||||||
linkify = "0.4.0"
|
linkify = "0.4.0"
|
||||||
xdg-utils = "0.3.0"
|
xdg-utils = "0.3.0"
|
||||||
notify = "4.0.1" # >:c
|
notify = "4.0.1" # >:c
|
||||||
|
|
|
@ -473,7 +473,7 @@ fn run_app(opt: Opt) -> Result<()> {
|
||||||
},
|
},
|
||||||
ThreadEvent::JobFinished(id) => {
|
ThreadEvent::JobFinished(id) => {
|
||||||
debug!("Job finished {}", id);
|
debug!("Job finished {}", id);
|
||||||
for account in state.context.accounts.iter_mut() {
|
for account in state.context.accounts.values_mut() {
|
||||||
if account.process_event(&id) {
|
if account.process_event(&id) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::components::Component;
|
use crate::components::Component;
|
||||||
use melib::backends::MailboxHash;
|
use melib::backends::{AccountHash, MailboxHash};
|
||||||
pub use melib::thread::{SortField, SortOrder};
|
pub use melib::thread::{SortField, SortOrder};
|
||||||
use melib::{Draft, EnvelopeHash};
|
use melib::{Draft, EnvelopeHash};
|
||||||
|
|
||||||
|
@ -59,10 +59,10 @@ pub enum ListingAction {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TabAction {
|
pub enum TabAction {
|
||||||
New(Option<Box<dyn Component>>),
|
New(Option<Box<dyn Component>>),
|
||||||
NewDraft(usize, Option<Draft>),
|
NewDraft(AccountHash, Option<Draft>),
|
||||||
Reply((usize, MailboxHash), EnvelopeHash), // thread coordinates (account, mailbox) and envelope
|
Reply((AccountHash, MailboxHash), EnvelopeHash), // thread coordinates (account, mailbox) and envelope
|
||||||
Close,
|
Close,
|
||||||
Edit(usize, EnvelopeHash), // account_position, envelope hash
|
Edit(AccountHash, EnvelopeHash), // account_position, envelope hash
|
||||||
Kill(Uuid),
|
Kill(Uuid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,9 @@
|
||||||
*/
|
*/
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::melib::text_processing::TextProcessing;
|
use crate::melib::text_processing::TextProcessing;
|
||||||
|
use melib::backends::AccountHash;
|
||||||
use melib::CardId;
|
use melib::CardId;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
|
@ -33,6 +34,7 @@ enum ViewMode {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct AccountMenuEntry {
|
struct AccountMenuEntry {
|
||||||
name: String,
|
name: String,
|
||||||
|
hash: AccountHash,
|
||||||
// Index in the config account vector.
|
// Index in the config account vector.
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
@ -74,8 +76,9 @@ impl ContactList {
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, a)| AccountMenuEntry {
|
.map(|(i, (h, a))| AccountMenuEntry {
|
||||||
name: a.name().to_string(),
|
name: a.name().to_string(),
|
||||||
|
hash: *h,
|
||||||
index: i,
|
index: i,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -633,15 +636,15 @@ impl Component for ContactList {
|
||||||
&& self.length > 0 =>
|
&& self.length > 0 =>
|
||||||
{
|
{
|
||||||
let account = &context.accounts[self.account_pos];
|
let account = &context.accounts[self.account_pos];
|
||||||
|
let account_hash = account.hash();
|
||||||
let book = &account.address_book;
|
let book = &account.address_book;
|
||||||
let card = &book[&self.id_positions[self.cursor_pos]];
|
let card = &book[&self.id_positions[self.cursor_pos]];
|
||||||
let mut draft: Draft = Draft::default();
|
let mut draft: Draft = Draft::default();
|
||||||
*draft.headers_mut().get_mut("To").unwrap() =
|
*draft.headers_mut().get_mut("To").unwrap() =
|
||||||
format!("{} <{}>", &card.name(), &card.email());
|
format!("{} <{}>", &card.name(), &card.email());
|
||||||
context.replies.push_back(UIEvent::Action(Tab(NewDraft(
|
context
|
||||||
self.account_pos,
|
.replies
|
||||||
Some(draft),
|
.push_back(UIEvent::Action(Tab(NewDraft(account_hash, Some(draft)))));
|
||||||
))));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,7 @@
|
||||||
/*! Entities that handle Mail specific functions.
|
/*! Entities that handle Mail specific functions.
|
||||||
*/
|
*/
|
||||||
use super::*;
|
use super::*;
|
||||||
use melib::backends::Mailbox;
|
use melib::backends::{AccountHash, Mailbox, MailboxHash};
|
||||||
use melib::backends::MailboxHash;
|
|
||||||
use melib::thread::ThreadNodeHash;
|
use melib::thread::ThreadNodeHash;
|
||||||
|
|
||||||
pub mod listing;
|
pub mod listing;
|
||||||
|
@ -38,8 +37,8 @@ pub mod pgp;
|
||||||
mod status;
|
mod status;
|
||||||
pub use self::status::*;
|
pub use self::status::*;
|
||||||
|
|
||||||
fn get_display_name(context: &Context, idx: usize) -> String {
|
fn get_display_name(context: &Context, account_hash: AccountHash) -> String {
|
||||||
let settings = context.accounts[idx].settings.account();
|
let settings = context.accounts[&account_hash].settings.account();
|
||||||
if let Some(d) = settings.display_name.as_ref() {
|
if let Some(d) = settings.display_name.as_ref() {
|
||||||
format!("{} <{}>", d, settings.identity)
|
format!("{} <{}>", d, settings.identity)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl std::ops::DerefMut for EmbedStatus {
|
||||||
pub struct Composer {
|
pub struct Composer {
|
||||||
reply_context: Option<(MailboxHash, EnvelopeHash)>,
|
reply_context: Option<(MailboxHash, EnvelopeHash)>,
|
||||||
reply_bytes_request: Option<(JobId, JobChannel<Vec<u8>>)>,
|
reply_bytes_request: Option<(JobId, JobChannel<Vec<u8>>)>,
|
||||||
account_cursor: usize,
|
account_hash: AccountHash,
|
||||||
|
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ impl Default for Composer {
|
||||||
Composer {
|
Composer {
|
||||||
reply_context: None,
|
reply_context: None,
|
||||||
reply_bytes_request: None,
|
reply_bytes_request: None,
|
||||||
account_cursor: 0,
|
account_hash: 0,
|
||||||
|
|
||||||
cursor: Cursor::Headers,
|
cursor: Cursor::Headers,
|
||||||
|
|
||||||
|
@ -146,14 +146,14 @@ impl fmt::Display for Composer {
|
||||||
|
|
||||||
impl Composer {
|
impl Composer {
|
||||||
const DESCRIPTION: &'static str = "composing";
|
const DESCRIPTION: &'static str = "composing";
|
||||||
pub fn new(account_cursor: usize, context: &Context) -> Self {
|
pub fn new(account_hash: AccountHash, context: &Context) -> Self {
|
||||||
let mut ret = Composer {
|
let mut ret = Composer {
|
||||||
account_cursor,
|
account_hash,
|
||||||
id: ComponentId::new_v4(),
|
id: ComponentId::new_v4(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
for (h, v) in
|
for (h, v) in
|
||||||
mailbox_acc_settings!(context[account_cursor].composing.default_header_values).iter()
|
mailbox_acc_settings!(context[account_hash].composing.default_header_values).iter()
|
||||||
{
|
{
|
||||||
if v.is_empty() {
|
if v.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -176,23 +176,23 @@ impl Composer {
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit(account_pos: usize, h: EnvelopeHash, context: &Context) -> Result<Self> {
|
pub fn edit(new_account_hash: AccountHash, h: EnvelopeHash, context: &Context) -> Result<Self> {
|
||||||
let mut ret = Composer::default();
|
let mut ret = Composer::default();
|
||||||
let op = context.accounts[account_pos].operation(h)?;
|
let op = context.accounts[&new_account_hash].operation(h)?;
|
||||||
let envelope: EnvelopeRef = context.accounts[account_pos].collection.get_env(h);
|
let envelope: EnvelopeRef = context.accounts[&new_account_hash].collection.get_env(h);
|
||||||
|
|
||||||
ret.draft = Draft::edit(&envelope, op)?;
|
ret.draft = Draft::edit(&envelope, op)?;
|
||||||
|
|
||||||
ret.account_cursor = account_pos;
|
ret.account_hash = new_account_hash;
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_context(
|
pub fn with_context(
|
||||||
coordinates: (usize, MailboxHash),
|
coordinates: (AccountHash, MailboxHash),
|
||||||
msg: EnvelopeHash,
|
msg: EnvelopeHash,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let account = &context.accounts[coordinates.0];
|
let account = &context.accounts[&coordinates.0];
|
||||||
let mut ret = Composer::default();
|
let mut ret = Composer::default();
|
||||||
ret.pager
|
ret.pager
|
||||||
.set_colors(crate::conf::value(context, "theme_default"));
|
.set_colors(crate::conf::value(context, "theme_default"));
|
||||||
|
@ -245,7 +245,7 @@ impl Composer {
|
||||||
);
|
);
|
||||||
|
|
||||||
drop(parent_message);
|
drop(parent_message);
|
||||||
match context.accounts[coordinates.0]
|
match context.accounts[&coordinates.0]
|
||||||
.operation(msg)
|
.operation(msg)
|
||||||
.and_then(|mut op| op.as_bytes())
|
.and_then(|mut op| op.as_bytes())
|
||||||
{
|
{
|
||||||
|
@ -257,10 +257,10 @@ impl Composer {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Ok(fut) => {
|
Ok(fut) => {
|
||||||
let (mut rcvr, handle, job_id) = context.accounts[coordinates.0]
|
let (mut rcvr, handle, job_id) = context.accounts[&coordinates.0]
|
||||||
.job_executor
|
.job_executor
|
||||||
.spawn_specialized(fut);
|
.spawn_specialized(fut);
|
||||||
context.accounts[coordinates.0]
|
context.accounts[&coordinates.0]
|
||||||
.active_jobs
|
.active_jobs
|
||||||
.insert(job_id, JobRequest::AsBytes(handle));
|
.insert(job_id, JobRequest::AsBytes(handle));
|
||||||
if let Ok(Some(parent_bytes)) = try_recv_timeout!(&mut rcvr) {
|
if let Ok(Some(parent_bytes)) = try_recv_timeout!(&mut rcvr) {
|
||||||
|
@ -274,8 +274,9 @@ impl Composer {
|
||||||
}
|
}
|
||||||
Ok(parent_bytes) => {
|
Ok(parent_bytes) => {
|
||||||
let env_hash = msg;
|
let env_hash = msg;
|
||||||
let parent_message =
|
let parent_message = context.accounts[&coordinates.0]
|
||||||
context.accounts[coordinates.0].collection.get_env(env_hash);
|
.collection
|
||||||
|
.get_env(env_hash);
|
||||||
let mut new_draft = Draft::new_reply(&parent_message, &parent_bytes);
|
let mut new_draft = Draft::new_reply(&parent_message, &parent_bytes);
|
||||||
new_draft
|
new_draft
|
||||||
.headers_mut()
|
.headers_mut()
|
||||||
|
@ -291,7 +292,7 @@ impl Composer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret.account_cursor = coordinates.0;
|
ret.account_hash = coordinates.0;
|
||||||
ret.reply_context = Some((coordinates.1, msg));
|
ret.reply_context = Some((coordinates.1, msg));
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -317,14 +318,14 @@ impl Composer {
|
||||||
self.form.hide_buttons();
|
self.form.hide_buttons();
|
||||||
self.form.set_cursor(old_cursor);
|
self.form.set_cursor(old_cursor);
|
||||||
let headers = self.draft.headers();
|
let headers = self.draft.headers();
|
||||||
let account_cursor = self.account_cursor;
|
let account_hash = self.account_hash;
|
||||||
for &k in &["Date", "From", "To", "Cc", "Bcc", "Subject"] {
|
for &k in &["Date", "From", "To", "Cc", "Bcc", "Subject"] {
|
||||||
if k == "To" || k == "Cc" || k == "Bcc" {
|
if k == "To" || k == "Cc" || k == "Bcc" {
|
||||||
self.form.push_cl((
|
self.form.push_cl((
|
||||||
k.into(),
|
k.into(),
|
||||||
headers[k].to_string(),
|
headers[k].to_string(),
|
||||||
Box::new(move |c, term| {
|
Box::new(move |c, term| {
|
||||||
let book: &AddressBook = &c.accounts[account_cursor].address_book;
|
let book: &AddressBook = &c.accounts[&account_hash].address_book;
|
||||||
let results: Vec<String> = book.search(term);
|
let results: Vec<String> = book.search(term);
|
||||||
results
|
results
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -346,7 +347,7 @@ impl Composer {
|
||||||
write_string_to_grid(
|
write_string_to_grid(
|
||||||
&format!(
|
&format!(
|
||||||
"☑ sign with {}",
|
"☑ sign with {}",
|
||||||
mailbox_acc_settings!(context[self.account_cursor].pgp.key)
|
mailbox_acc_settings!(context[self.account_hash].pgp.key)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.as_str())
|
.map(|s| s.as_str())
|
||||||
.unwrap_or("default key")
|
.unwrap_or("default key")
|
||||||
|
@ -438,14 +439,14 @@ impl Component for Composer {
|
||||||
if !self.initialized {
|
if !self.initialized {
|
||||||
if self.sign_mail.is_unset() {
|
if self.sign_mail.is_unset() {
|
||||||
self.sign_mail = ToggleFlag::InternalVal(*mailbox_acc_settings!(
|
self.sign_mail = ToggleFlag::InternalVal(*mailbox_acc_settings!(
|
||||||
context[self.account_cursor].pgp.auto_sign
|
context[self.account_hash].pgp.auto_sign
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if !self.draft.headers().contains_key("From") || self.draft.headers()["From"].is_empty()
|
if !self.draft.headers().contains_key("From") || self.draft.headers()["From"].is_empty()
|
||||||
{
|
{
|
||||||
self.draft.headers_mut().insert(
|
self.draft.headers_mut().insert(
|
||||||
"From".into(),
|
"From".into(),
|
||||||
crate::components::mail::get_display_name(context, self.account_cursor),
|
crate::components::mail::get_display_name(context, self.account_hash),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.pager.update_from_str(self.draft.body(), Some(77));
|
self.pager.update_from_str(self.draft.body(), Some(77));
|
||||||
|
@ -644,7 +645,7 @@ impl Component for Composer {
|
||||||
match bytes {
|
match bytes {
|
||||||
Ok(parent_bytes) => {
|
Ok(parent_bytes) => {
|
||||||
let env_hash = self.reply_context.unwrap().1;
|
let env_hash = self.reply_context.unwrap().1;
|
||||||
let parent_message = context.accounts[self.account_cursor]
|
let parent_message = context.accounts[&self.account_hash]
|
||||||
.collection
|
.collection
|
||||||
.get_env(env_hash);
|
.get_env(env_hash);
|
||||||
let mut new_draft = Draft::new_reply(&parent_message, &parent_bytes);
|
let mut new_draft = Draft::new_reply(&parent_message, &parent_bytes);
|
||||||
|
@ -681,7 +682,7 @@ impl Component for Composer {
|
||||||
match send_draft(
|
match send_draft(
|
||||||
self.sign_mail,
|
self.sign_mail,
|
||||||
context,
|
context,
|
||||||
self.account_cursor,
|
self.account_hash,
|
||||||
self.draft.clone(),
|
self.draft.clone(),
|
||||||
SpecialUsageMailbox::Sent,
|
SpecialUsageMailbox::Sent,
|
||||||
Flag::SEEN,
|
Flag::SEEN,
|
||||||
|
@ -726,7 +727,7 @@ impl Component for Composer {
|
||||||
context,
|
context,
|
||||||
SpecialUsageMailbox::Drafts,
|
SpecialUsageMailbox::Drafts,
|
||||||
Flag::SEEN | Flag::DRAFT,
|
Flag::SEEN | Flag::DRAFT,
|
||||||
self.account_cursor,
|
self.account_hash,
|
||||||
);
|
);
|
||||||
self.mode = ViewMode::Edit;
|
self.mode = ViewMode::Edit;
|
||||||
}
|
}
|
||||||
|
@ -774,7 +775,7 @@ impl Component for Composer {
|
||||||
context,
|
context,
|
||||||
SpecialUsageMailbox::Drafts,
|
SpecialUsageMailbox::Drafts,
|
||||||
Flag::SEEN | Flag::DRAFT,
|
Flag::SEEN | Flag::DRAFT,
|
||||||
self.account_cursor,
|
self.account_hash,
|
||||||
);
|
);
|
||||||
context.replies.push_back(UIEvent::Action(Tab(Kill(*u))));
|
context.replies.push_back(UIEvent::Action(Tab(Kill(*u))));
|
||||||
return true;
|
return true;
|
||||||
|
@ -808,7 +809,7 @@ impl Component for Composer {
|
||||||
if let ViewMode::WaitingForSendResult(_, handle, job_id, chan) =
|
if let ViewMode::WaitingForSendResult(_, handle, job_id, chan) =
|
||||||
std::mem::replace(&mut self.mode, ViewMode::Edit)
|
std::mem::replace(&mut self.mode, ViewMode::Edit)
|
||||||
{
|
{
|
||||||
context.accounts[self.account_cursor].active_jobs.insert(
|
context.accounts[&self.account_hash].active_jobs.insert(
|
||||||
job_id,
|
job_id,
|
||||||
JobRequest::SendMessageBackground(handle, chan),
|
JobRequest::SendMessageBackground(handle, chan),
|
||||||
);
|
);
|
||||||
|
@ -863,10 +864,9 @@ impl Component for Composer {
|
||||||
/*
|
/*
|
||||||
/* Switch e-mail From: field to the `left` configured account. */
|
/* Switch e-mail From: field to the `left` configured account. */
|
||||||
UIEvent::Input(Key::Left) if self.cursor == Cursor::From => {
|
UIEvent::Input(Key::Left) if self.cursor == Cursor::From => {
|
||||||
self.account_cursor = self.account_cursor.saturating_sub(1);
|
|
||||||
self.draft.headers_mut().insert(
|
self.draft.headers_mut().insert(
|
||||||
"From".into(),
|
"From".into(),
|
||||||
get_display_name(context, self.account_cursor),
|
get_display_name(context, self.account_hash),
|
||||||
);
|
);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1039,7 +1039,7 @@ impl Component for Composer {
|
||||||
{
|
{
|
||||||
/* Edit draft in $EDITOR */
|
/* Edit draft in $EDITOR */
|
||||||
let editor = if let Some(editor_command) =
|
let editor = if let Some(editor_command) =
|
||||||
mailbox_acc_settings!(context[self.account_cursor].composing.editor_command)
|
mailbox_acc_settings!(context[self.account_hash].composing.editor_command)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
{
|
{
|
||||||
editor_command.to_string()
|
editor_command.to_string()
|
||||||
|
@ -1065,7 +1065,7 @@ impl Component for Composer {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
if *mailbox_acc_settings!(context[self.account_cursor].composing.embed) {
|
if *mailbox_acc_settings!(context[self.account_hash].composing.embed) {
|
||||||
self.embed = Some(EmbedStatus::Running(
|
self.embed = Some(EmbedStatus::Running(
|
||||||
crate::terminal::embed::create_pty(
|
crate::terminal::embed::create_pty(
|
||||||
width!(self.embed_area),
|
width!(self.embed_area),
|
||||||
|
@ -1249,7 +1249,7 @@ impl Component for Composer {
|
||||||
context,
|
context,
|
||||||
SpecialUsageMailbox::Drafts,
|
SpecialUsageMailbox::Drafts,
|
||||||
Flag::SEEN | Flag::DRAFT,
|
Flag::SEEN | Flag::DRAFT,
|
||||||
self.account_cursor,
|
self.account_hash,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1319,7 +1319,7 @@ impl Component for Composer {
|
||||||
};
|
};
|
||||||
|
|
||||||
let our_map: ShortcutMap =
|
let our_map: ShortcutMap =
|
||||||
mailbox_acc_settings!(context[self.account_cursor].shortcuts.composing).key_values();
|
mailbox_acc_settings!(context[self.account_hash].shortcuts.composing).key_values();
|
||||||
map.insert(Composer::DESCRIPTION, our_map);
|
map.insert(Composer::DESCRIPTION, our_map);
|
||||||
|
|
||||||
map
|
map
|
||||||
|
@ -1366,13 +1366,13 @@ impl Component for Composer {
|
||||||
pub fn send_draft(
|
pub fn send_draft(
|
||||||
sign_mail: ToggleFlag,
|
sign_mail: ToggleFlag,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
account_cursor: usize,
|
account_hash: AccountHash,
|
||||||
mut draft: Draft,
|
mut draft: Draft,
|
||||||
mailbox_type: SpecialUsageMailbox,
|
mailbox_type: SpecialUsageMailbox,
|
||||||
flags: Flag,
|
flags: Flag,
|
||||||
complete_in_background: bool,
|
complete_in_background: bool,
|
||||||
) -> Result<Option<(JobId, JoinHandle, JobChannel<()>)>> {
|
) -> Result<Option<(JobId, JoinHandle, JobChannel<()>)>> {
|
||||||
let format_flowed = *mailbox_acc_settings!(context[account_cursor].composing.format_flowed);
|
let format_flowed = *mailbox_acc_settings!(context[account_hash].composing.format_flowed);
|
||||||
if sign_mail.is_true() {
|
if sign_mail.is_true() {
|
||||||
let mut content_type = ContentType::default();
|
let mut content_type = ContentType::default();
|
||||||
if format_flowed {
|
if format_flowed {
|
||||||
|
@ -1407,10 +1407,10 @@ pub fn send_draft(
|
||||||
}
|
}
|
||||||
let output = crate::components::mail::pgp::sign(
|
let output = crate::components::mail::pgp::sign(
|
||||||
body.into(),
|
body.into(),
|
||||||
mailbox_acc_settings!(context[account_cursor].pgp.gpg_binary)
|
mailbox_acc_settings!(context[account_hash].pgp.gpg_binary)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.as_str()),
|
.map(|s| s.as_str()),
|
||||||
mailbox_acc_settings!(context[account_cursor].pgp.key)
|
mailbox_acc_settings!(context[account_hash].pgp.key)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.as_str()),
|
.map(|s| s.as_str()),
|
||||||
);
|
);
|
||||||
|
@ -1420,7 +1420,7 @@ pub fn send_draft(
|
||||||
log(
|
log(
|
||||||
format!(
|
format!(
|
||||||
"Could not sign draft in account `{}`: {}.",
|
"Could not sign draft in account `{}`: {}.",
|
||||||
context.accounts[account_cursor].name(),
|
context.accounts[&account_hash].name(),
|
||||||
err.to_string()
|
err.to_string()
|
||||||
),
|
),
|
||||||
ERROR,
|
ERROR,
|
||||||
|
@ -1428,7 +1428,7 @@ pub fn send_draft(
|
||||||
context.replies.push_back(UIEvent::Notification(
|
context.replies.push_back(UIEvent::Notification(
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"Could not sign draft in account `{}`.",
|
"Could not sign draft in account `{}`.",
|
||||||
context.accounts[account_cursor].name()
|
context.accounts[&account_hash].name()
|
||||||
)),
|
)),
|
||||||
err.to_string(),
|
err.to_string(),
|
||||||
Some(NotificationType::ERROR),
|
Some(NotificationType::ERROR),
|
||||||
|
@ -1459,16 +1459,10 @@ pub fn send_draft(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let bytes = draft.finalise().unwrap();
|
let bytes = draft.finalise().unwrap();
|
||||||
let send_mail = mailbox_acc_settings!(context[account_cursor].composing.send_mail).clone();
|
let send_mail = mailbox_acc_settings!(context[account_hash].composing.send_mail).clone();
|
||||||
let ret =
|
let ret =
|
||||||
context.accounts[account_cursor].send(bytes.clone(), send_mail, complete_in_background);
|
context.accounts[&account_hash].send(bytes.clone(), send_mail, complete_in_background);
|
||||||
save_draft(
|
save_draft(bytes.as_bytes(), context, mailbox_type, flags, account_hash);
|
||||||
bytes.as_bytes(),
|
|
||||||
context,
|
|
||||||
mailbox_type,
|
|
||||||
flags,
|
|
||||||
account_cursor,
|
|
||||||
);
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1477,9 +1471,9 @@ pub fn save_draft(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
mailbox_type: SpecialUsageMailbox,
|
mailbox_type: SpecialUsageMailbox,
|
||||||
flags: Flag,
|
flags: Flag,
|
||||||
account_cursor: usize,
|
account_hash: AccountHash,
|
||||||
) {
|
) {
|
||||||
match context.accounts[account_cursor].save_special(bytes, mailbox_type, flags) {
|
match context.accounts[&account_hash].save_special(bytes, mailbox_type, flags) {
|
||||||
Err(MeliError {
|
Err(MeliError {
|
||||||
summary, details, ..
|
summary, details, ..
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -1494,7 +1488,7 @@ pub fn save_draft(
|
||||||
Some("Message saved".into()),
|
Some("Message saved".into()),
|
||||||
format!(
|
format!(
|
||||||
"Message saved in `{}`",
|
"Message saved in `{}`",
|
||||||
&context.accounts[account_cursor].mailbox_entries[&mailbox_hash].name
|
&context.accounts[&account_hash].mailbox_entries[&mailbox_hash].name
|
||||||
),
|
),
|
||||||
Some(NotificationType::INFO),
|
Some(NotificationType::INFO),
|
||||||
));
|
));
|
||||||
|
|
|
@ -134,7 +134,7 @@ column_str!(struct TagString(String, SmallVec<[Option<Color>; 8]>));
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct AccountMenuEntry {
|
struct AccountMenuEntry {
|
||||||
name: String,
|
name: String,
|
||||||
// Index in the config account vector.
|
hash: AccountHash,
|
||||||
index: usize,
|
index: usize,
|
||||||
entries: SmallVec<[(usize, MailboxHash); 16]>,
|
entries: SmallVec<[(usize, MailboxHash); 16]>,
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
thread_hashes: SmallVec<[ThreadHash; 8]>,
|
thread_hashes: SmallVec<[ThreadHash; 8]>,
|
||||||
a: &ListingAction,
|
a: &ListingAction,
|
||||||
) {
|
) {
|
||||||
let account_pos = self.coordinates().0;
|
let account_hash = self.coordinates().0;
|
||||||
let account = &mut context.accounts[account_pos];
|
let account = &mut context.accounts[&account_hash];
|
||||||
let mut envs_to_set: SmallVec<[EnvelopeHash; 8]> = SmallVec::new();
|
let mut envs_to_set: SmallVec<[EnvelopeHash; 8]> = SmallVec::new();
|
||||||
let mailbox_hash = self.coordinates().1;
|
let mailbox_hash = self.coordinates().1;
|
||||||
{
|
{
|
||||||
|
@ -361,8 +361,8 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ListingTrait: Component {
|
pub trait ListingTrait: Component {
|
||||||
fn coordinates(&self) -> (usize, MailboxHash);
|
fn coordinates(&self) -> (AccountHash, MailboxHash);
|
||||||
fn set_coordinates(&mut self, _: (usize, MailboxHash));
|
fn set_coordinates(&mut self, _: (AccountHash, MailboxHash));
|
||||||
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
|
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
|
||||||
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context);
|
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize, context: &Context);
|
||||||
fn filter(
|
fn filter(
|
||||||
|
@ -482,10 +482,6 @@ impl fmt::Display for Listing {
|
||||||
|
|
||||||
impl Component for Listing {
|
impl Component for Listing {
|
||||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||||
for i in 0..context.accounts.len() {
|
|
||||||
let _ = context.is_online(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.is_dirty() {
|
if !self.is_dirty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -524,12 +520,13 @@ impl Component for Listing {
|
||||||
.push_back(((mid, get_y(upper_left)), (mid, get_y(bottom_right))));
|
.push_back(((mid, get_y(upper_left)), (mid, get_y(bottom_right))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let account_hash = self.accounts[self.cursor_pos.0].hash;
|
||||||
if right_component_width == total_cols {
|
if right_component_width == total_cols {
|
||||||
if context.is_online(self.cursor_pos.0).is_err() {
|
if context.is_online(account_hash).is_err() {
|
||||||
match self.component {
|
match self.component {
|
||||||
ListingComponent::Offline(_) => {}
|
ListingComponent::Offline(_) => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.component = Offline(OfflineListing::new((self.cursor_pos.0, 0)));
|
self.component = Offline(OfflineListing::new((account_hash, 0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -539,11 +536,11 @@ impl Component for Listing {
|
||||||
self.draw_menu(grid, area, context);
|
self.draw_menu(grid, area, context);
|
||||||
} else {
|
} else {
|
||||||
self.draw_menu(grid, (upper_left, (mid, get_y(bottom_right))), context);
|
self.draw_menu(grid, (upper_left, (mid, get_y(bottom_right))), context);
|
||||||
if context.is_online(self.cursor_pos.0).is_err() {
|
if context.is_online(account_hash).is_err() {
|
||||||
match self.component {
|
match self.component {
|
||||||
ListingComponent::Offline(_) => {}
|
ListingComponent::Offline(_) => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.component = Offline(OfflineListing::new((self.cursor_pos.0, 0)));
|
self.component = Offline(OfflineListing::new((account_hash, 0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,15 +568,19 @@ impl Component for Listing {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEvent::AccountStatusChange(account_index) => {
|
UIEvent::AccountStatusChange(account_hash) => {
|
||||||
if self.cursor_pos.0 == *account_index {
|
let account_index = context
|
||||||
|
.accounts
|
||||||
|
.get_index_of(account_hash)
|
||||||
|
.expect("Invalid account_hash in UIEventMailbox{Delete,Create}");
|
||||||
|
if self.cursor_pos.0 == account_index {
|
||||||
self.change_account(context);
|
self.change_account(context);
|
||||||
} else {
|
} else {
|
||||||
self.accounts[*account_index].entries = context.accounts[*account_index]
|
self.accounts[account_index].entries = context.accounts[&*account_hash]
|
||||||
.list_mailboxes()
|
.list_mailboxes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|mailbox_node| {
|
.filter(|mailbox_node| {
|
||||||
context.accounts[*account_index][&mailbox_node.hash]
|
context.accounts[&*account_hash][&mailbox_node.hash]
|
||||||
.ref_mailbox
|
.ref_mailbox
|
||||||
.is_subscribed()
|
.is_subscribed()
|
||||||
})
|
})
|
||||||
|
@ -589,25 +590,29 @@ impl Component for Listing {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::MailboxDelete((account_index, _mailbox_hash))
|
UIEvent::MailboxDelete((account_hash, _mailbox_hash))
|
||||||
| UIEvent::MailboxCreate((account_index, _mailbox_hash)) => {
|
| UIEvent::MailboxCreate((account_hash, _mailbox_hash)) => {
|
||||||
self.accounts[*account_index].entries = context.accounts[*account_index]
|
let account_index = context
|
||||||
|
.accounts
|
||||||
|
.get_index_of(account_hash)
|
||||||
|
.expect("Invalid account_hash in UIEventMailbox{Delete,Create}");
|
||||||
|
self.accounts[account_index].entries = context.accounts[&*account_hash]
|
||||||
.list_mailboxes()
|
.list_mailboxes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|mailbox_node| {
|
.filter(|mailbox_node| {
|
||||||
context.accounts[*account_index][&mailbox_node.hash]
|
context.accounts[&*account_hash][&mailbox_node.hash]
|
||||||
.ref_mailbox
|
.ref_mailbox
|
||||||
.is_subscribed()
|
.is_subscribed()
|
||||||
})
|
})
|
||||||
.map(|f| (f.depth, f.hash))
|
.map(|f| (f.depth, f.hash))
|
||||||
.collect::<_>();
|
.collect::<_>();
|
||||||
if self.cursor_pos.0 == *account_index {
|
if self.cursor_pos.0 == account_index {
|
||||||
self.cursor_pos.1 = std::cmp::min(
|
self.cursor_pos.1 = std::cmp::min(
|
||||||
self.accounts[self.cursor_pos.0].entries.len() - 1,
|
self.accounts[self.cursor_pos.0].entries.len() - 1,
|
||||||
self.cursor_pos.1,
|
self.cursor_pos.1,
|
||||||
);
|
);
|
||||||
self.component.set_coordinates((
|
self.component.set_coordinates((
|
||||||
self.cursor_pos.0,
|
self.accounts[self.cursor_pos.0].hash,
|
||||||
self.accounts[self.cursor_pos.0].entries[self.cursor_pos.1].1,
|
self.accounts[self.cursor_pos.0].entries[self.cursor_pos.1].1,
|
||||||
));
|
));
|
||||||
self.component.refresh_mailbox(context, true);
|
self.component.refresh_mailbox(context, true);
|
||||||
|
@ -759,9 +764,10 @@ impl Component for Listing {
|
||||||
if let Some((_, mailbox_hash)) =
|
if let Some((_, mailbox_hash)) =
|
||||||
self.accounts[self.cursor_pos.0].entries.get(*idx)
|
self.accounts[self.cursor_pos.0].entries.get(*idx)
|
||||||
{
|
{
|
||||||
|
let account_hash = self.accounts[self.cursor_pos.0].hash;
|
||||||
self.cursor_pos.1 = *idx;
|
self.cursor_pos.1 = *idx;
|
||||||
self.component
|
self.component
|
||||||
.set_coordinates((self.cursor_pos.0, *mailbox_hash));
|
.set_coordinates((account_hash, *mailbox_hash));
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1092,9 +1098,10 @@ impl Component for Listing {
|
||||||
UIEvent::Input(ref k)
|
UIEvent::Input(ref k)
|
||||||
if shortcut!(k == shortcuts[Listing::DESCRIPTION]["new_mail"]) =>
|
if shortcut!(k == shortcuts[Listing::DESCRIPTION]["new_mail"]) =>
|
||||||
{
|
{
|
||||||
|
let account_hash = context.accounts[self.cursor_pos.0].hash();
|
||||||
context
|
context
|
||||||
.replies
|
.replies
|
||||||
.push_back(UIEvent::Action(Tab(NewDraft(self.cursor_pos.0, None))));
|
.push_back(UIEvent::Action(Tab(NewDraft(account_hash, None))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::StartupCheck(_) => {
|
UIEvent::StartupCheck(_) => {
|
||||||
|
@ -1190,17 +1197,6 @@ impl Component for Listing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(IndexStyle, (usize, MailboxHash))> for ListingComponent {
|
|
||||||
fn from((index_style, coordinates): (IndexStyle, (usize, MailboxHash))) -> Self {
|
|
||||||
match index_style {
|
|
||||||
IndexStyle::Plain => Plain(PlainListing::new(coordinates)),
|
|
||||||
IndexStyle::Threaded => Threaded(ThreadListing::new(coordinates)),
|
|
||||||
IndexStyle::Compact => Compact(CompactListing::new(coordinates)),
|
|
||||||
IndexStyle::Conversations => Conversations(ConversationsListing::new(coordinates)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Listing {
|
impl Listing {
|
||||||
pub const DESCRIPTION: &'static str = "listing";
|
pub const DESCRIPTION: &'static str = "listing";
|
||||||
pub fn new(context: &mut Context) -> Self {
|
pub fn new(context: &mut Context) -> Self {
|
||||||
|
@ -1208,7 +1204,7 @@ impl Listing {
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, a)| {
|
.map(|(i, (h, a))| {
|
||||||
let entries: SmallVec<[(usize, MailboxHash); 16]> = a
|
let entries: SmallVec<[(usize, MailboxHash); 16]> = a
|
||||||
.list_mailboxes()
|
.list_mailboxes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1218,13 +1214,14 @@ impl Listing {
|
||||||
|
|
||||||
AccountMenuEntry {
|
AccountMenuEntry {
|
||||||
name: a.name().to_string(),
|
name: a.name().to_string(),
|
||||||
|
hash: *h,
|
||||||
index: i,
|
index: i,
|
||||||
entries,
|
entries,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let mut ret = Listing {
|
let mut ret = Listing {
|
||||||
component: Offline(OfflineListing::new((0, 0))),
|
component: Offline(OfflineListing::new((account_entries[0].hash, 0))),
|
||||||
accounts: account_entries,
|
accounts: account_entries,
|
||||||
visible: true,
|
visible: true,
|
||||||
dirty: true,
|
dirty: true,
|
||||||
|
@ -1477,6 +1474,7 @@ impl Listing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_account(&mut self, context: &mut Context) {
|
fn change_account(&mut self, context: &mut Context) {
|
||||||
|
let account_hash = context.accounts[self.cursor_pos.0].hash();
|
||||||
self.accounts[self.cursor_pos.0].entries = context.accounts[self.cursor_pos.0]
|
self.accounts[self.cursor_pos.0].entries = context.accounts[self.cursor_pos.0]
|
||||||
.list_mailboxes()
|
.list_mailboxes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1493,15 +1491,15 @@ impl Listing {
|
||||||
.get(self.cursor_pos.1)
|
.get(self.cursor_pos.1)
|
||||||
{
|
{
|
||||||
self.component
|
self.component
|
||||||
.set_coordinates((self.cursor_pos.0, *mailbox_hash));
|
.set_coordinates((account_hash, *mailbox_hash));
|
||||||
/* Check if per-mailbox configuration overrides general configuration */
|
/* Check if per-mailbox configuration overrides general configuration */
|
||||||
|
|
||||||
let index_style =
|
let index_style =
|
||||||
mailbox_settings!(context[self.cursor_pos.0][mailbox_hash].listing.index_style);
|
mailbox_settings!(context[account_hash][mailbox_hash].listing.index_style);
|
||||||
self.component.set_style(*index_style);
|
self.component.set_style(*index_style);
|
||||||
} else {
|
} else {
|
||||||
/* Set to dummy */
|
/* Set to dummy */
|
||||||
self.component = Offline(OfflineListing::new((self.cursor_pos.0, 0)));
|
self.component = Offline(OfflineListing::new((account_hash, 0)));
|
||||||
}
|
}
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
context
|
context
|
||||||
|
|
|
@ -124,8 +124,8 @@ macro_rules! row_attr {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CompactListing {
|
pub struct CompactListing {
|
||||||
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
||||||
cursor_pos: (usize, MailboxHash, usize),
|
cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
new_cursor_pos: (usize, MailboxHash, usize),
|
new_cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
length: usize,
|
length: usize,
|
||||||
sort: (SortField, SortOrder),
|
sort: (SortField, SortOrder),
|
||||||
subsort: (SortField, SortOrder),
|
subsort: (SortField, SortOrder),
|
||||||
|
@ -231,7 +231,7 @@ impl MailListingTrait for CompactListing {
|
||||||
|
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
match context.accounts[self.cursor_pos.0].load(self.cursor_pos.1) {
|
match context.accounts[&self.cursor_pos.0].load(self.cursor_pos.1) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let default_cell = {
|
let default_cell = {
|
||||||
|
@ -242,7 +242,7 @@ impl MailListingTrait for CompactListing {
|
||||||
ret
|
ret
|
||||||
};
|
};
|
||||||
let message: String =
|
let message: String =
|
||||||
context.accounts[self.cursor_pos.0][&self.cursor_pos.1].status();
|
context.accounts[&self.cursor_pos.0][&self.cursor_pos.1].status();
|
||||||
self.data_columns.columns[0] =
|
self.data_columns.columns[0] =
|
||||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
|
@ -259,14 +259,14 @@ impl MailListingTrait for CompactListing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let threads = context.accounts[self.cursor_pos.0]
|
let threads = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_threads(self.cursor_pos.1);
|
.get_threads(self.cursor_pos.1);
|
||||||
let mut roots = threads.roots();
|
let mut roots = threads.roots();
|
||||||
threads.group_inner_sort_by(
|
threads.group_inner_sort_by(
|
||||||
&mut roots,
|
&mut roots,
|
||||||
self.sort,
|
self.sort,
|
||||||
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
&context.accounts[&self.cursor_pos.0].collection.envelopes,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.redraw_threads_list(
|
self.redraw_threads_list(
|
||||||
|
@ -288,7 +288,7 @@ impl MailListingTrait for CompactListing {
|
||||||
context: &Context,
|
context: &Context,
|
||||||
items: Box<dyn Iterator<Item = ThreadHash>>,
|
items: Box<dyn Iterator<Item = ThreadHash>>,
|
||||||
) {
|
) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
|
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
self.order.clear();
|
self.order.clear();
|
||||||
|
@ -328,18 +328,18 @@ impl MailListingTrait for CompactListing {
|
||||||
} else {
|
} else {
|
||||||
continue 'items_for_loop;
|
continue 'items_for_loop;
|
||||||
};
|
};
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(root_env_hash) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(root_env_hash) {
|
||||||
debug!("key = {}", root_env_hash);
|
debug!("key = {}", root_env_hash);
|
||||||
debug!(
|
debug!(
|
||||||
"name = {} {}",
|
"name = {} {}",
|
||||||
account[&self.cursor_pos.1].name(),
|
account[&self.cursor_pos.1].name(),
|
||||||
context.accounts[self.cursor_pos.0].name()
|
context.accounts[&self.cursor_pos.0].name()
|
||||||
);
|
);
|
||||||
debug!("{:#?}", context.accounts);
|
debug!("{:#?}", context.accounts);
|
||||||
|
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let root_envelope: EnvelopeRef = context.accounts[self.cursor_pos.0]
|
let root_envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(root_env_hash);
|
.get_env(root_env_hash);
|
||||||
use melib::search::QueryTrait;
|
use melib::search::QueryTrait;
|
||||||
|
@ -455,11 +455,11 @@ impl MailListingTrait for CompactListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListingTrait for CompactListing {
|
impl ListingTrait for CompactListing {
|
||||||
fn coordinates(&self) -> (usize, MailboxHash) {
|
fn coordinates(&self) -> (AccountHash, MailboxHash) {
|
||||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, MailboxHash)) {
|
fn set_coordinates(&mut self, coordinates: (AccountHash, MailboxHash)) {
|
||||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||||
self.unfocused = false;
|
self.unfocused = false;
|
||||||
self.view = ThreadView::default();
|
self.view = ThreadView::default();
|
||||||
|
@ -475,7 +475,7 @@ impl ListingTrait for CompactListing {
|
||||||
}
|
}
|
||||||
let thread_hash = self.get_thread_under_cursor(idx);
|
let thread_hash = self.get_thread_under_cursor(idx);
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
let thread = threads.thread_ref(thread_hash);
|
let thread = threads.thread_ref(thread_hash);
|
||||||
|
|
||||||
|
@ -698,7 +698,7 @@ impl ListingTrait for CompactListing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
for r in 0..cmp::min(self.length - top_idx, rows) {
|
for r in 0..cmp::min(self.length - top_idx, rows) {
|
||||||
let thread_hash = self.get_thread_under_cursor(r + top_idx);
|
let thread_hash = self.get_thread_under_cursor(r + top_idx);
|
||||||
|
@ -778,7 +778,7 @@ impl ListingTrait for CompactListing {
|
||||||
self.filter_term = filter_term;
|
self.filter_term = filter_term;
|
||||||
self.row_updates.clear();
|
self.row_updates.clear();
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
match results {
|
match results {
|
||||||
Ok(results) => {
|
Ok(results) => {
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
|
@ -805,7 +805,7 @@ impl ListingTrait for CompactListing {
|
||||||
threads.group_inner_sort_by(
|
threads.group_inner_sort_by(
|
||||||
&mut self.filtered_selection,
|
&mut self.filtered_selection,
|
||||||
self.sort,
|
self.sort,
|
||||||
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
&context.accounts[&self.cursor_pos.0].collection.envelopes,
|
||||||
);
|
);
|
||||||
self.new_cursor_pos.2 =
|
self.new_cursor_pos.2 =
|
||||||
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
|
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
|
||||||
|
@ -873,9 +873,9 @@ impl fmt::Display for CompactListing {
|
||||||
|
|
||||||
impl CompactListing {
|
impl CompactListing {
|
||||||
pub const DESCRIPTION: &'static str = "compact listing";
|
pub const DESCRIPTION: &'static str = "compact listing";
|
||||||
pub fn new(coordinates: (usize, MailboxHash)) -> Self {
|
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self {
|
||||||
CompactListing {
|
CompactListing {
|
||||||
cursor_pos: (0, 1, 0),
|
cursor_pos: (coordinates.0, 1, 0),
|
||||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||||
length: 0,
|
length: 0,
|
||||||
sort: (Default::default(), Default::default()),
|
sort: (Default::default(), Default::default()),
|
||||||
|
@ -911,7 +911,7 @@ impl CompactListing {
|
||||||
let thread = threads.thread_ref(hash);
|
let thread = threads.thread_ref(hash);
|
||||||
let mut tags = String::new();
|
let mut tags = String::new();
|
||||||
let mut colors: SmallVec<[_; 8]> = SmallVec::new();
|
let mut colors: SmallVec<[_; 8]> = SmallVec::new();
|
||||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
let backend_lck = context.accounts[&self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
for t in e.labels().iter() {
|
for t in e.labels().iter() {
|
||||||
|
@ -984,7 +984,7 @@ impl CompactListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
let thread = threads.thread_ref(thread_hash);
|
let thread = threads.thread_ref(thread_hash);
|
||||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||||
|
@ -1144,7 +1144,7 @@ impl CompactListing {
|
||||||
self.data_columns.columns[3].size().0,
|
self.data_columns.columns[3].size().0,
|
||||||
self.data_columns.columns[4].size().0,
|
self.data_columns.columns[4].size().0,
|
||||||
);
|
);
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
|
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
|
|
||||||
|
@ -1152,12 +1152,12 @@ impl CompactListing {
|
||||||
self.rows.iter().skip(start).take(end - start + 1)
|
self.rows.iter().skip(start).take(end - start + 1)
|
||||||
{
|
{
|
||||||
let idx = *idx;
|
let idx = *idx;
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(*root_env_hash) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(*root_env_hash) {
|
||||||
//debug!("key = {}", root_env_hash);
|
//debug!("key = {}", root_env_hash);
|
||||||
//debug!(
|
//debug!(
|
||||||
// "name = {} {}",
|
// "name = {} {}",
|
||||||
// account[&self.cursor_pos.1].name(),
|
// account[&self.cursor_pos.1].name(),
|
||||||
// context.accounts[self.cursor_pos.0].name()
|
// context.accounts[&self.cursor_pos.0].name()
|
||||||
//);
|
//);
|
||||||
//debug!("{:#?}", context.accounts);
|
//debug!("{:#?}", context.accounts);
|
||||||
|
|
||||||
|
@ -1316,7 +1316,7 @@ impl CompactListing {
|
||||||
results: Result<SmallVec<[EnvelopeHash; 512]>>,
|
results: Result<SmallVec<[EnvelopeHash; 512]>>,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
) {
|
) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
match results {
|
match results {
|
||||||
Ok(results) => {
|
Ok(results) => {
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
|
@ -1500,7 +1500,7 @@ impl Component for CompactListing {
|
||||||
}
|
}
|
||||||
Action::ToggleThreadSnooze if !self.unfocused => {
|
Action::ToggleThreadSnooze if !self.unfocused => {
|
||||||
let thread = self.get_thread_under_cursor(self.cursor_pos.2);
|
let thread = self.get_thread_under_cursor(self.cursor_pos.2);
|
||||||
let account = &mut context.accounts[self.cursor_pos.0];
|
let account = &mut context.accounts[&self.cursor_pos.0];
|
||||||
account
|
account
|
||||||
.collection
|
.collection
|
||||||
.threads
|
.threads
|
||||||
|
@ -1534,7 +1534,7 @@ impl Component for CompactListing {
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
if !account.collection.contains_key(&new_hash) {
|
if !account.collection.contains_key(&new_hash) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1552,8 +1552,10 @@ impl Component for CompactListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
self.view
|
||||||
|
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRemove(ref _env_hash, ref thread_hash) => {
|
UIEvent::EnvelopeRemove(ref _env_hash, ref thread_hash) => {
|
||||||
if self.order.contains_key(thread_hash) {
|
if self.order.contains_key(thread_hash) {
|
||||||
|
@ -1562,7 +1564,7 @@ impl Component for CompactListing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
if !account.collection.contains_key(&env_hash) {
|
if !account.collection.contains_key(&env_hash) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1580,8 +1582,10 @@ impl Component for CompactListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
self.view
|
||||||
|
.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
@ -1606,16 +1610,16 @@ impl Component for CompactListing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::Action(Action::Listing(Search(ref filter_term))) if !self.unfocused => {
|
UIEvent::Action(Action::Listing(Search(ref filter_term))) if !self.unfocused => {
|
||||||
match context.accounts[self.cursor_pos.0].search(
|
match context.accounts[&self.cursor_pos.0].search(
|
||||||
filter_term,
|
filter_term,
|
||||||
self.sort,
|
self.sort,
|
||||||
self.cursor_pos.1,
|
self.cursor_pos.1,
|
||||||
) {
|
) {
|
||||||
Ok(job) => {
|
Ok(job) => {
|
||||||
let (chan, handle, job_id) = context.accounts[self.cursor_pos.0]
|
let (chan, handle, job_id) = context.accounts[&self.cursor_pos.0]
|
||||||
.job_executor
|
.job_executor
|
||||||
.spawn_specialized(job);
|
.spawn_specialized(job);
|
||||||
context.accounts[self.cursor_pos.0]
|
context.accounts[&self.cursor_pos.0]
|
||||||
.active_jobs
|
.active_jobs
|
||||||
.insert(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
.insert(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
||||||
self.search_job = Some((filter_term.to_string(), chan, job_id));
|
self.search_job = Some((filter_term.to_string(), chan, job_id));
|
||||||
|
@ -1631,19 +1635,19 @@ impl Component for CompactListing {
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::Action(Action::Listing(Select(ref search_term))) if !self.unfocused => {
|
UIEvent::Action(Action::Listing(Select(ref search_term))) if !self.unfocused => {
|
||||||
match context.accounts[self.cursor_pos.0].search(
|
match context.accounts[&self.cursor_pos.0].search(
|
||||||
search_term,
|
search_term,
|
||||||
self.sort,
|
self.sort,
|
||||||
self.cursor_pos.1,
|
self.cursor_pos.1,
|
||||||
) {
|
) {
|
||||||
Ok(job) => {
|
Ok(job) => {
|
||||||
let (mut chan, handle, job_id) = context.accounts[self.cursor_pos.0]
|
let (mut chan, handle, job_id) = context.accounts[&self.cursor_pos.0]
|
||||||
.job_executor
|
.job_executor
|
||||||
.spawn_specialized(job);
|
.spawn_specialized(job);
|
||||||
if let Ok(Some(search_result)) = try_recv_timeout!(&mut chan) {
|
if let Ok(Some(search_result)) = try_recv_timeout!(&mut chan) {
|
||||||
self.select(search_term, search_result, context);
|
self.select(search_term, search_result, context);
|
||||||
} else {
|
} else {
|
||||||
context.accounts[self.cursor_pos.0]
|
context.accounts[&self.cursor_pos.0]
|
||||||
.active_jobs
|
.active_jobs
|
||||||
.insert(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
.insert(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
||||||
self.select_job = Some((search_term.to_string(), chan, job_id));
|
self.select_job = Some((search_term.to_string(), chan, job_id));
|
||||||
|
|
|
@ -94,8 +94,8 @@ macro_rules! row_attr {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConversationsListing {
|
pub struct ConversationsListing {
|
||||||
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
||||||
cursor_pos: (usize, MailboxHash, usize),
|
cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
new_cursor_pos: (usize, MailboxHash, usize),
|
new_cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
length: usize,
|
length: usize,
|
||||||
sort: (SortField, SortOrder),
|
sort: (SortField, SortOrder),
|
||||||
subsort: (SortField, SortOrder),
|
subsort: (SortField, SortOrder),
|
||||||
|
@ -194,7 +194,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
}
|
}
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
match context.accounts[self.cursor_pos.0].load(self.cursor_pos.1) {
|
match context.accounts[&self.cursor_pos.0].load(self.cursor_pos.1) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let default_cell = {
|
let default_cell = {
|
||||||
|
@ -205,7 +205,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
ret
|
ret
|
||||||
};
|
};
|
||||||
let message: String =
|
let message: String =
|
||||||
context.accounts[self.cursor_pos.0][&self.cursor_pos.1].status();
|
context.accounts[&self.cursor_pos.0][&self.cursor_pos.1].status();
|
||||||
self.content =
|
self.content =
|
||||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
|
@ -222,7 +222,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let threads = context.accounts[self.cursor_pos.0]
|
let threads = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_threads(self.cursor_pos.1);
|
.get_threads(self.cursor_pos.1);
|
||||||
self.all_threads.clear();
|
self.all_threads.clear();
|
||||||
|
@ -230,7 +230,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
threads.group_inner_sort_by(
|
threads.group_inner_sort_by(
|
||||||
&mut roots,
|
&mut roots,
|
||||||
self.sort,
|
self.sort,
|
||||||
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
&context.accounts[&self.cursor_pos.0].collection.envelopes,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.redraw_threads_list(
|
self.redraw_threads_list(
|
||||||
|
@ -253,7 +253,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
context: &Context,
|
context: &Context,
|
||||||
items: Box<dyn Iterator<Item = ThreadHash>>,
|
items: Box<dyn Iterator<Item = ThreadHash>>,
|
||||||
) {
|
) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
|
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
self.order.clear();
|
self.order.clear();
|
||||||
|
@ -284,12 +284,12 @@ impl MailListingTrait for ConversationsListing {
|
||||||
} else {
|
} else {
|
||||||
continue 'items_for_loop;
|
continue 'items_for_loop;
|
||||||
};
|
};
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(root_env_hash) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(root_env_hash) {
|
||||||
debug!("key = {}", root_env_hash);
|
debug!("key = {}", root_env_hash);
|
||||||
debug!(
|
debug!(
|
||||||
"name = {} {}",
|
"name = {} {}",
|
||||||
account[&self.cursor_pos.1].name(),
|
account[&self.cursor_pos.1].name(),
|
||||||
context.accounts[self.cursor_pos.0].name()
|
context.accounts[&self.cursor_pos.0].name()
|
||||||
);
|
);
|
||||||
debug!("{:#?}", context.accounts);
|
debug!("{:#?}", context.accounts);
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
for (_, h) in threads.thread_group_iter(thread) {
|
for (_, h) in threads.thread_group_iter(thread) {
|
||||||
let env_hash = threads.thread_nodes()[&h].message().unwrap();
|
let env_hash = threads.thread_nodes()[&h].message().unwrap();
|
||||||
|
|
||||||
let envelope: &EnvelopeRef = &context.accounts[self.cursor_pos.0]
|
let envelope: &EnvelopeRef = &context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(env_hash);
|
.get_env(env_hash);
|
||||||
for addr in envelope.from().iter() {
|
for addr in envelope.from().iter() {
|
||||||
|
@ -311,7 +311,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
from_address_list.push(addr.clone());
|
from_address_list.push(addr.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let root_envelope: &EnvelopeRef = &context.accounts[self.cursor_pos.0]
|
let root_envelope: &EnvelopeRef = &context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(root_env_hash);
|
.get_env(root_env_hash);
|
||||||
use melib::search::QueryTrait;
|
use melib::search::QueryTrait;
|
||||||
|
@ -361,7 +361,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
let padding_fg = self.color_cache.padding.fg;
|
let padding_fg = self.color_cache.padding.fg;
|
||||||
|
|
||||||
for ((idx, (thread, root_env_hash)), strings) in rows {
|
for ((idx, (thread, root_env_hash)), strings) in rows {
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(root_env_hash) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(root_env_hash) {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let thread = threads.thread_ref(thread);
|
let thread = threads.thread_ref(thread);
|
||||||
|
@ -487,11 +487,11 @@ impl MailListingTrait for ConversationsListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListingTrait for ConversationsListing {
|
impl ListingTrait for ConversationsListing {
|
||||||
fn coordinates(&self) -> (usize, MailboxHash) {
|
fn coordinates(&self) -> (AccountHash, MailboxHash) {
|
||||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, MailboxHash)) {
|
fn set_coordinates(&mut self, coordinates: (AccountHash, MailboxHash)) {
|
||||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||||
self.unfocused = false;
|
self.unfocused = false;
|
||||||
|
@ -508,7 +508,7 @@ impl ListingTrait for ConversationsListing {
|
||||||
}
|
}
|
||||||
let thread_hash = self.get_thread_under_cursor(idx);
|
let thread_hash = self.get_thread_under_cursor(idx);
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
let thread = threads.thread_ref(thread_hash);
|
let thread = threads.thread_ref(thread_hash);
|
||||||
|
|
||||||
|
@ -769,7 +769,7 @@ impl ListingTrait for ConversationsListing {
|
||||||
*v = false;
|
*v = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
match results {
|
match results {
|
||||||
Ok(results) => {
|
Ok(results) => {
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
|
@ -796,7 +796,7 @@ impl ListingTrait for ConversationsListing {
|
||||||
threads.group_inner_sort_by(
|
threads.group_inner_sort_by(
|
||||||
&mut self.filtered_selection,
|
&mut self.filtered_selection,
|
||||||
self.sort,
|
self.sort,
|
||||||
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
&context.accounts[&self.cursor_pos.0].collection.envelopes,
|
||||||
);
|
);
|
||||||
self.new_cursor_pos.2 =
|
self.new_cursor_pos.2 =
|
||||||
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
|
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
|
||||||
|
@ -863,9 +863,9 @@ impl fmt::Display for ConversationsListing {
|
||||||
|
|
||||||
impl ConversationsListing {
|
impl ConversationsListing {
|
||||||
const DESCRIPTION: &'static str = "conversations listing";
|
const DESCRIPTION: &'static str = "conversations listing";
|
||||||
pub fn new(coordinates: (usize, MailboxHash)) -> Self {
|
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self {
|
||||||
ConversationsListing {
|
ConversationsListing {
|
||||||
cursor_pos: (0, 1, 0),
|
cursor_pos: (coordinates.0, 1, 0),
|
||||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||||
length: 0,
|
length: 0,
|
||||||
sort: (Default::default(), Default::default()),
|
sort: (Default::default(), Default::default()),
|
||||||
|
@ -899,7 +899,7 @@ impl ConversationsListing {
|
||||||
let thread = threads.thread_ref(hash);
|
let thread = threads.thread_ref(hash);
|
||||||
let mut tags = String::new();
|
let mut tags = String::new();
|
||||||
let mut colors = SmallVec::new();
|
let mut colors = SmallVec::new();
|
||||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
let backend_lck = context.accounts[&self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
for t in e.labels().iter() {
|
for t in e.labels().iter() {
|
||||||
|
@ -1006,7 +1006,7 @@ impl ConversationsListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
fn update_line(&mut self, context: &Context, thread_hash: ThreadHash) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
let thread = threads.thread_ref(thread_hash);
|
let thread = threads.thread_ref(thread_hash);
|
||||||
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
let thread_node_hash = threads.thread_group_iter(thread_hash).next().unwrap().1;
|
||||||
|
@ -1029,7 +1029,7 @@ impl ConversationsListing {
|
||||||
for (_, h) in threads.thread_group_iter(thread_hash) {
|
for (_, h) in threads.thread_group_iter(thread_hash) {
|
||||||
let env_hash = threads.thread_nodes()[&h].message().unwrap();
|
let env_hash = threads.thread_nodes()[&h].message().unwrap();
|
||||||
|
|
||||||
let envelope: &EnvelopeRef = &context.accounts[self.cursor_pos.0]
|
let envelope: &EnvelopeRef = &context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(env_hash);
|
.get_env(env_hash);
|
||||||
for addr in envelope.from().iter() {
|
for addr in envelope.from().iter() {
|
||||||
|
@ -1294,7 +1294,7 @@ impl Component for ConversationsListing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
if !account.collection.contains_key(&new_hash) {
|
if !account.collection.contains_key(&new_hash) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1312,11 +1312,15 @@ impl Component for ConversationsListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
self.view.process_event(
|
||||||
|
&mut UIEvent::EnvelopeRename(*old_hash, *new_hash),
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
if !account.collection.contains_key(&env_hash) {
|
if !account.collection.contains_key(&env_hash) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1334,8 +1338,10 @@ impl Component for ConversationsListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
self.view
|
||||||
|
.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
Action::SubSort(field, order) if !self.unfocused => {
|
Action::SubSort(field, order) if !self.unfocused => {
|
||||||
|
@ -1356,12 +1362,12 @@ impl Component for ConversationsListing {
|
||||||
/*
|
/*
|
||||||
self.sort = (*field, *order);
|
self.sort = (*field, *order);
|
||||||
if !self.filtered_selection.is_empty() {
|
if !self.filtered_selection.is_empty() {
|
||||||
let threads = &context.accounts[self.cursor_pos.0].collection.threads
|
let threads = &context.accounts[&self.cursor_pos.0].collection.threads
|
||||||
[&self.cursor_pos.1];
|
[&self.cursor_pos.1];
|
||||||
threads.vec_inner_sort_by(
|
threads.vec_inner_sort_by(
|
||||||
&mut self.filtered_selection,
|
&mut self.filtered_selection,
|
||||||
self.sort,
|
self.sort,
|
||||||
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
&context.accounts[&self.cursor_pos.0].collection.envelopes,
|
||||||
);
|
);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1372,7 +1378,7 @@ impl Component for ConversationsListing {
|
||||||
}
|
}
|
||||||
Action::ToggleThreadSnooze if !self.unfocused => {
|
Action::ToggleThreadSnooze if !self.unfocused => {
|
||||||
let thread = self.get_thread_under_cursor(self.cursor_pos.2);
|
let thread = self.get_thread_under_cursor(self.cursor_pos.2);
|
||||||
let account = &mut context.accounts[self.cursor_pos.0];
|
let account = &mut context.accounts[&self.cursor_pos.0];
|
||||||
account
|
account
|
||||||
.collection
|
.collection
|
||||||
.threads
|
.threads
|
||||||
|
@ -1411,16 +1417,16 @@ impl Component for ConversationsListing {
|
||||||
}
|
}
|
||||||
UIEvent::Action(ref action) => match action {
|
UIEvent::Action(ref action) => match action {
|
||||||
Action::Listing(Search(ref filter_term)) if !self.unfocused => {
|
Action::Listing(Search(ref filter_term)) if !self.unfocused => {
|
||||||
match context.accounts[self.cursor_pos.0].search(
|
match context.accounts[&self.cursor_pos.0].search(
|
||||||
filter_term,
|
filter_term,
|
||||||
self.sort,
|
self.sort,
|
||||||
self.cursor_pos.1,
|
self.cursor_pos.1,
|
||||||
) {
|
) {
|
||||||
Ok(job) => {
|
Ok(job) => {
|
||||||
let (chan, handle, job_id) = context.accounts[self.cursor_pos.0]
|
let (chan, handle, job_id) = context.accounts[&self.cursor_pos.0]
|
||||||
.job_executor
|
.job_executor
|
||||||
.spawn_specialized(job);
|
.spawn_specialized(job);
|
||||||
context.accounts[self.cursor_pos.0]
|
context.accounts[&self.cursor_pos.0]
|
||||||
.active_jobs
|
.active_jobs
|
||||||
.insert(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
.insert(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
||||||
self.search_job = Some((filter_term.to_string(), chan, job_id));
|
self.search_job = Some((filter_term.to_string(), chan, job_id));
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::components::utilities::PageMovement;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OfflineListing {
|
pub struct OfflineListing {
|
||||||
cursor_pos: (usize, MailboxHash),
|
cursor_pos: (AccountHash, MailboxHash),
|
||||||
_row_updates: SmallVec<[ThreadHash; 8]>,
|
_row_updates: SmallVec<[ThreadHash; 8]>,
|
||||||
_selection: HashMap<ThreadHash, bool>,
|
_selection: HashMap<ThreadHash, bool>,
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
|
@ -60,11 +60,11 @@ impl MailListingTrait for OfflineListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListingTrait for OfflineListing {
|
impl ListingTrait for OfflineListing {
|
||||||
fn coordinates(&self) -> (usize, MailboxHash) {
|
fn coordinates(&self) -> (AccountHash, MailboxHash) {
|
||||||
self.cursor_pos
|
self.cursor_pos
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, MailboxHash)) {
|
fn set_coordinates(&mut self, coordinates: (AccountHash, MailboxHash)) {
|
||||||
self.cursor_pos = coordinates;
|
self.cursor_pos = coordinates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ impl fmt::Display for OfflineListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OfflineListing {
|
impl OfflineListing {
|
||||||
pub fn new(cursor_pos: (usize, MailboxHash)) -> Self {
|
pub fn new(cursor_pos: (AccountHash, MailboxHash)) -> Self {
|
||||||
OfflineListing {
|
OfflineListing {
|
||||||
cursor_pos,
|
cursor_pos,
|
||||||
_row_updates: SmallVec::new(),
|
_row_updates: SmallVec::new(),
|
||||||
|
@ -137,7 +137,7 @@ impl Component for OfflineListing {
|
||||||
area,
|
area,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
let mut jobs: SmallVec<[_; 64]> = context.accounts[self.cursor_pos.0]
|
let mut jobs: SmallVec<[_; 64]> = context.accounts[&self.cursor_pos.0]
|
||||||
.active_jobs
|
.active_jobs
|
||||||
.iter()
|
.iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -163,7 +163,9 @@ impl Component for OfflineListing {
|
||||||
}
|
}
|
||||||
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||||
match event {
|
match event {
|
||||||
UIEvent::AccountStatusChange(idx) if *idx == self.cursor_pos.0 => self.dirty = true,
|
UIEvent::AccountStatusChange(account_hash) if *account_hash == self.cursor_pos.0 => {
|
||||||
|
self.dirty = true
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
|
|
@ -47,8 +47,8 @@ macro_rules! address_list {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PlainListing {
|
pub struct PlainListing {
|
||||||
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
||||||
cursor_pos: (usize, MailboxHash, usize),
|
cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
new_cursor_pos: (usize, MailboxHash, usize),
|
new_cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
length: usize,
|
length: usize,
|
||||||
sort: (SortField, SortOrder),
|
sort: (SortField, SortOrder),
|
||||||
subsort: (SortField, SortOrder),
|
subsort: (SortField, SortOrder),
|
||||||
|
@ -148,7 +148,7 @@ impl MailListingTrait for PlainListing {
|
||||||
|
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
match context.accounts[self.cursor_pos.0].load(self.cursor_pos.1) {
|
match context.accounts[&self.cursor_pos.0].load(self.cursor_pos.1) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let default_cell = {
|
let default_cell = {
|
||||||
|
@ -159,7 +159,7 @@ impl MailListingTrait for PlainListing {
|
||||||
ret
|
ret
|
||||||
};
|
};
|
||||||
let message: String =
|
let message: String =
|
||||||
context.accounts[self.cursor_pos.0][&self.cursor_pos.1].status();
|
context.accounts[&self.cursor_pos.0][&self.cursor_pos.1].status();
|
||||||
self.data_columns.columns[0] =
|
self.data_columns.columns[0] =
|
||||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
|
@ -175,18 +175,18 @@ impl MailListingTrait for PlainListing {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.local_collection = context.accounts[self.cursor_pos.0]
|
self.local_collection = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_mailbox(self.cursor_pos.1)
|
.get_mailbox(self.cursor_pos.1)
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
let env_lck = context.accounts[self.cursor_pos.0]
|
let env_lck = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.envelopes
|
.envelopes
|
||||||
.read()
|
.read()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.thread_node_hashes = context.accounts[self.cursor_pos.0]
|
self.thread_node_hashes = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_mailbox(self.cursor_pos.1)
|
.get_mailbox(self.cursor_pos.1)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -240,7 +240,7 @@ impl MailListingTrait for PlainListing {
|
||||||
context: &Context,
|
context: &Context,
|
||||||
items: Box<dyn Iterator<Item = ThreadHash>>,
|
items: Box<dyn Iterator<Item = ThreadHash>>,
|
||||||
) {
|
) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
let roots = items
|
let roots = items
|
||||||
.filter_map(|r| threads.groups[&r].root().map(|r| r.root))
|
.filter_map(|r| threads.groups[&r].root().map(|r| r.root))
|
||||||
|
@ -262,11 +262,11 @@ impl MailListingTrait for PlainListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListingTrait for PlainListing {
|
impl ListingTrait for PlainListing {
|
||||||
fn coordinates(&self) -> (usize, MailboxHash) {
|
fn coordinates(&self) -> (AccountHash, MailboxHash) {
|
||||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, MailboxHash)) {
|
fn set_coordinates(&mut self, coordinates: (AccountHash, MailboxHash)) {
|
||||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||||
self.unfocused = false;
|
self.unfocused = false;
|
||||||
self.view = MailView::default();
|
self.view = MailView::default();
|
||||||
|
@ -282,7 +282,7 @@ impl ListingTrait for PlainListing {
|
||||||
}
|
}
|
||||||
let i = self.get_env_under_cursor(idx, context);
|
let i = self.get_env_under_cursor(idx, context);
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let envelope: EnvelopeRef = account.collection.get_env(i);
|
let envelope: EnvelopeRef = account.collection.get_env(i);
|
||||||
|
|
||||||
let fg_color = if !envelope.is_seen() {
|
let fg_color = if !envelope.is_seen() {
|
||||||
|
@ -616,7 +616,7 @@ impl ListingTrait for PlainListing {
|
||||||
*v = false;
|
*v = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
match results {
|
match results {
|
||||||
Ok(results) => {
|
Ok(results) => {
|
||||||
for env_hash in results {
|
for env_hash in results {
|
||||||
|
@ -699,7 +699,7 @@ impl fmt::Display for PlainListing {
|
||||||
|
|
||||||
impl PlainListing {
|
impl PlainListing {
|
||||||
const DESCRIPTION: &'static str = "plain listing";
|
const DESCRIPTION: &'static str = "plain listing";
|
||||||
pub fn new(coordinates: (usize, MailboxHash)) -> Self {
|
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self {
|
||||||
PlainListing {
|
PlainListing {
|
||||||
cursor_pos: (0, 1, 0),
|
cursor_pos: (0, 1, 0),
|
||||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||||
|
@ -734,7 +734,7 @@ impl PlainListing {
|
||||||
fn make_entry_string(&self, e: EnvelopeRef, context: &Context) -> EntryStrings {
|
fn make_entry_string(&self, e: EnvelopeRef, context: &Context) -> EntryStrings {
|
||||||
let mut tags = String::new();
|
let mut tags = String::new();
|
||||||
let mut colors = SmallVec::new();
|
let mut colors = SmallVec::new();
|
||||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
let backend_lck = context.accounts[&self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
for t in e.labels().iter() {
|
for t in e.labels().iter() {
|
||||||
|
@ -773,7 +773,7 @@ impl PlainListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redraw_list(&mut self, context: &Context, iter: Box<dyn Iterator<Item = EnvelopeHash>>) {
|
fn redraw_list(&mut self, context: &Context, iter: Box<dyn Iterator<Item = EnvelopeHash>>) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let mailbox = &account[&self.cursor_pos.1];
|
let mailbox = &account[&self.cursor_pos.1];
|
||||||
|
|
||||||
self.order.clear();
|
self.order.clear();
|
||||||
|
@ -783,18 +783,18 @@ impl PlainListing {
|
||||||
let mut min_width = (0, 0, 0, 0, 0);
|
let mut min_width = (0, 0, 0, 0, 0);
|
||||||
|
|
||||||
for i in iter {
|
for i in iter {
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(i) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(i) {
|
||||||
debug!("key = {}", i);
|
debug!("key = {}", i);
|
||||||
debug!(
|
debug!(
|
||||||
"name = {} {}",
|
"name = {} {}",
|
||||||
mailbox.name(),
|
mailbox.name(),
|
||||||
context.accounts[self.cursor_pos.0].name()
|
context.accounts[&self.cursor_pos.0].name()
|
||||||
);
|
);
|
||||||
debug!("{:#?}", context.accounts);
|
debug!("{:#?}", context.accounts);
|
||||||
|
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
let envelope: EnvelopeRef = context.accounts[self.cursor_pos.0].collection.get_env(i);
|
let envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0].collection.get_env(i);
|
||||||
use melib::search::QueryTrait;
|
use melib::search::QueryTrait;
|
||||||
if let Some(filter_query) = mailbox_settings!(
|
if let Some(filter_query) = mailbox_settings!(
|
||||||
context[self.cursor_pos.0][&self.cursor_pos.1]
|
context[self.cursor_pos.0][&self.cursor_pos.1]
|
||||||
|
@ -858,19 +858,19 @@ impl PlainListing {
|
||||||
|
|
||||||
let columns = &mut self.data_columns.columns;
|
let columns = &mut self.data_columns.columns;
|
||||||
for ((idx, i), strings) in iter.enumerate().zip(rows) {
|
for ((idx, i), strings) in iter.enumerate().zip(rows) {
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(i) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(i) {
|
||||||
//debug!("key = {}", i);
|
//debug!("key = {}", i);
|
||||||
//debug!(
|
//debug!(
|
||||||
// "name = {} {}",
|
// "name = {} {}",
|
||||||
// mailbox.name(),
|
// mailbox.name(),
|
||||||
// context.accounts[self.cursor_pos.0].name()
|
// context.accounts[&self.cursor_pos.0].name()
|
||||||
//);
|
//);
|
||||||
//debug!("{:#?}", context.accounts);
|
//debug!("{:#?}", context.accounts);
|
||||||
|
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
||||||
let envelope: EnvelopeRef = context.accounts[self.cursor_pos.0].collection.get_env(i);
|
let envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0].collection.get_env(i);
|
||||||
let row_attr = if !envelope.is_seen() {
|
let row_attr = if !envelope.is_seen() {
|
||||||
if idx % 2 == 0 {
|
if idx % 2 == 0 {
|
||||||
self.color_cache.even_unseen
|
self.color_cache.even_unseen
|
||||||
|
@ -971,7 +971,7 @@ impl PlainListing {
|
||||||
for c in columns[4].row_iter(x..min_width.4, idx) {
|
for c in columns[4].row_iter(x..min_width.4, idx) {
|
||||||
columns[4][c].set_bg(row_attr.bg).set_attrs(row_attr.attrs);
|
columns[4][c].set_bg(row_attr.bg).set_attrs(row_attr.attrs);
|
||||||
}
|
}
|
||||||
if context.accounts[self.cursor_pos.0]
|
if context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(i)
|
.get_env(i)
|
||||||
.has_attachments()
|
.has_attachments()
|
||||||
|
@ -1019,7 +1019,7 @@ impl PlainListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_action(&mut self, context: &mut Context, env_hash: EnvelopeHash, a: &ListingAction) {
|
fn perform_action(&mut self, context: &mut Context, env_hash: EnvelopeHash, a: &ListingAction) {
|
||||||
let account = &mut context.accounts[self.cursor_pos.0];
|
let account = &mut context.accounts[&self.cursor_pos.0];
|
||||||
match {
|
match {
|
||||||
match a {
|
match a {
|
||||||
ListingAction::SetSeen => account.backend.write().unwrap().set_flags(
|
ListingAction::SetSeen => account.backend.write().unwrap().set_flags(
|
||||||
|
@ -1232,7 +1232,7 @@ impl Component for PlainListing {
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
if !account.collection.contains_key(new_hash)
|
if !account.collection.contains_key(new_hash)
|
||||||
|| !account
|
|| !account
|
||||||
.collection
|
.collection
|
||||||
|
@ -1257,11 +1257,13 @@ impl Component for PlainListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
self.view
|
||||||
|
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
if !account.collection.contains_key(env_hash)
|
if !account.collection.contains_key(env_hash)
|
||||||
|| !account
|
|| !account
|
||||||
.collection
|
.collection
|
||||||
|
@ -1274,8 +1276,10 @@ impl Component for PlainListing {
|
||||||
self.row_updates.push(*env_hash);
|
self.row_updates.push(*env_hash);
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
self.view
|
||||||
|
.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
@ -1300,16 +1304,16 @@ impl Component for PlainListing {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::Action(Action::Listing(Search(ref filter_term))) if !self.unfocused => {
|
UIEvent::Action(Action::Listing(Search(ref filter_term))) if !self.unfocused => {
|
||||||
match context.accounts[self.cursor_pos.0].search(
|
match context.accounts[&self.cursor_pos.0].search(
|
||||||
filter_term,
|
filter_term,
|
||||||
self.sort,
|
self.sort,
|
||||||
self.cursor_pos.1,
|
self.cursor_pos.1,
|
||||||
) {
|
) {
|
||||||
Ok(job) => {
|
Ok(job) => {
|
||||||
let (chan, handle, job_id) = context.accounts[self.cursor_pos.0]
|
let (chan, handle, job_id) = context.accounts[&self.cursor_pos.0]
|
||||||
.job_executor
|
.job_executor
|
||||||
.spawn_specialized(job);
|
.spawn_specialized(job);
|
||||||
context.accounts[self.cursor_pos.0]
|
context.accounts[&self.cursor_pos.0]
|
||||||
.insert_job(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
.insert_job(job_id, crate::conf::accounts::JobRequest::Search(handle));
|
||||||
self.search_job = Some((filter_term.to_string(), chan, job_id));
|
self.search_job = Some((filter_term.to_string(), chan, job_id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,8 +105,8 @@ macro_rules! row_attr {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ThreadListing {
|
pub struct ThreadListing {
|
||||||
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
/// (x, y, z): x is accounts, y is mailboxes, z is index inside a mailbox.
|
||||||
cursor_pos: (usize, MailboxHash, usize),
|
cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
new_cursor_pos: (usize, MailboxHash, usize),
|
new_cursor_pos: (AccountHash, MailboxHash, usize),
|
||||||
length: usize,
|
length: usize,
|
||||||
sort: (SortField, SortOrder),
|
sort: (SortField, SortOrder),
|
||||||
subsort: (SortField, SortOrder),
|
subsort: (SortField, SortOrder),
|
||||||
|
@ -179,7 +179,7 @@ impl MailListingTrait for ThreadListing {
|
||||||
|
|
||||||
// Get mailbox as a reference.
|
// Get mailbox as a reference.
|
||||||
//
|
//
|
||||||
match context.accounts[self.cursor_pos.0].load(self.cursor_pos.1) {
|
match context.accounts[&self.cursor_pos.0].load(self.cursor_pos.1) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let default_cell = {
|
let default_cell = {
|
||||||
|
@ -190,7 +190,7 @@ impl MailListingTrait for ThreadListing {
|
||||||
ret
|
ret
|
||||||
};
|
};
|
||||||
let message: String =
|
let message: String =
|
||||||
context.accounts[self.cursor_pos.0][&self.cursor_pos.1].status();
|
context.accounts[&self.cursor_pos.0][&self.cursor_pos.1].status();
|
||||||
self.data_columns.columns[0] =
|
self.data_columns.columns[0] =
|
||||||
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
|
@ -206,14 +206,14 @@ impl MailListingTrait for ThreadListing {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let threads = context.accounts[self.cursor_pos.0]
|
let threads = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_threads(self.cursor_pos.1);
|
.get_threads(self.cursor_pos.1);
|
||||||
let mut roots = threads.roots();
|
let mut roots = threads.roots();
|
||||||
threads.group_inner_sort_by(
|
threads.group_inner_sort_by(
|
||||||
&mut roots,
|
&mut roots,
|
||||||
self.sort,
|
self.sort,
|
||||||
&context.accounts[self.cursor_pos.0].collection.envelopes,
|
&context.accounts[&self.cursor_pos.0].collection.envelopes,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.redraw_threads_list(
|
self.redraw_threads_list(
|
||||||
|
@ -227,7 +227,7 @@ impl MailListingTrait for ThreadListing {
|
||||||
context: &Context,
|
context: &Context,
|
||||||
items: Box<dyn Iterator<Item = ThreadHash>>,
|
items: Box<dyn Iterator<Item = ThreadHash>>,
|
||||||
) {
|
) {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let threads = account.collection.get_threads(self.cursor_pos.1);
|
let threads = account.collection.get_threads(self.cursor_pos.1);
|
||||||
self.length = 0;
|
self.length = 0;
|
||||||
self.order.clear();
|
self.order.clear();
|
||||||
|
@ -414,10 +414,10 @@ impl MailListingTrait for ThreadListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ListingTrait for ThreadListing {
|
impl ListingTrait for ThreadListing {
|
||||||
fn coordinates(&self) -> (usize, MailboxHash) {
|
fn coordinates(&self) -> (AccountHash, MailboxHash) {
|
||||||
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
(self.new_cursor_pos.0, self.new_cursor_pos.1)
|
||||||
}
|
}
|
||||||
fn set_coordinates(&mut self, coordinates: (usize, MailboxHash)) {
|
fn set_coordinates(&mut self, coordinates: (AccountHash, MailboxHash)) {
|
||||||
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
|
||||||
self.unfocused = false;
|
self.unfocused = false;
|
||||||
self.view = None;
|
self.view = None;
|
||||||
|
@ -714,7 +714,7 @@ impl ListingTrait for ThreadListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
let env_hash = self.get_env_under_cursor(idx, context);
|
let env_hash = self.get_env_under_cursor(idx, context);
|
||||||
let envelope: EnvelopeRef = context.accounts[self.cursor_pos.0]
|
let envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(env_hash);
|
.get_env(env_hash);
|
||||||
|
|
||||||
|
@ -748,9 +748,9 @@ impl fmt::Display for ThreadListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThreadListing {
|
impl ThreadListing {
|
||||||
pub fn new(coordinates: (usize, MailboxHash)) -> Self {
|
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self {
|
||||||
ThreadListing {
|
ThreadListing {
|
||||||
cursor_pos: (0, 1, 0),
|
cursor_pos: (coordinates.0, 0, 0),
|
||||||
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
new_cursor_pos: (coordinates.0, coordinates.1, 0),
|
||||||
length: 0,
|
length: 0,
|
||||||
sort: (Default::default(), Default::default()),
|
sort: (Default::default(), Default::default()),
|
||||||
|
@ -779,7 +779,7 @@ impl ThreadListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
let env_hash = self.get_env_under_cursor(idx, context);
|
let env_hash = self.get_env_under_cursor(idx, context);
|
||||||
let envelope: EnvelopeRef = context.accounts[self.cursor_pos.0]
|
let envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(env_hash);
|
.get_env(env_hash);
|
||||||
|
|
||||||
|
@ -850,7 +850,7 @@ impl ThreadListing {
|
||||||
fn make_entry_string(&self, e: &Envelope, context: &Context) -> EntryStrings {
|
fn make_entry_string(&self, e: &Envelope, context: &Context) -> EntryStrings {
|
||||||
let mut tags = String::new();
|
let mut tags = String::new();
|
||||||
let mut colors: SmallVec<[_; 8]> = SmallVec::new();
|
let mut colors: SmallVec<[_; 8]> = SmallVec::new();
|
||||||
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
let backend_lck = context.accounts[&self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
for t in e.labels().iter() {
|
for t in e.labels().iter() {
|
||||||
|
@ -913,12 +913,12 @@ impl ThreadListing {
|
||||||
self.rows.iter().skip(start).take(end - start + 1)
|
self.rows.iter().skip(start).take(end - start + 1)
|
||||||
{
|
{
|
||||||
let idx = *idx;
|
let idx = *idx;
|
||||||
if !context.accounts[self.cursor_pos.0].contains_key(*env_hash) {
|
if !context.accounts[&self.cursor_pos.0].contains_key(*env_hash) {
|
||||||
//debug!("key = {}", root_env_hash);
|
//debug!("key = {}", root_env_hash);
|
||||||
//debug!(
|
//debug!(
|
||||||
// "name = {} {}",
|
// "name = {} {}",
|
||||||
// account[&self.cursor_pos.1].name(),
|
// account[&self.cursor_pos.1].name(),
|
||||||
// context.accounts[self.cursor_pos.0].name()
|
// context.accounts[&self.cursor_pos.0].name()
|
||||||
//);
|
//);
|
||||||
//debug!("{:#?}", context.accounts);
|
//debug!("{:#?}", context.accounts);
|
||||||
|
|
||||||
|
@ -1109,7 +1109,7 @@ impl Component for ThreadListing {
|
||||||
if self.length == 0 {
|
if self.length == 0 {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
let envelope: EnvelopeRef = account
|
let envelope: EnvelopeRef = account
|
||||||
.collection
|
.collection
|
||||||
.get_env(self.get_env_under_cursor(idx, context));
|
.get_env(self.get_env_under_cursor(idx, context));
|
||||||
|
@ -1169,11 +1169,9 @@ impl Component for ThreadListing {
|
||||||
self.view = Some(MailView::new(coordinates, None, None, context));
|
self.view = Some(MailView::new(coordinates, None, None, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.view.as_mut().unwrap().draw(
|
if let Some(v) = self.view.as_mut() {
|
||||||
grid,
|
v.draw(grid, (set_y(upper_left, mid + 1), bottom_right), context);
|
||||||
(set_y(upper_left, mid + 1), bottom_right),
|
}
|
||||||
context,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
}
|
}
|
||||||
|
@ -1207,7 +1205,7 @@ impl Component for ThreadListing {
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
if !account.collection.contains_key(&new_hash) {
|
if !account.collection.contains_key(&new_hash) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1219,9 +1217,14 @@ impl Component for ThreadListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view.as_mut().map(|c| {
|
if self.unfocused {
|
||||||
c.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context)
|
if let Some(v) = self.view.as_mut() {
|
||||||
});
|
v.process_event(
|
||||||
|
&mut UIEvent::EnvelopeRename(*old_hash, *new_hash),
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRemove(ref env_hash, _) => {
|
UIEvent::EnvelopeRemove(ref env_hash, _) => {
|
||||||
if self.order.contains_key(env_hash) {
|
if self.order.contains_key(env_hash) {
|
||||||
|
@ -1230,7 +1233,7 @@ impl Component for ThreadListing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||||
let account = &context.accounts[self.cursor_pos.0];
|
let account = &context.accounts[&self.cursor_pos.0];
|
||||||
if !account.collection.contains_key(env_hash) {
|
if !account.collection.contains_key(env_hash) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1240,9 +1243,11 @@ impl Component for ThreadListing {
|
||||||
|
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
||||||
self.view
|
if self.unfocused {
|
||||||
.as_mut()
|
if let Some(v) = self.view.as_mut() {
|
||||||
.map(|c| c.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context));
|
v.process_event(&mut UIEvent::EnvelopeUpdate(*env_hash), context);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UIEvent::ChangeMode(UIMode::Normal) => {
|
UIEvent::ChangeMode(UIMode::Normal) => {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
|
|
|
@ -271,7 +271,7 @@ impl StatusPanel {
|
||||||
Some(2),
|
Some(2),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i, a) in context.accounts.iter().enumerate() {
|
for (i, (_h, a)) in context.accounts.iter().enumerate() {
|
||||||
for x in 2..(120 - 1) {
|
for x in 2..(120 - 1) {
|
||||||
set_and_join_box(&mut self.content, (x, 12 + i * 10), BoxBoundary::Horizontal);
|
set_and_join_box(&mut self.content, (x, 12 + i * 10), BoxBoundary::Horizontal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl ViewMode {
|
||||||
/// menus
|
/// menus
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct MailView {
|
pub struct MailView {
|
||||||
coordinates: (usize, MailboxHash, EnvelopeHash),
|
coordinates: (AccountHash, MailboxHash, EnvelopeHash),
|
||||||
pager: Pager,
|
pager: Pager,
|
||||||
subview: Option<Box<dyn Component>>,
|
subview: Option<Box<dyn Component>>,
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
|
@ -152,7 +152,7 @@ impl fmt::Display for MailView {
|
||||||
impl MailView {
|
impl MailView {
|
||||||
const DESCRIPTION: &'static str = "view mail";
|
const DESCRIPTION: &'static str = "view mail";
|
||||||
pub fn new(
|
pub fn new(
|
||||||
coordinates: (usize, MailboxHash, EnvelopeHash),
|
coordinates: (AccountHash, MailboxHash, EnvelopeHash),
|
||||||
pager: Option<Pager>,
|
pager: Option<Pager>,
|
||||||
subview: Option<Box<dyn Component>>,
|
subview: Option<Box<dyn Component>>,
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
|
@ -185,7 +185,7 @@ impl MailView {
|
||||||
|
|
||||||
fn init_futures(&mut self, context: &mut Context) {
|
fn init_futures(&mut self, context: &mut Context) {
|
||||||
debug!("init_futures");
|
debug!("init_futures");
|
||||||
let account = &mut context.accounts[self.coordinates.0];
|
let account = &mut context.accounts[&self.coordinates.0];
|
||||||
if debug!(account.contains_key(self.coordinates.2)) {
|
if debug!(account.contains_key(self.coordinates.2)) {
|
||||||
{
|
{
|
||||||
match account
|
match account
|
||||||
|
@ -372,7 +372,7 @@ impl MailView {
|
||||||
|
|
||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_coordinates: (usize, MailboxHash, EnvelopeHash),
|
new_coordinates: (AccountHash, MailboxHash, EnvelopeHash),
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
) {
|
) {
|
||||||
self.coordinates = new_coordinates;
|
self.coordinates = new_coordinates;
|
||||||
|
@ -553,7 +553,7 @@ impl Component for MailView {
|
||||||
let bottom_right = bottom_right!(area);
|
let bottom_right = bottom_right!(area);
|
||||||
|
|
||||||
let y: usize = {
|
let y: usize = {
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
if !account.contains_key(self.coordinates.2) {
|
if !account.contains_key(self.coordinates.2) {
|
||||||
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
||||||
* arrive */
|
* arrive */
|
||||||
|
@ -966,7 +966,7 @@ impl Component for MailView {
|
||||||
if *id == s.id() =>
|
if *id == s.id() =>
|
||||||
{
|
{
|
||||||
if let Some(results) = results.downcast_ref::<Vec<Card>>() {
|
if let Some(results) = results.downcast_ref::<Vec<Card>>() {
|
||||||
let account = &mut context.accounts[self.coordinates.0];
|
let account = &mut context.accounts[&self.coordinates.0];
|
||||||
{
|
{
|
||||||
for card in results.iter() {
|
for card in results.iter() {
|
||||||
account.address_book.add_card(card.clone());
|
account.address_book.add_card(card.clone());
|
||||||
|
@ -1074,7 +1074,7 @@ impl Component for MailView {
|
||||||
key == shortcuts[MailView::DESCRIPTION]["add_addresses_to_contacts"]
|
key == shortcuts[MailView::DESCRIPTION]["add_addresses_to_contacts"]
|
||||||
) =>
|
) =>
|
||||||
{
|
{
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
|
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
|
||||||
|
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
|
@ -1285,7 +1285,7 @@ impl Component for MailView {
|
||||||
self.coordinates.2 = new_hash;
|
self.coordinates.2 = new_hash;
|
||||||
}
|
}
|
||||||
UIEvent::Action(View(ViewAction::SaveAttachment(a_i, ref path))) => {
|
UIEvent::Action(View(ViewAction::SaveAttachment(a_i, ref path))) => {
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
if !account.contains_key(self.coordinates.2) {
|
if !account.contains_key(self.coordinates.2) {
|
||||||
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
||||||
* arrive */
|
* arrive */
|
||||||
|
@ -1445,7 +1445,7 @@ impl Component for MailView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIEvent::Action(MailingListAction(ref e)) => {
|
UIEvent::Action(MailingListAction(ref e)) => {
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
if !account.contains_key(self.coordinates.2) {
|
if !account.contains_key(self.coordinates.2) {
|
||||||
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
/* The envelope has been renamed or removed, so wait for the appropriate event to
|
||||||
* arrive */
|
* arrive */
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub struct EnvelopeView {
|
||||||
mode: ViewMode,
|
mode: ViewMode,
|
||||||
wrapper: EnvelopeWrapper,
|
wrapper: EnvelopeWrapper,
|
||||||
|
|
||||||
account_pos: usize,
|
account_hash: AccountHash,
|
||||||
cmd_buf: String,
|
cmd_buf: String,
|
||||||
id: ComponentId,
|
id: ComponentId,
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ impl EnvelopeView {
|
||||||
wrapper: EnvelopeWrapper,
|
wrapper: EnvelopeWrapper,
|
||||||
pager: Option<Pager>,
|
pager: Option<Pager>,
|
||||||
subview: Option<Box<dyn Component>>,
|
subview: Option<Box<dyn Component>>,
|
||||||
account_pos: usize,
|
account_hash: AccountHash,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
EnvelopeView {
|
EnvelopeView {
|
||||||
pager,
|
pager,
|
||||||
|
@ -78,7 +78,7 @@ impl EnvelopeView {
|
||||||
dirty: true,
|
dirty: true,
|
||||||
mode: ViewMode::Normal,
|
mode: ViewMode::Normal,
|
||||||
wrapper,
|
wrapper,
|
||||||
account_pos,
|
account_hash,
|
||||||
cmd_buf: String::with_capacity(4),
|
cmd_buf: String::with_capacity(4),
|
||||||
id: ComponentId::new_v4(),
|
id: ComponentId::new_v4(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub struct ThreadView {
|
||||||
expanded_pos: usize,
|
expanded_pos: usize,
|
||||||
new_expanded_pos: usize,
|
new_expanded_pos: usize,
|
||||||
reversed: bool,
|
reversed: bool,
|
||||||
coordinates: (usize, MailboxHash, usize),
|
coordinates: (AccountHash, MailboxHash, usize),
|
||||||
thread_group: ThreadHash,
|
thread_group: ThreadHash,
|
||||||
mailview: MailView,
|
mailview: MailView,
|
||||||
show_mailview: bool,
|
show_mailview: bool,
|
||||||
|
@ -66,7 +66,7 @@ impl ThreadView {
|
||||||
* context: current context
|
* context: current context
|
||||||
*/
|
*/
|
||||||
pub fn new(
|
pub fn new(
|
||||||
coordinates: (usize, MailboxHash, usize),
|
coordinates: (AccountHash, MailboxHash, usize),
|
||||||
thread_group: ThreadHash,
|
thread_group: ThreadHash,
|
||||||
expanded_hash: Option<ThreadNodeHash>,
|
expanded_hash: Option<ThreadNodeHash>,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
|
@ -160,7 +160,7 @@ impl ThreadView {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initiate(&mut self, expanded_hash: Option<ThreadNodeHash>, context: &Context) {
|
fn initiate(&mut self, expanded_hash: Option<ThreadNodeHash>, context: &Context) {
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
let threads = account.collection.get_threads(self.coordinates.1);
|
let threads = account.collection.get_threads(self.coordinates.1);
|
||||||
|
|
||||||
if !threads.groups.contains_key(&self.thread_group) {
|
if !threads.groups.contains_key(&self.thread_group) {
|
||||||
|
@ -197,7 +197,7 @@ impl ThreadView {
|
||||||
let mut highlight_reply_subjects: Vec<Option<usize>> =
|
let mut highlight_reply_subjects: Vec<Option<usize>> =
|
||||||
Vec::with_capacity(self.entries.len());
|
Vec::with_capacity(self.entries.len());
|
||||||
for e in &mut self.entries {
|
for e in &mut self.entries {
|
||||||
let envelope: EnvelopeRef = context.accounts[self.coordinates.0]
|
let envelope: EnvelopeRef = context.accounts[&self.coordinates.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(e.msg_hash);
|
.get_env(e.msg_hash);
|
||||||
let thread_node = &threads.thread_nodes()[&e.index.1];
|
let thread_node = &threads.thread_nodes()[&e.index.1];
|
||||||
|
@ -274,7 +274,7 @@ impl ThreadView {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
let envelope: EnvelopeRef = context.accounts[self.coordinates.0]
|
let envelope: EnvelopeRef = context.accounts[&self.coordinates.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(e.msg_hash);
|
.get_env(e.msg_hash);
|
||||||
if envelope.has_attachments() {
|
if envelope.has_attachments() {
|
||||||
|
@ -357,7 +357,7 @@ impl ThreadView {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
let envelope: EnvelopeRef = context.accounts[self.coordinates.0]
|
let envelope: EnvelopeRef = context.accounts[&self.coordinates.0]
|
||||||
.collection
|
.collection
|
||||||
.get_env(e.msg_hash);
|
.get_env(e.msg_hash);
|
||||||
if envelope.has_attachments() {
|
if envelope.has_attachments() {
|
||||||
|
@ -647,7 +647,7 @@ impl ThreadView {
|
||||||
/* First draw the thread subject on the first row */
|
/* First draw the thread subject on the first row */
|
||||||
let y = if self.dirty {
|
let y = if self.dirty {
|
||||||
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
let threads = account.collection.get_threads(self.coordinates.1);
|
let threads = account.collection.get_threads(self.coordinates.1);
|
||||||
let thread_root = threads
|
let thread_root = threads
|
||||||
.thread_group_iter(self.thread_group)
|
.thread_group_iter(self.thread_group)
|
||||||
|
@ -748,7 +748,7 @@ impl ThreadView {
|
||||||
/* First draw the thread subject on the first row */
|
/* First draw the thread subject on the first row */
|
||||||
let y = {
|
let y = {
|
||||||
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
let threads = account.collection.get_threads(self.coordinates.1);
|
let threads = account.collection.get_threads(self.coordinates.1);
|
||||||
let thread_root = threads
|
let thread_root = threads
|
||||||
.thread_group_iter(self.thread_group)
|
.thread_group_iter(self.thread_group)
|
||||||
|
@ -1103,7 +1103,7 @@ impl Component for ThreadView {
|
||||||
self.set_dirty(true);
|
self.set_dirty(true);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
for e in self.entries.iter_mut() {
|
for e in self.entries.iter_mut() {
|
||||||
if e.msg_hash == *old_hash {
|
if e.msg_hash == *old_hash {
|
||||||
e.msg_hash = *new_hash;
|
e.msg_hash = *new_hash;
|
||||||
|
@ -1118,7 +1118,7 @@ impl Component for ThreadView {
|
||||||
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
.process_event(&mut UIEvent::EnvelopeRename(*old_hash, *new_hash), context);
|
||||||
}
|
}
|
||||||
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
UIEvent::EnvelopeUpdate(ref env_hash) => {
|
||||||
let account = &context.accounts[self.coordinates.0];
|
let account = &context.accounts[&self.coordinates.0];
|
||||||
for e in self.entries.iter_mut() {
|
for e in self.entries.iter_mut() {
|
||||||
if e.msg_hash == *env_hash {
|
if e.msg_hash == *env_hash {
|
||||||
let seen: bool = account.collection.get_env(*env_hash).is_seen();
|
let seen: bool = account.collection.get_env(*env_hash).is_seen();
|
||||||
|
|
|
@ -1666,8 +1666,8 @@ impl Component for Tabbed {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::Action(Tab(NewDraft(account_idx, ref draft))) => {
|
UIEvent::Action(Tab(NewDraft(account_hash, ref draft))) => {
|
||||||
let mut composer = Composer::new(*account_idx, context);
|
let mut composer = Composer::new(*account_hash, context);
|
||||||
if let Some(draft) = draft {
|
if let Some(draft) = draft {
|
||||||
composer.set_draft(draft.clone());
|
composer.set_draft(draft.clone());
|
||||||
}
|
}
|
||||||
|
@ -1692,8 +1692,8 @@ impl Component for Tabbed {
|
||||||
self.help_curr_views = children_maps;
|
self.help_curr_views = children_maps;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
UIEvent::Action(Tab(Edit(account_pos, msg))) => {
|
UIEvent::Action(Tab(Edit(account_hash, msg))) => {
|
||||||
let composer = match Composer::edit(*account_pos, *msg, context) {
|
let composer = match Composer::edit(*account_hash, *msg, context) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
context.replies.push_back(UIEvent::Notification(
|
context.replies.push_back(UIEvent::Notification(
|
||||||
|
@ -1704,7 +1704,7 @@ impl Component for Tabbed {
|
||||||
log(
|
log(
|
||||||
format!(
|
format!(
|
||||||
"Failed to open envelope {}: {}",
|
"Failed to open envelope {}: {}",
|
||||||
context.accounts[*account_pos]
|
context.accounts[&*account_hash]
|
||||||
.collection
|
.collection
|
||||||
.get_env(*msg)
|
.get_env(*msg)
|
||||||
.message_id_display(),
|
.message_id_display(),
|
||||||
|
|
45
src/conf.rs
45
src/conf.rs
|
@ -62,6 +62,7 @@ use melib::error::*;
|
||||||
|
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
use indexmap::IndexMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
|
@ -78,8 +79,8 @@ macro_rules! split_command {
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! mailbox_acc_settings {
|
macro_rules! mailbox_acc_settings {
|
||||||
($context:ident[$account_idx:expr].$setting:ident.$field:ident) => {{
|
($context:ident[$account_hash:expr].$setting:ident.$field:ident) => {{
|
||||||
$context.accounts[$account_idx]
|
$context.accounts[&$account_hash]
|
||||||
.settings
|
.settings
|
||||||
.conf_override
|
.conf_override
|
||||||
.$setting
|
.$setting
|
||||||
|
@ -90,14 +91,14 @@ macro_rules! mailbox_acc_settings {
|
||||||
}
|
}
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! mailbox_settings {
|
macro_rules! mailbox_settings {
|
||||||
($context:ident[$account_idx:expr][$mailbox_path:expr].$setting:ident.$field:ident) => {{
|
($context:ident[$account_hash:expr][$mailbox_path:expr].$setting:ident.$field:ident) => {{
|
||||||
$context.accounts[$account_idx][$mailbox_path]
|
$context.accounts[&$account_hash][$mailbox_path]
|
||||||
.conf
|
.conf
|
||||||
.conf_override
|
.conf_override
|
||||||
.$setting
|
.$setting
|
||||||
.$field
|
.$field
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.or($context.accounts[$account_idx]
|
.or($context.accounts[&$account_hash]
|
||||||
.settings
|
.settings
|
||||||
.conf_override
|
.conf_override
|
||||||
.$setting
|
.$setting
|
||||||
|
@ -163,7 +164,7 @@ pub struct FileAccount {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
subscribed_mailboxes: Vec<String>,
|
subscribed_mailboxes: Vec<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
mailboxes: HashMap<String, FileMailboxConf>,
|
mailboxes: IndexMap<String, FileMailboxConf>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
search_backend: SearchBackend,
|
search_backend: SearchBackend,
|
||||||
#[serde(default = "false_val")]
|
#[serde(default = "false_val")]
|
||||||
|
@ -174,11 +175,11 @@ pub struct FileAccount {
|
||||||
pub conf_override: MailUIConf,
|
pub conf_override: MailUIConf,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
#[serde(deserialize_with = "extra_settings")]
|
#[serde(deserialize_with = "extra_settings")]
|
||||||
pub extra: HashMap<String, String>, /* use custom deserializer to convert any given value (eg bool, number, etc) to string */
|
pub extra: IndexMap<String, String>, /* use custom deserializer to convert any given value (eg bool, number, etc) to string */
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileAccount {
|
impl FileAccount {
|
||||||
pub fn mailboxes(&self) -> &HashMap<String, FileMailboxConf> {
|
pub fn mailboxes(&self) -> &IndexMap<String, FileMailboxConf> {
|
||||||
&self.mailboxes
|
&self.mailboxes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ impl FileAccount {
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct FileSettings {
|
pub struct FileSettings {
|
||||||
pub accounts: HashMap<String, FileAccount>,
|
pub accounts: IndexMap<String, FileAccount>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub pager: PagerSettings,
|
pub pager: PagerSettings,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -211,7 +212,7 @@ pub struct FileSettings {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub terminal: TerminalSettings,
|
pub terminal: TerminalSettings,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub plugins: HashMap<String, Plugin>,
|
pub plugins: IndexMap<String, Plugin>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub log: LogSettings,
|
pub log: LogSettings,
|
||||||
}
|
}
|
||||||
|
@ -221,7 +222,7 @@ pub struct AccountConf {
|
||||||
pub account: AccountSettings,
|
pub account: AccountSettings,
|
||||||
pub conf: FileAccount,
|
pub conf: FileAccount,
|
||||||
pub conf_override: MailUIConf,
|
pub conf_override: MailUIConf,
|
||||||
pub mailbox_confs: HashMap<String, FileMailboxConf>,
|
pub mailbox_confs: IndexMap<String, FileMailboxConf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountConf {
|
impl AccountConf {
|
||||||
|
@ -261,7 +262,7 @@ impl From<FileAccount> for AccountConf {
|
||||||
subscribed_mailboxes: x.subscribed_mailboxes.clone(),
|
subscribed_mailboxes: x.subscribed_mailboxes.clone(),
|
||||||
mailboxes,
|
mailboxes,
|
||||||
manual_refresh: x.manual_refresh,
|
manual_refresh: x.manual_refresh,
|
||||||
extra: x.extra.clone(),
|
extra: x.extra.clone().into_iter().collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mailbox_confs = x.mailboxes.clone();
|
let mailbox_confs = x.mailboxes.clone();
|
||||||
|
@ -422,7 +423,7 @@ impl FileSettings {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(k, v)| (k, v.mailbox_conf))
|
.map(|(k, v)| (k, v.mailbox_conf))
|
||||||
.collect(),
|
.collect(),
|
||||||
extra,
|
extra: extra.into_iter().collect(),
|
||||||
};
|
};
|
||||||
backends.validate_config(&lowercase_format, &s)?;
|
backends.validate_config(&lowercase_format, &s)?;
|
||||||
}
|
}
|
||||||
|
@ -433,7 +434,7 @@ impl FileSettings {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize)]
|
#[derive(Debug, Clone, Default, Serialize)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub accounts: HashMap<String, AccountConf>,
|
pub accounts: IndexMap<String, AccountConf>,
|
||||||
pub pager: PagerSettings,
|
pub pager: PagerSettings,
|
||||||
pub listing: ListingSettings,
|
pub listing: ListingSettings,
|
||||||
pub notifications: NotificationsSettings,
|
pub notifications: NotificationsSettings,
|
||||||
|
@ -442,14 +443,14 @@ pub struct Settings {
|
||||||
pub composing: ComposingSettings,
|
pub composing: ComposingSettings,
|
||||||
pub pgp: PGPSettings,
|
pub pgp: PGPSettings,
|
||||||
pub terminal: TerminalSettings,
|
pub terminal: TerminalSettings,
|
||||||
pub plugins: HashMap<String, Plugin>,
|
pub plugins: IndexMap<String, Plugin>,
|
||||||
pub log: LogSettings,
|
pub log: LogSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
pub fn new() -> Result<Settings> {
|
pub fn new() -> Result<Settings> {
|
||||||
let fs = FileSettings::new()?;
|
let fs = FileSettings::new()?;
|
||||||
let mut s: HashMap<String, AccountConf> = HashMap::new();
|
let mut s: IndexMap<String, AccountConf> = IndexMap::new();
|
||||||
|
|
||||||
for (id, x) in fs.accounts {
|
for (id, x) in fs.accounts {
|
||||||
let mut ac = AccountConf::from(x);
|
let mut ac = AccountConf::from(x);
|
||||||
|
@ -490,7 +491,7 @@ impl Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Settings {
|
Ok(Settings {
|
||||||
accounts: HashMap::new(),
|
accounts: IndexMap::new(),
|
||||||
pager: fs.pager,
|
pager: fs.pager,
|
||||||
listing: fs.listing,
|
listing: fs.listing,
|
||||||
notifications: fs.notifications,
|
notifications: fs.notifications,
|
||||||
|
@ -583,10 +584,10 @@ mod deserializers {
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use indexmap::IndexMap;
|
||||||
pub(in crate::conf) fn extra_settings<'de, D>(
|
pub(in crate::conf) fn extra_settings<'de, D>(
|
||||||
deserializer: D,
|
deserializer: D,
|
||||||
) -> std::result::Result<HashMap<String, String>, D::Error>
|
) -> std::result::Result<IndexMap<String, String>, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
|
@ -596,7 +597,7 @@ mod deserializers {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Wrapper(#[serde(deserialize_with = "any_of")] String);
|
struct Wrapper(#[serde(deserialize_with = "any_of")] String);
|
||||||
|
|
||||||
let v = <HashMap<String, Wrapper>>::deserialize(deserializer)?;
|
let v = <IndexMap<String, Wrapper>>::deserialize(deserializer)?;
|
||||||
Ok(v.into_iter().map(|(k, Wrapper(v))| (k, v)).collect())
|
Ok(v.into_iter().map(|(k, Wrapper(v))| (k, v)).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -869,6 +870,10 @@ mod dotaddressable {
|
||||||
for HashMap<K, V>
|
for HashMap<K, V>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
impl<K: DotAddressable + std::cmp::Eq + std::hash::Hash, V: DotAddressable> DotAddressable
|
||||||
|
for IndexMap<K, V>
|
||||||
|
{
|
||||||
|
}
|
||||||
impl<K: DotAddressable + std::cmp::Eq + std::hash::Hash> DotAddressable for HashSet<K> {}
|
impl<K: DotAddressable + std::cmp::Eq + std::hash::Hash> DotAddressable for HashSet<K> {}
|
||||||
|
|
||||||
impl DotAddressable for LogSettings {
|
impl DotAddressable for LogSettings {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
use super::{AccountConf, FileMailboxConf};
|
use super::{AccountConf, FileMailboxConf};
|
||||||
use crate::jobs::{JobChannel, JobExecutor, JobId, JoinHandle};
|
use crate::jobs::{JobChannel, JobExecutor, JobId, JoinHandle};
|
||||||
|
use indexmap::IndexMap;
|
||||||
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
||||||
use melib::backends::*;
|
use melib::backends::*;
|
||||||
use melib::email::*;
|
use melib::email::*;
|
||||||
|
@ -141,12 +142,11 @@ impl MailboxEntry {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
pub index: usize,
|
|
||||||
name: String,
|
name: String,
|
||||||
hash: AccountHash,
|
hash: AccountHash,
|
||||||
pub is_online: Result<()>,
|
pub is_online: Result<()>,
|
||||||
pub last_online_request: std::time::Instant,
|
pub last_online_request: std::time::Instant,
|
||||||
pub(crate) mailbox_entries: HashMap<MailboxHash, MailboxEntry>,
|
pub(crate) mailbox_entries: IndexMap<MailboxHash, MailboxEntry>,
|
||||||
pub(crate) mailboxes_order: Vec<MailboxHash>,
|
pub(crate) mailboxes_order: Vec<MailboxHash>,
|
||||||
tree: Vec<MailboxNode>,
|
tree: Vec<MailboxNode>,
|
||||||
sent_mailbox: Option<MailboxHash>,
|
sent_mailbox: Option<MailboxHash>,
|
||||||
|
@ -351,7 +351,6 @@ pub struct MailboxNode {
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
index: usize,
|
|
||||||
hash: AccountHash,
|
hash: AccountHash,
|
||||||
name: String,
|
name: String,
|
||||||
mut settings: AccountConf,
|
mut settings: AccountConf,
|
||||||
|
@ -410,7 +409,6 @@ impl Account {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut ret = Account {
|
let mut ret = Account {
|
||||||
index,
|
|
||||||
hash,
|
hash,
|
||||||
name,
|
name,
|
||||||
is_online: if !backend.capabilities().is_remote {
|
is_online: if !backend.capabilities().is_remote {
|
||||||
|
@ -451,8 +449,8 @@ impl Account {
|
||||||
self.backend.read().unwrap().mailboxes()?
|
self.backend.read().unwrap().mailboxes()?
|
||||||
};
|
};
|
||||||
self.backend_capabilities = self.backend.read().unwrap().capabilities();
|
self.backend_capabilities = self.backend.read().unwrap().capabilities();
|
||||||
let mut mailbox_entries: HashMap<MailboxHash, MailboxEntry> =
|
let mut mailbox_entries: IndexMap<MailboxHash, MailboxEntry> =
|
||||||
HashMap::with_capacity_and_hasher(ref_mailboxes.len(), Default::default());
|
IndexMap::with_capacity_and_hasher(ref_mailboxes.len(), Default::default());
|
||||||
let mut mailboxes_order: Vec<MailboxHash> = Vec::with_capacity(ref_mailboxes.len());
|
let mut mailboxes_order: Vec<MailboxHash> = Vec::with_capacity(ref_mailboxes.len());
|
||||||
|
|
||||||
let mut sent_mailbox = None;
|
let mut sent_mailbox = None;
|
||||||
|
@ -818,7 +816,7 @@ impl Account {
|
||||||
.ignore
|
.ignore
|
||||||
.is_true()
|
.is_true()
|
||||||
{
|
{
|
||||||
return Some(UIEvent::MailboxUpdate((self.index, mailbox_hash)));
|
return Some(UIEvent::MailboxUpdate((self.hash, mailbox_hash)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let thread = {
|
let thread = {
|
||||||
|
@ -833,10 +831,10 @@ impl Account {
|
||||||
.thread_ref(thread)
|
.thread_ref(thread)
|
||||||
.snoozed()
|
.snoozed()
|
||||||
{
|
{
|
||||||
return Some(UIEvent::MailboxUpdate((self.index, mailbox_hash)));
|
return Some(UIEvent::MailboxUpdate((self.hash, mailbox_hash)));
|
||||||
}
|
}
|
||||||
if is_seen || is_draft {
|
if is_seen || is_draft {
|
||||||
return Some(UIEvent::MailboxUpdate((self.index, mailbox_hash)));
|
return Some(UIEvent::MailboxUpdate((self.hash, mailbox_hash)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(Notification(
|
return Some(Notification(
|
||||||
|
@ -1201,7 +1199,7 @@ impl Account {
|
||||||
});
|
});
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
||||||
self.index,
|
self.hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
))))
|
))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1441,7 +1439,7 @@ impl Account {
|
||||||
)?;
|
)?;
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxCreate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxCreate((
|
||||||
self.index,
|
self.hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
))))
|
))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1515,7 +1513,7 @@ impl Account {
|
||||||
)?;
|
)?;
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxDelete((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxDelete((
|
||||||
self.index,
|
self.hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
))))
|
))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1664,7 +1662,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange(
|
.send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange(
|
||||||
self.index,
|
self.hash,
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1769,7 +1767,7 @@ impl Account {
|
||||||
});
|
});
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
||||||
self.index,
|
self.hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
))))
|
))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1802,7 +1800,7 @@ impl Account {
|
||||||
});
|
});
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
||||||
self.index,
|
self.hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
))))
|
))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1819,15 +1817,13 @@ impl Account {
|
||||||
{
|
{
|
||||||
for f in updated_mailboxes {
|
for f in updated_mailboxes {
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((self.hash, f))))
|
||||||
self.index, f,
|
|
||||||
))))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
.send(ThreadEvent::UIEvent(UIEvent::MailboxUpdate((
|
||||||
self.index,
|
self.hash,
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
))))
|
))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1837,7 +1833,7 @@ impl Account {
|
||||||
if let Some(is_online) = is_online {
|
if let Some(is_online) = is_online {
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange(
|
.send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange(
|
||||||
self.index,
|
self.hash,
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if is_online.is_ok() {
|
if is_online.is_ok() {
|
||||||
|
@ -1893,7 +1889,7 @@ impl Account {
|
||||||
self.is_online = Ok(());
|
self.is_online = Ok(());
|
||||||
self.sender
|
self.sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange(
|
.send(ThreadEvent::UIEvent(UIEvent::AccountStatusChange(
|
||||||
self.index,
|
self.hash,
|
||||||
)))
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -2156,7 +2152,7 @@ impl IndexMut<&MailboxHash> for Account {
|
||||||
|
|
||||||
fn build_mailboxes_order(
|
fn build_mailboxes_order(
|
||||||
tree: &mut Vec<MailboxNode>,
|
tree: &mut Vec<MailboxNode>,
|
||||||
mailbox_entries: &HashMap<MailboxHash, MailboxEntry>,
|
mailbox_entries: &IndexMap<MailboxHash, MailboxEntry>,
|
||||||
mailboxes_order: &mut Vec<MailboxHash>,
|
mailboxes_order: &mut Vec<MailboxHash>,
|
||||||
) {
|
) {
|
||||||
tree.clear();
|
tree.clear();
|
||||||
|
@ -2165,7 +2161,7 @@ fn build_mailboxes_order(
|
||||||
if f.ref_mailbox.parent().is_none() {
|
if f.ref_mailbox.parent().is_none() {
|
||||||
fn rec(
|
fn rec(
|
||||||
h: MailboxHash,
|
h: MailboxHash,
|
||||||
mailbox_entries: &HashMap<MailboxHash, MailboxEntry>,
|
mailbox_entries: &IndexMap<MailboxHash, MailboxEntry>,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
) -> MailboxNode {
|
) -> MailboxNode {
|
||||||
let mut node = MailboxNode {
|
let mut node = MailboxNode {
|
||||||
|
|
88
src/state.rs
88
src/state.rs
|
@ -34,8 +34,8 @@ use melib::backends::{AccountHash, MailboxHash, NotifyFn};
|
||||||
|
|
||||||
use crate::jobs::JobExecutor;
|
use crate::jobs::JobExecutor;
|
||||||
use crossbeam::channel::{unbounded, Receiver, Sender};
|
use crossbeam::channel::{unbounded, Receiver, Sender};
|
||||||
|
use indexmap::IndexMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
@ -101,8 +101,7 @@ impl InputHandler {
|
||||||
|
|
||||||
/// A context container for loaded settings, accounts, UI changes, etc.
|
/// A context container for loaded settings, accounts, UI changes, etc.
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub accounts: Vec<Account>,
|
pub accounts: IndexMap<AccountHash, Account>,
|
||||||
pub account_hashes: HashMap<AccountHash, usize>,
|
|
||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
|
|
||||||
pub runtime_settings: Settings,
|
pub runtime_settings: Settings,
|
||||||
|
@ -135,7 +134,7 @@ impl Context {
|
||||||
self.input_thread.restore();
|
self.input_thread.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
|
pub fn is_online_idx(&mut self, account_pos: usize) -> Result<()> {
|
||||||
let Context {
|
let Context {
|
||||||
ref mut accounts,
|
ref mut accounts,
|
||||||
ref mut replies,
|
ref mut replies,
|
||||||
|
@ -155,15 +154,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
accounts[account_pos].watch();
|
accounts[account_pos].watch();
|
||||||
|
|
||||||
replies.push_back(UIEvent::AccountStatusChange(account_pos));
|
replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ret.is_ok() != was_online {
|
if ret.is_ok() != was_online {
|
||||||
replies.push_back(UIEvent::AccountStatusChange(account_pos));
|
replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash()));
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_online(&mut self, account_hash: AccountHash) -> Result<()> {
|
||||||
|
let idx = self.accounts.get_index_of(&account_hash).unwrap();
|
||||||
|
self.is_online_idx(idx)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn work_controller(&self) -> &WorkController {
|
pub fn work_controller(&self) -> &WorkController {
|
||||||
&self.work_controller
|
&self.work_controller
|
||||||
}
|
}
|
||||||
|
@ -257,20 +261,13 @@ impl State {
|
||||||
let cols = termsize.0 as usize;
|
let cols = termsize.0 as usize;
|
||||||
let rows = termsize.1 as usize;
|
let rows = termsize.1 as usize;
|
||||||
|
|
||||||
let mut account_hashes = HashMap::with_capacity_and_hasher(1, Default::default());
|
|
||||||
let work_controller = WorkController::new(sender.clone());
|
let work_controller = WorkController::new(sender.clone());
|
||||||
let job_executor = Arc::new(JobExecutor::new(sender.clone()));
|
let job_executor = Arc::new(JobExecutor::new(sender.clone()));
|
||||||
let accounts: Vec<Account> = {
|
let accounts = {
|
||||||
let mut file_accs = settings
|
settings
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.collect::<Vec<(&String, &AccountConf)>>();
|
.map(|(n, a_s)| {
|
||||||
file_accs.sort_by(|a, b| a.0.cmp(&b.0));
|
|
||||||
|
|
||||||
file_accs
|
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(index, (n, a_s))| {
|
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
let account_hash = {
|
let account_hash = {
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
@ -279,9 +276,7 @@ impl State {
|
||||||
hasher.write(n.as_bytes());
|
hasher.write(n.as_bytes());
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
};
|
};
|
||||||
account_hashes.insert(account_hash, index);
|
|
||||||
Account::new(
|
Account::new(
|
||||||
index,
|
|
||||||
account_hash,
|
account_hash,
|
||||||
n.to_string(),
|
n.to_string(),
|
||||||
a_s.clone(),
|
a_s.clone(),
|
||||||
|
@ -301,6 +296,7 @@ impl State {
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<Account>>>()?
|
.collect::<Result<Vec<Account>>>()?
|
||||||
};
|
};
|
||||||
|
let accounts = accounts.into_iter().map(|acc| (acc.hash(), acc)).collect();
|
||||||
|
|
||||||
let timer = {
|
let timer = {
|
||||||
let sender = sender.clone();
|
let sender = sender.clone();
|
||||||
|
@ -343,7 +339,6 @@ impl State {
|
||||||
|
|
||||||
context: Context {
|
context: Context {
|
||||||
accounts,
|
accounts,
|
||||||
account_hashes,
|
|
||||||
settings: settings.clone(),
|
settings: settings.clone(),
|
||||||
runtime_settings: settings,
|
runtime_settings: settings,
|
||||||
dirty_areas: VecDeque::with_capacity(5),
|
dirty_areas: VecDeque::with_capacity(5),
|
||||||
|
@ -378,7 +373,7 @@ impl State {
|
||||||
if !s.context.accounts[i].backend_capabilities.is_remote {
|
if !s.context.accounts[i].backend_capabilities.is_remote {
|
||||||
s.context.accounts[i].watch();
|
s.context.accounts[i].watch();
|
||||||
}
|
}
|
||||||
if s.context.is_online(i).is_ok() && s.context.accounts[i].is_empty() {
|
if s.context.is_online_idx(i).is_ok() && s.context.accounts[i].is_empty() {
|
||||||
//return Err(MeliError::new(format!(
|
//return Err(MeliError::new(format!(
|
||||||
// "Account {} has no mailboxes configured.",
|
// "Account {} has no mailboxes configured.",
|
||||||
// s.context.accounts[i].name()
|
// s.context.accounts[i].name()
|
||||||
|
@ -397,29 +392,30 @@ impl State {
|
||||||
pub fn refresh_event(&mut self, event: RefreshEvent) {
|
pub fn refresh_event(&mut self, event: RefreshEvent) {
|
||||||
let account_hash = event.account_hash();
|
let account_hash = event.account_hash();
|
||||||
let mailbox_hash = event.mailbox_hash();
|
let mailbox_hash = event.mailbox_hash();
|
||||||
if let Some(&idxa) = self.context.account_hashes.get(&account_hash) {
|
if self.context.accounts[&account_hash]
|
||||||
if self.context.accounts[idxa]
|
.mailbox_entries
|
||||||
.mailbox_entries
|
.contains_key(&mailbox_hash)
|
||||||
.contains_key(&mailbox_hash)
|
{
|
||||||
|
if self.context.accounts[&account_hash]
|
||||||
|
.load(mailbox_hash)
|
||||||
|
.is_err()
|
||||||
{
|
{
|
||||||
if self.context.accounts[idxa].load(mailbox_hash).is_err() {
|
self.context.replies.push_back(UIEvent::from(event));
|
||||||
self.context.replies.push_back(UIEvent::from(event));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
let Context {
|
||||||
let Context {
|
ref mut accounts, ..
|
||||||
ref mut accounts, ..
|
} = &mut self.context;
|
||||||
} = &mut self.context;
|
|
||||||
|
|
||||||
if let Some(notification) = accounts[idxa].reload(event, mailbox_hash) {
|
if let Some(notification) = accounts[&account_hash].reload(event, mailbox_hash) {
|
||||||
if let UIEvent::Notification(_, _, _) = notification {
|
if let UIEvent::Notification(_, _, _) = notification {
|
||||||
self.rcv_event(UIEvent::MailboxUpdate((idxa, mailbox_hash)));
|
self.rcv_event(UIEvent::MailboxUpdate((account_hash, mailbox_hash)));
|
||||||
}
|
|
||||||
self.rcv_event(notification);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let melib::backends::RefreshEventKind::Failure(err) = event.kind() {
|
|
||||||
debug!(err);
|
|
||||||
}
|
}
|
||||||
|
self.rcv_event(notification);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let melib::backends::RefreshEventKind::Failure(err) = event.kind() {
|
||||||
|
debug!(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -838,7 +834,7 @@ impl State {
|
||||||
if let Some(account) = self
|
if let Some(account) = self
|
||||||
.context
|
.context
|
||||||
.accounts
|
.accounts
|
||||||
.iter_mut()
|
.values_mut()
|
||||||
.find(|a| a.name() == account_name)
|
.find(|a| a.name() == account_name)
|
||||||
{
|
{
|
||||||
match account.mailbox_operation(op) {
|
match account.mailbox_operation(op) {
|
||||||
|
@ -868,7 +864,7 @@ impl State {
|
||||||
.context
|
.context
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.position(|acc| acc.name() == account_name)
|
.position(|(_, acc)| acc.name() == account_name)
|
||||||
{
|
{
|
||||||
a
|
a
|
||||||
} else {
|
} else {
|
||||||
|
@ -937,7 +933,7 @@ impl State {
|
||||||
.context
|
.context
|
||||||
.accounts
|
.accounts
|
||||||
.iter()
|
.iter()
|
||||||
.position(|a| a.name() == account_name)
|
.position(|(_h, a)| a.name() == account_name)
|
||||||
{
|
{
|
||||||
self.context.replies.push_back(UIEvent::StatusEvent(
|
self.context.replies.push_back(UIEvent::StatusEvent(
|
||||||
StatusEvent::UpdateStatus(format!(
|
StatusEvent::UpdateStatus(format!(
|
||||||
|
@ -1033,9 +1029,7 @@ impl State {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UIEvent::WorkerProgress(account_hash, mailbox_hash) => {
|
UIEvent::WorkerProgress(account_hash, mailbox_hash) => {
|
||||||
if let Some(&account_idx) = self.context.account_hashes.get(&account_hash) {
|
let _ = self.context.accounts[&account_hash].load(mailbox_hash);
|
||||||
let _ = self.context.accounts[account_idx].load(mailbox_hash);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UIEvent::ChangeMode(m) => {
|
UIEvent::ChangeMode(m) => {
|
||||||
|
@ -1169,7 +1163,7 @@ impl State {
|
||||||
pub fn check_accounts(&mut self) {
|
pub fn check_accounts(&mut self) {
|
||||||
let mut ctr = 0;
|
let mut ctr = 0;
|
||||||
for i in 0..self.context.accounts.len() {
|
for i in 0..self.context.accounts.len() {
|
||||||
if self.context.is_online(i).is_ok() {
|
if self.context.is_online_idx(i).is_ok() {
|
||||||
ctr += 1;
|
ctr += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,10 +114,10 @@ pub enum UIEvent {
|
||||||
Notification(Option<String>, String, Option<NotificationType>),
|
Notification(Option<String>, String, Option<NotificationType>),
|
||||||
Action(Action),
|
Action(Action),
|
||||||
StatusEvent(StatusEvent),
|
StatusEvent(StatusEvent),
|
||||||
MailboxUpdate((usize, MailboxHash)), // (account_idx, mailbox_idx)
|
MailboxUpdate((AccountHash, MailboxHash)), // (account_idx, mailbox_idx)
|
||||||
MailboxDelete((usize, MailboxHash)),
|
MailboxDelete((AccountHash, MailboxHash)),
|
||||||
MailboxCreate((usize, MailboxHash)),
|
MailboxCreate((AccountHash, MailboxHash)),
|
||||||
AccountStatusChange(usize),
|
AccountStatusChange(AccountHash),
|
||||||
ComponentKill(Uuid),
|
ComponentKill(Uuid),
|
||||||
WorkerProgress(AccountHash, MailboxHash),
|
WorkerProgress(AccountHash, MailboxHash),
|
||||||
StartupCheck(MailboxHash),
|
StartupCheck(MailboxHash),
|
||||||
|
|
Loading…
Reference in New Issue