Wrap {AccountHash,MailboxHash} type aliases in New Types wrappers

imap-lemonade
Manos Pitsidianakis 2022-09-03 23:35:24 +03:00
parent 808bdf75a1
commit 9fcf88b494
19 changed files with 123 additions and 131 deletions

View File

@ -257,6 +257,27 @@ impl Backends {
}
}
#[derive(
Debug, Serialize, Deserialize, Clone, PartialOrd, Ord, Default, Copy, Hash, PartialEq, Eq,
)]
pub struct AccountHash(pub u64);
#[derive(
Debug, Serialize, Deserialize, Clone, PartialOrd, Ord, Default, Copy, Hash, PartialEq, Eq,
)]
pub struct MailboxHash(pub u64);
impl std::fmt::Display for AccountHash {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "AccountHash({})", self.0)
}
}
impl std::fmt::Display for MailboxHash {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MailboxHash({})", self.0)
}
}
#[derive(Debug, Clone)]
pub enum BackendEvent {
Notice {
@ -589,8 +610,6 @@ pub trait BackendMailbox: Debug {
fn count(&self) -> Result<(usize, usize)>;
}
pub type AccountHash = u64;
pub type MailboxHash = u64;
pub type Mailbox = Box<dyn BackendMailbox + Send + Sync>;
impl Clone for Mailbox {

View File

@ -505,7 +505,7 @@ impl MailBackend for ImapType {
let account_hash = uid_store.account_hash;
main_conn_lck.add_refresh_event(RefreshEvent {
account_hash,
mailbox_hash: 0,
mailbox_hash: MailboxHash(0),
kind: RefreshEventKind::Failure(err.clone()),
});
return Err(err);
@ -938,7 +938,7 @@ impl MailBackend for ImapType {
}
let ret: Result<()> = ImapResponse::try_from(response.as_slice())?.into();
ret?;
let new_hash = get_path_hash!(path.as_str());
let new_hash = MailboxHash(get_path_hash!(path.as_str()));
uid_store.mailboxes.lock().await.clear();
Ok((new_hash, new_mailbox_fut?.await.map_err(|err| MeliError::new(format!("Mailbox create was succesful (returned `{}`) but listing mailboxes afterwards returned `{}`", String::from_utf8_lossy(&response), err)))?))
}))
@ -1075,7 +1075,7 @@ impl MailBackend for ImapType {
.read_response(&mut response, RequiredResponses::empty())
.await?;
}
let new_hash = get_path_hash!(new_path.as_str());
let new_hash = MailboxHash(get_path_hash!(new_path.as_str()));
let ret: Result<()> = ImapResponse::try_from(response.as_slice())?.into();
ret?;
uid_store.mailboxes.lock().await.clear();
@ -1322,7 +1322,7 @@ impl ImapType {
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(s.name.as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
let account_name = Arc::new(s.name().to_string());
let uid_store: Arc<UIDStore> = Arc::new(UIDStore {
@ -1475,7 +1475,7 @@ impl ImapType {
debug!("parse error for {:?}", l);
}
}
mailboxes.retain(|_, v| v.hash != 0);
mailboxes.retain(|_, v| v.hash.0 != 0);
conn.send_command(b"LSUB \"\" \"*\"").await?;
conn.read_response(&mut res, RequiredResponses::LSUB_REQUIRED)
.await?;

View File

@ -177,7 +177,7 @@ mod sqlite3_m {
.prepare("SELECT MAX(uid) FROM envelopes WHERE mailbox_hash = ?1;")?;
let mut ret: Vec<UID> = stmt
.query_map(sqlite3::params![mailbox_hash as i64], |row| {
.query_map(sqlite3::params![mailbox_hash.0 as i64], |row| {
Ok(row.get(0).map(|i: Sqlite3UID| i as UID)?)
})?
.collect::<std::result::Result<_, _>>()?;
@ -199,7 +199,7 @@ mod sqlite3_m {
"SELECT uidvalidity, flags, highestmodseq FROM mailbox WHERE mailbox_hash = ?1;",
)?;
let mut ret = stmt.query_map(sqlite3::params![mailbox_hash as i64], |row| {
let mut ret = stmt.query_map(sqlite3::params![mailbox_hash.0 as i64], |row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
row.get(1)?,
@ -265,7 +265,7 @@ mod sqlite3_m {
self.connection
.execute(
"DELETE FROM mailbox WHERE mailbox_hash = ?1",
sqlite3::params![mailbox_hash as i64],
sqlite3::params![mailbox_hash.0 as i64],
)
.chain_err_summary(|| {
format!(
@ -277,7 +277,7 @@ mod sqlite3_m {
if let Some(Ok(highestmodseq)) = select_response.highestmodseq {
self.connection.execute(
"INSERT OR IGNORE INTO mailbox (uidvalidity, flags, highestmodseq, mailbox_hash) VALUES (?1, ?2, ?3, ?4)",
sqlite3::params![select_response.uidvalidity as Sqlite3UID, select_response.flags.1.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join("\0").as_bytes(), highestmodseq, mailbox_hash as i64],
sqlite3::params![select_response.uidvalidity as Sqlite3UID, select_response.flags.1.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join("\0").as_bytes(), highestmodseq, mailbox_hash.0 as i64],
)
.chain_err_summary(|| {
format!(
@ -292,7 +292,7 @@ mod sqlite3_m {
sqlite3::params![
select_response.uidvalidity as Sqlite3UID,
select_response.flags.1.iter().map(|s| s.as_str()).collect::<Vec<&str>>().join("\0").as_bytes(),
mailbox_hash as i64
mailbox_hash.0 as i64
],
)
.chain_err_summary(|| {
@ -328,7 +328,7 @@ mod sqlite3_m {
.join("\0")
.as_bytes(),
highestmodseq,
mailbox_hash as i64
mailbox_hash.0 as i64
],
)
.chain_err_summary(|| {
@ -350,7 +350,7 @@ mod sqlite3_m {
.collect::<Vec<&str>>()
.join("\0")
.as_bytes(),
mailbox_hash as i64
mailbox_hash.0 as i64
],
)
.chain_err_summary(|| {
@ -374,7 +374,7 @@ mod sqlite3_m {
)?;
let ret: Vec<(UID, Envelope, Option<ModSequence>)> = stmt
.query_map(sqlite3::params![mailbox_hash as i64], |row| {
.query_map(sqlite3::params![mailbox_hash.0 as i64], |row| {
Ok((
row.get(0).map(|i: Sqlite3UID| i as UID)?,
row.get(1)?,
@ -452,7 +452,7 @@ mod sqlite3_m {
max_uid = std::cmp::max(max_uid, *uid);
tx.execute(
"INSERT OR REPLACE INTO envelopes (hash, uid, mailbox_hash, modsequence, envelope) VALUES (?1, ?2, ?3, ?4, ?5)",
sqlite3::params![envelope.hash() as i64, *uid as Sqlite3UID, mailbox_hash as i64, modseq, &envelope],
sqlite3::params![envelope.hash() as i64, *uid as Sqlite3UID, mailbox_hash.0 as i64, modseq, &envelope],
).chain_err_summary(|| format!("Could not insert envelope {} {} in header_cache of account {}", envelope.message_id(), envelope.hash(), uid_store.account_name))?;
}
}
@ -486,7 +486,7 @@ mod sqlite3_m {
hash_index_lck.remove(&env_hash);
tx.execute(
"DELETE FROM envelopes WHERE mailbox_hash = ?1 AND uid = ?2;",
sqlite3::params![mailbox_hash as i64, *uid as Sqlite3UID],
sqlite3::params![mailbox_hash.0 as i64, *uid as Sqlite3UID],
)
.chain_err_summary(|| {
format!(
@ -502,7 +502,7 @@ mod sqlite3_m {
let mut ret: Vec<Envelope> = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, *uid as Sqlite3UID],
sqlite3::params![mailbox_hash.0 as i64, *uid as Sqlite3UID],
|row| Ok(row.get(0)?),
)?
.collect::<std::result::Result<_, _>>()?;
@ -512,7 +512,7 @@ mod sqlite3_m {
env.labels_mut().extend(tags.iter().map(|t| tag_hash!(t)));
tx.execute(
"UPDATE envelopes SET envelope = ?1 WHERE mailbox_hash = ?2 AND uid = ?3;",
sqlite3::params![&env, mailbox_hash as i64, *uid as Sqlite3UID],
sqlite3::params![&env, mailbox_hash.0 as i64, *uid as Sqlite3UID],
)
.chain_err_summary(|| {
format!(
@ -556,7 +556,7 @@ mod sqlite3_m {
let x = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, uid as Sqlite3UID],
sqlite3::params![mailbox_hash.0 as i64, uid as Sqlite3UID],
|row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
@ -575,7 +575,7 @@ mod sqlite3_m {
let x = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, env_hash as i64],
sqlite3::params![mailbox_hash.0 as i64, env_hash as i64],
|row| {
Ok((
row.get(0).map(|u: Sqlite3UID| u as UID)?,
@ -612,7 +612,7 @@ mod sqlite3_m {
)?;
let x = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, uid as Sqlite3UID],
sqlite3::params![mailbox_hash.0 as i64, uid as Sqlite3UID],
|row| Ok(row.get(0)?),
)?
.collect::<std::result::Result<_, _>>()?;
@ -624,7 +624,7 @@ mod sqlite3_m {
)?;
let x = stmt
.query_map(
sqlite3::params![mailbox_hash as i64, env_hash as i64],
sqlite3::params![mailbox_hash.0 as i64, env_hash as i64],
|row| Ok(row.get(0)?),
)?
.collect::<std::result::Result<_, _>>()?;

View File

@ -478,7 +478,7 @@ pub fn list_mailbox_result(input: &[u8]) -> IResult<&[u8], ImapMailbox> {
}
}
f.imap_path = path.to_string();
f.hash = get_path_hash!(&f.imap_path);
f.hash = MailboxHash(get_path_hash!(&f.imap_path));
f.path = if separator == b'/' {
f.imap_path.clone()
} else {
@ -486,7 +486,7 @@ pub fn list_mailbox_result(input: &[u8]) -> IResult<&[u8], ImapMailbox> {
};
f.name = if let Some(pos) = f.imap_path.as_bytes().iter().rposition(|&c| c == separator)
{
f.parent = Some(get_path_hash!(&f.imap_path[..pos]));
f.parent = Some(MailboxHash(get_path_hash!(&f.imap_path[..pos])));
f.imap_path[pos + 1..].to_string()
} else {
f.imap_path.clone()
@ -1561,7 +1561,9 @@ pub struct StatusResponse {
pub fn status_response(input: &[u8]) -> IResult<&[u8], StatusResponse> {
let (input, _) = tag("* STATUS ")(input)?;
let (input, mailbox) = take_until(" (")(input)?;
let mailbox = mailbox_token(mailbox).map(|(_, m)| get_path_hash!(m)).ok();
let mailbox = mailbox_token(mailbox)
.map(|(_, m)| MailboxHash(get_path_hash!(m)))
.ok();
let (input, _) = tag(" (")(input)?;
let (input, result) = permutation((
opt(preceded(

View File

@ -138,8 +138,11 @@ impl MaildirMailbox {
settings: &AccountSettings,
) -> Result<Self> {
let pathbuf = PathBuf::from(&path);
let mut h = DefaultHasher::new();
pathbuf.hash(&mut h);
let hash = {
let mut h = DefaultHasher::new();
pathbuf.hash(&mut h);
MailboxHash(h.finish())
};
/* Check if mailbox path (Eg `INBOX/Lists/luddites`) is included in the subscribed
* mailboxes in user configuration */
@ -159,7 +162,7 @@ impl MaildirMailbox {
};
let ret = MaildirMailbox {
hash: h.finish(),
hash,
name: file_name,
path: fname.unwrap().to_path_buf(),
fs_path: pathbuf,

View File

@ -220,7 +220,7 @@ impl MailBackend for MaildirType {
let account_hash = {
let mut hasher = DefaultHasher::default();
hasher.write(self.name.as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
let sender = self.event_consumer.clone();
@ -327,7 +327,7 @@ impl MailBackend for MaildirType {
let account_hash = {
let mut hasher = DefaultHasher::default();
hasher.write(self.name.as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
let root_path = self.path.to_path_buf();
watcher.watch(&root_path, RecursiveMode::Recursive).unwrap();
@ -377,7 +377,7 @@ impl MailBackend for MaildirType {
}
};
}
let mailbox_hash = get_path_hash!(pathbuf);
let mailbox_hash = MailboxHash(get_path_hash!(pathbuf));
let file_name = pathbuf
.as_path()
.strip_prefix(&root_path)
@ -418,7 +418,7 @@ impl MailBackend for MaildirType {
/* Update */
DebouncedEvent::NoticeWrite(pathbuf) | DebouncedEvent::Write(pathbuf) => {
debug!("DebouncedEvent::Write(path = {:?}", &pathbuf);
let mailbox_hash = get_path_hash!(pathbuf);
let mailbox_hash = MailboxHash(get_path_hash!(pathbuf));
let mut hash_indexes_lock = hash_indexes.lock().unwrap();
let index_lock =
&mut hash_indexes_lock.entry(mailbox_hash).or_default();
@ -495,7 +495,7 @@ impl MailBackend for MaildirType {
/* Remove */
DebouncedEvent::NoticeRemove(pathbuf) | DebouncedEvent::Remove(pathbuf) => {
debug!("DebouncedEvent::Remove(path = {:?}", pathbuf);
let mailbox_hash = get_path_hash!(pathbuf);
let mailbox_hash = MailboxHash(get_path_hash!(pathbuf));
let mut hash_indexes_lock = hash_indexes.lock().unwrap();
let index_lock = hash_indexes_lock.entry(mailbox_hash).or_default();
let hash: EnvelopeHash = if let Some((k, _)) =
@ -549,9 +549,9 @@ impl MailBackend for MaildirType {
/* Envelope hasn't changed */
DebouncedEvent::Rename(src, dest) => {
debug!("DebouncedEvent::Rename(src = {:?}, dest = {:?})", src, dest);
let mailbox_hash = get_path_hash!(src);
let mailbox_hash = MailboxHash(get_path_hash!(src));
let dest_mailbox = {
let dest_mailbox = get_path_hash!(dest);
let dest_mailbox = MailboxHash(get_path_hash!(dest));
if dest_mailbox == mailbox_hash {
None
} else {
@ -787,7 +787,7 @@ impl MailBackend for MaildirType {
/* Maybe a re-read should be triggered here just to be safe.
(sender)(account_hash, BackendEvent::Refresh(RefreshEvent {
account_hash,
mailbox_hash: get_path_hash!(dest),
mailbox_hash: MailboxHash(get_path_hash!(dest)),
kind: Rescan,
}));
*/
@ -1011,7 +1011,7 @@ impl MailBackend for MaildirType {
.map(|item| *item.0)
});
let mailbox_hash = get_path_hash!(&path);
let mailbox_hash = MailboxHash(get_path_hash!(&path));
if let Some(parent) = parent {
self.mailboxes
.entry(parent)

View File

@ -981,7 +981,7 @@ impl MailBackend for MboxType {
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(self.account_name.as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
let mailboxes = self.mailboxes.clone();
let mailbox_index = self.mailbox_index.clone();
@ -1002,7 +1002,7 @@ impl MailBackend for MboxType {
Ok(event) => match event {
/* Update */
DebouncedEvent::NoticeWrite(pathbuf) | DebouncedEvent::Write(pathbuf) => {
let mailbox_hash = get_path_hash!(&pathbuf);
let mailbox_hash = MailboxHash(get_path_hash!(&pathbuf));
let file = match std::fs::OpenOptions::new()
.read(true)
.write(true)
@ -1064,7 +1064,7 @@ impl MailBackend for MboxType {
.values()
.any(|f| f.fs_path == pathbuf)
{
let mailbox_hash = get_path_hash!(&pathbuf);
let mailbox_hash = MailboxHash(get_path_hash!(&pathbuf));
(sender)(
account_hash,
BackendEvent::Refresh(RefreshEvent {
@ -1081,7 +1081,7 @@ impl MailBackend for MboxType {
}
DebouncedEvent::Rename(src, dest) => {
if mailboxes.lock().unwrap().values().any(|f| f.fs_path == src) {
let mailbox_hash = get_path_hash!(&src);
let mailbox_hash = MailboxHash(get_path_hash!(&src));
(sender)(
account_hash,
BackendEvent::Refresh(RefreshEvent {
@ -1265,7 +1265,7 @@ impl MboxType {
.file_name()
.map(|f| f.to_string_lossy().into())
.unwrap_or_default();
let hash = get_path_hash!(&ret.path);
let hash = MailboxHash(get_path_hash!(&ret.path));
let read_only = if let Ok(metadata) = std::fs::metadata(&ret.path) {
metadata.permissions().readonly()
@ -1303,7 +1303,7 @@ impl MboxType {
/* Look for other mailboxes */
for (k, f) in s.mailboxes.iter() {
if let Some(path_str) = f.extra.get("path") {
let hash = get_path_hash!(path_str);
let hash = MailboxHash(get_path_hash!(path_str));
let pathbuf: PathBuf = path_str.into();
if !pathbuf.exists() || pathbuf.is_dir() {
return Err(MeliError::new(format!(

View File

@ -573,12 +573,12 @@ impl NntpType {
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(s.name.as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
let account_name = Arc::new(s.name().to_string());
let mut mailboxes = HashMap::default();
for (k, _f) in s.mailboxes.iter() {
let mailbox_hash = get_path_hash!(&k);
let mailbox_hash = MailboxHash(get_path_hash!(&k));
mailboxes.insert(
mailbox_hash,
NntpMailbox {
@ -645,7 +645,7 @@ impl NntpType {
if s.len() != 3 {
continue;
}
let mailbox_hash = get_path_hash!(&s[0]);
let mailbox_hash = MailboxHash(get_path_hash!(&s[0]));
mailboxes_lck.entry(mailbox_hash).and_modify(|m| {
*m.high_watermark.lock().unwrap() = usize::from_str(s[1]).unwrap_or(0);
*m.low_watermark.lock().unwrap() = usize::from_str(s[2]).unwrap_or(0);

View File

@ -367,7 +367,7 @@ impl NotmuchDb {
let hash = {
let mut h = DefaultHasher::new();
k.hash(&mut h);
h.finish()
MailboxHash(h.finish())
};
mailboxes.insert(
hash,
@ -396,7 +396,7 @@ impl NotmuchDb {
let account_hash = {
let mut hasher = DefaultHasher::new();
hasher.write(s.name().as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
Ok(Box::new(NotmuchDb {
lib,
@ -533,7 +533,7 @@ impl MailBackend for NotmuchDb {
database: Arc<DbConnection>,
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
mailbox_index: Arc<RwLock<HashMap<EnvelopeHash, SmallVec<[MailboxHash; 16]>>>>,
mailboxes: Arc<RwLock<HashMap<u64, NotmuchMailbox>>>,
mailboxes: Arc<RwLock<HashMap<MailboxHash, NotmuchMailbox>>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
iter: std::vec::IntoIter<CString>,
}

View File

@ -151,7 +151,7 @@ impl Composer {
pager.set_show_scrollbar(true);
Composer {
reply_context: None,
account_hash: 0,
account_hash: AccountHash(0),
cursor: Cursor::Headers,
pager,
draft: Draft::default(),

View File

@ -613,6 +613,7 @@ pub struct Listing {
cursor_pos: (usize, MenuEntryCursor),
menu_cursor_pos: (usize, MenuEntryCursor),
menu_content: CellBuffer,
menu_content_dirty: bool,
menu_scrollbar_show_timer: crate::jobs::Timer,
show_menu_scrollbar: ShowMenuScrollbar,
startup_checks_rate: RateLimit,
@ -698,7 +699,8 @@ impl Component for Listing {
match self.component {
ListingComponent::Offline(_) => {}
_ => {
self.component = Offline(OfflineListing::new((account_hash, 0)));
self.component =
Offline(OfflineListing::new((account_hash, MailboxHash(0))));
}
}
}
@ -720,7 +722,8 @@ impl Component for Listing {
match self.component {
ListingComponent::Offline(_) => {}
_ => {
self.component = Offline(OfflineListing::new((account_hash, 0)));
self.component =
Offline(OfflineListing::new((account_hash, MailboxHash(0))));
}
}
}
@ -743,6 +746,7 @@ impl Component for Listing {
*account_settings!(context[account_hash].listing.sidebar_divider);
self.sidebar_divider_theme = conf::value(context, "mail.sidebar_divider");
self.menu_content = CellBuffer::new_with_context(0, 0, None, context);
self.menu_content_dirty = true;
self.set_dirty(true);
}
UIEvent::Timer(n) if *n == self.menu_scrollbar_show_timer.id() => {
@ -750,6 +754,7 @@ impl Component for Listing {
self.show_menu_scrollbar = ShowMenuScrollbar::False;
self.set_dirty(true);
self.menu_content.empty();
self.menu_content_dirty = true;
}
return true;
}
@ -775,41 +780,10 @@ impl Component for Listing {
if self.cursor_pos.0 == account_index {
self.change_account(context);
} else {
let previous_collapsed_mailboxes: BTreeSet<MailboxHash> = self.accounts
[account_index]
.entries
.iter()
.filter_map(|e| {
if e.collapsed {
Some(e.mailbox_hash)
} else {
None
}
})
.collect::<_>();
self.accounts[account_index].entries = context.accounts[&*account_hash]
.list_mailboxes()
.into_iter()
.filter(|mailbox_node| {
context.accounts[&*account_hash][&mailbox_node.hash]
.ref_mailbox
.is_subscribed()
})
.map(|f| MailboxMenuEntry {
depth: f.depth,
indentation: f.indentation,
has_sibling: f.has_sibling,
mailbox_hash: f.hash,
visible: true,
collapsed: if previous_collapsed_mailboxes.is_empty() {
context.accounts[&*account_hash][&f.hash].conf.collapsed
} else {
previous_collapsed_mailboxes.contains(&f.hash)
},
})
.collect::<_>();
self.update_menu_account(account_index, context);
self.set_dirty(true);
self.menu_content.empty();
self.menu_content_dirty = true;
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(
@ -825,35 +799,8 @@ impl Component for Listing {
.get_index_of(account_hash)
.expect("Invalid account_hash in UIEventMailbox{Delete,Create}");
self.menu_content.empty();
let previous_collapsed_mailboxes: BTreeSet<MailboxHash> = self.accounts
[account_index]
.entries
.iter()
.filter_map(|e| {
if e.collapsed {
Some(e.mailbox_hash)
} else {
None
}
})
.collect::<_>();
self.accounts[account_index].entries = context.accounts[&*account_hash]
.list_mailboxes()
.into_iter()
.filter(|mailbox_node| {
context.accounts[&*account_hash][&mailbox_node.hash]
.ref_mailbox
.is_subscribed()
})
.map(|f| MailboxMenuEntry {
depth: f.depth,
indentation: f.indentation,
has_sibling: f.has_sibling,
mailbox_hash: f.hash,
visible: true,
collapsed: previous_collapsed_mailboxes.contains(&f.hash),
})
.collect::<_>();
self.menu_content_dirty = true;
self.update_menu_account(account_index, context);
let mut fallback = 0;
if let MenuEntryCursor::Mailbox(ref mut cur) = self.cursor_pos.1 {
*cur = std::cmp::min(
@ -900,6 +847,7 @@ impl Component for Listing {
self.component
.set_coordinates((account_hash, *mailbox_hash));
self.menu_content.empty();
self.menu_content_dirty = true;
self.set_dirty(true);
}
return true;
@ -1378,6 +1326,7 @@ impl Component for Listing {
target.collapsed = !(target.collapsed);
self.dirty = true;
self.menu_content.empty();
self.menu_content_dirty = true;
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::ScrollUpdate(
@ -1520,6 +1469,7 @@ impl Component for Listing {
self.show_menu_scrollbar = ShowMenuScrollbar::True;
}
self.menu_content.empty();
self.menu_content_dirty = true;
self.set_dirty(true);
return true;
}
@ -1581,6 +1531,7 @@ impl Component for Listing {
self.show_menu_scrollbar = ShowMenuScrollbar::True;
}
self.menu_content.empty();
self.menu_content_dirty = true;
return true;
}
UIEvent::Input(ref k)
@ -1634,6 +1585,7 @@ impl Component for Listing {
self.show_menu_scrollbar = ShowMenuScrollbar::True;
}
self.menu_content.empty();
self.menu_content_dirty = true;
self.set_dirty(true);
return true;
@ -1660,6 +1612,7 @@ impl Component for Listing {
self.dirty = true;
/* clear menu to force redraw */
self.menu_content.empty();
self.menu_content_dirty = true;
context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(
@ -1810,13 +1763,14 @@ impl Listing {
.collect();
let first_account_hash = account_entries[0].hash;
let mut ret = Listing {
component: Offline(OfflineListing::new((first_account_hash, 0))),
component: Offline(OfflineListing::new((first_account_hash, MailboxHash(0)))),
accounts: account_entries,
status: None,
dirty: true,
cursor_pos: (0, MenuEntryCursor::Mailbox(0)),
menu_cursor_pos: (0, MenuEntryCursor::Mailbox(0)),
menu_content: CellBuffer::new_with_context(0, 0, None, context),
menu_content_dirty: true,
menu_scrollbar_show_timer: context.job_executor.clone().create_timer(
std::time::Duration::from_secs(0),
std::time::Duration::from_millis(1200),
@ -1841,6 +1795,11 @@ impl Listing {
}
fn draw_menu(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.menu_content_dirty {
for account_index in 0..self.accounts.len() {
self.update_menu_account(account_index, context);
}
}
clear_area(grid, area, self.theme_default);
let total_height: usize = 3 * (self.accounts.len())
+ self
@ -2283,9 +2242,8 @@ impl Listing {
}
}
fn change_account(&mut self, context: &mut Context) {
let account_hash = context.accounts[self.cursor_pos.0].hash();
let previous_collapsed_mailboxes: BTreeSet<MailboxHash> = self.accounts[self.cursor_pos.0]
fn update_menu_account(&mut self, account_index: usize, context: &mut Context) {
let previous_collapsed_mailboxes: BTreeSet<MailboxHash> = self.accounts[account_index]
.entries
.iter()
.filter_map(|e| {
@ -2296,11 +2254,11 @@ impl Listing {
}
})
.collect::<_>();
self.accounts[self.cursor_pos.0].entries = context.accounts[self.cursor_pos.0]
self.accounts[account_index].entries = context.accounts[account_index]
.list_mailboxes()
.into_iter()
.filter(|mailbox_node| {
context.accounts[self.cursor_pos.0][&mailbox_node.hash]
context.accounts[account_index][&mailbox_node.hash]
.ref_mailbox
.is_subscribed()
})
@ -2311,12 +2269,17 @@ impl Listing {
mailbox_hash: f.hash,
visible: true,
collapsed: if previous_collapsed_mailboxes.is_empty() {
context.accounts[self.cursor_pos.0][&f.hash].conf.collapsed
context.accounts[account_index][&f.hash].conf.collapsed
} else {
previous_collapsed_mailboxes.contains(&f.hash)
},
})
.collect::<_>();
}
fn change_account(&mut self, context: &mut Context) {
self.update_menu_account(self.cursor_pos.0, context);
let account_hash = self.accounts[self.cursor_pos.0].hash;
match self.cursor_pos.1 {
MenuEntryCursor::Mailbox(idx) => {
/* Account might have no mailboxes yet if it's offline */
@ -2334,7 +2297,7 @@ impl Listing {
self.component.set_style(*index_style);
} else {
/* Set to dummy */
self.component = Offline(OfflineListing::new((account_hash, 0)));
self.component = Offline(OfflineListing::new((account_hash, MailboxHash(0))));
}
self.status = None;
context

View File

@ -849,7 +849,7 @@ impl CompactListing {
pub const DESCRIPTION: &'static str = "compact listing";
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(CompactListing {
cursor_pos: (coordinates.0, 1, 0),
cursor_pos: (coordinates.0, MailboxHash(0), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),

View File

@ -570,7 +570,7 @@ impl ConversationsListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(ConversationsListing {
cursor_pos: (coordinates.0, 1, 0),
cursor_pos: (coordinates.0, MailboxHash(0), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),

View File

@ -660,7 +660,7 @@ impl PlainListing {
const DESCRIPTION: &'static str = "plain listing";
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(PlainListing {
cursor_pos: (0, 1, 0),
cursor_pos: (AccountHash(0), MailboxHash(0), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),

View File

@ -759,7 +759,7 @@ impl fmt::Display for ThreadListing {
impl ThreadListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(ThreadListing {
cursor_pos: (coordinates.0, 0, 0),
cursor_pos: (coordinates.0, MailboxHash(0), 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
sort: (Default::default(), Default::default()),

View File

@ -1652,7 +1652,7 @@ impl Component for MailView {
}
fn process_event(&mut self, mut event: &mut UIEvent, context: &mut Context) -> bool {
if self.coordinates.0 == 0 || self.coordinates.1 == 0 {
if self.coordinates.0 .0 == 0 || self.coordinates.1 .0 == 0 {
return false;
}
let shortcuts = self.get_shortcuts(context);

View File

@ -1112,7 +1112,7 @@ impl Account {
}
pub fn load(&mut self, mailbox_hash: MailboxHash) -> result::Result<(), usize> {
if mailbox_hash == 0 {
if mailbox_hash.0 == 0 {
return Err(0);
}
match self.mailbox_entries[&mailbox_hash].status {

View File

@ -314,7 +314,12 @@ fn run_app(opt: Opt) -> Result<()> {
sender,
receiver.clone(),
)?;
state.register_component(Box::new(EnvelopeView::new(wrapper, None, None, 0)));
state.register_component(Box::new(EnvelopeView::new(
wrapper,
None,
None,
AccountHash(0),
)));
} else {
state = State::new(None, sender, receiver.clone())?;
#[cfg(feature = "svgscreenshot")]

View File

@ -258,7 +258,7 @@ impl State {
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
hasher.write(n.as_bytes());
hasher.finish()
AccountHash(hasher.finish())
};
Account::new(
account_hash,