melib: Add BackendFolder methods, move special usage logic to backend
- add count() method to return (unseen, total) counts - add is_subscribed() - add set_special_usage() and set_is_subscribed() concerns #8memfd
parent
7bd2b6932d
commit
2b6f6ab42c
|
@ -372,6 +372,26 @@ pub enum SpecialUsageMailbox {
|
|||
Trash,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SpecialUsageMailbox {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
use SpecialUsageMailbox::*;
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Normal => "Normal",
|
||||
Inbox => "Inbox",
|
||||
Archive => "Archive",
|
||||
Drafts => "Drafts",
|
||||
Flagged => "Flagged",
|
||||
Junk => "Junk",
|
||||
Sent => "Sent",
|
||||
Trash => "Trash",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SpecialUsageMailbox {
|
||||
fn default() -> Self {
|
||||
SpecialUsageMailbox::Normal
|
||||
|
@ -409,8 +429,12 @@ pub trait BackendFolder: Debug {
|
|||
fn clone(&self) -> Folder;
|
||||
fn children(&self) -> &[FolderHash];
|
||||
fn parent(&self) -> Option<FolderHash>;
|
||||
fn is_subscribed(&self) -> bool;
|
||||
fn set_is_subscribed(&mut self, new_val: bool) -> Result<()>;
|
||||
fn set_special_usage(&mut self, new_val: SpecialUsageMailbox) -> Result<()>;
|
||||
fn special_usage(&self) -> SpecialUsageMailbox;
|
||||
fn permissions(&self) -> FolderPermissions;
|
||||
fn count(&self) -> Result<(usize, usize)>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -452,6 +476,18 @@ impl BackendFolder for DummyFolder {
|
|||
fn permissions(&self) -> FolderPermissions {
|
||||
FolderPermissions::default()
|
||||
}
|
||||
fn is_subscribed(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn set_is_subscribed(&mut self, _new_val: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn set_special_usage(&mut self, _new_val: SpecialUsageMailbox) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn count(&self) -> Result<(usize, usize)> {
|
||||
Ok((0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn folder_default() -> Folder {
|
||||
|
|
|
@ -169,9 +169,14 @@ impl MailBackend for ImapType {
|
|||
let can_create_flags = self.can_create_flags.clone();
|
||||
let folder_path = folder.path().to_string();
|
||||
let folder_hash = folder.hash();
|
||||
let (permissions, folder_exists, no_select) = {
|
||||
let (permissions, folder_exists, no_select, unseen) = {
|
||||
let f = &self.folders.read().unwrap()[&folder_hash];
|
||||
(f.permissions.clone(), f.exists.clone(), f.no_select)
|
||||
(
|
||||
f.permissions.clone(),
|
||||
f.exists.clone(),
|
||||
f.no_select,
|
||||
f.unseen.clone(),
|
||||
)
|
||||
};
|
||||
let connection = self.connection.clone();
|
||||
let closure = move |_work_context| {
|
||||
|
@ -228,10 +233,11 @@ impl MailBackend for ImapType {
|
|||
);
|
||||
|
||||
let mut tag_lck = tag_index.write().unwrap();
|
||||
let mut our_unseen = 0;
|
||||
while exists > 1 {
|
||||
let mut envelopes = vec![];
|
||||
exit_on_error!(&tx,
|
||||
conn.send_command(format!("UID FETCH {}:{} (UID FLAGS ENVELOPE BODYSTRUCTURE)", std::cmp::max(exists.saturating_sub(20000), 1), exists).as_bytes())
|
||||
conn.send_command(format!("UID FETCH {}:{} (UID FLAGS ENVELOPE BODYSTRUCTURE)", std::cmp::max(exists.saturating_sub(500), 1), exists).as_bytes())
|
||||
conn.read_response(&mut response)
|
||||
);
|
||||
debug!(
|
||||
|
@ -255,6 +261,9 @@ impl MailBackend for ImapType {
|
|||
h.write(folder_path.as_bytes());
|
||||
env.set_hash(h.finish());
|
||||
if let Some((flags, keywords)) = flags {
|
||||
if !flags.contains(Flag::SEEN) {
|
||||
our_unseen += 1;
|
||||
}
|
||||
env.set_flags(flags);
|
||||
for f in keywords {
|
||||
let hash = tag_hash!(f);
|
||||
|
@ -278,8 +287,10 @@ impl MailBackend for ImapType {
|
|||
tx.send(AsyncStatus::Payload(Err(e))).unwrap();
|
||||
}
|
||||
}
|
||||
exists = std::cmp::max(exists.saturating_sub(20000), 1);
|
||||
exists = std::cmp::max(exists.saturating_sub(500), 1);
|
||||
debug!("sending payload");
|
||||
|
||||
*unseen.lock().unwrap() = our_unseen;
|
||||
tx.send(AsyncStatus::Payload(Ok(envelopes))).unwrap();
|
||||
}
|
||||
drop(conn);
|
||||
|
@ -290,6 +301,17 @@ impl MailBackend for ImapType {
|
|||
w.build(handle)
|
||||
}
|
||||
|
||||
fn refresh(
|
||||
&mut self,
|
||||
_folder_hash: FolderHash,
|
||||
_sender: RefreshEventConsumer,
|
||||
) -> Result<Async<Result<Vec<RefreshEvent>>>> {
|
||||
let mut res = String::with_capacity(8 * 1024);
|
||||
self.connection.lock()?.send_command(b"NOOP")?;
|
||||
self.connection.lock()?.read_response(&mut res)?;
|
||||
Err(MeliError::new("Unimplemented."))
|
||||
}
|
||||
|
||||
fn watch(
|
||||
&self,
|
||||
sender: RefreshEventConsumer,
|
||||
|
|
|
@ -357,6 +357,13 @@ impl ImapConnection {
|
|||
}
|
||||
|
||||
pub fn read_lines(&mut self, ret: &mut String, termination_string: String) -> Result<()> {
|
||||
if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() {
|
||||
if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) {
|
||||
*status = Err(MeliError::new("Connection timed out"));
|
||||
self.stream = Err(MeliError::new("Connection timed out"));
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(ref mut stream) = self.stream {
|
||||
if let Ok(_) = stream.read_lines(ret, &termination_string) {
|
||||
return Ok(());
|
||||
|
@ -381,6 +388,12 @@ impl ImapConnection {
|
|||
}
|
||||
|
||||
pub fn wait_for_continuation_request(&mut self) -> Result<()> {
|
||||
if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() {
|
||||
if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) {
|
||||
*status = Err(MeliError::new("Connection timed out"));
|
||||
self.stream = Err(MeliError::new("Connection timed out"));
|
||||
}
|
||||
}
|
||||
if let Ok(ref mut stream) = self.stream {
|
||||
if let Ok(_) = stream.wait_for_continuation_request() {
|
||||
return Ok(());
|
||||
|
@ -405,6 +418,12 @@ impl ImapConnection {
|
|||
}
|
||||
|
||||
pub fn send_command(&mut self, command: &[u8]) -> Result<usize> {
|
||||
if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() {
|
||||
if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) {
|
||||
*status = Err(MeliError::new("Connection timed out"));
|
||||
self.stream = Err(MeliError::new("Connection timed out"));
|
||||
}
|
||||
}
|
||||
if let Ok(ref mut stream) = self.stream {
|
||||
if let Ok(ret) = stream.send_command(command) {
|
||||
return Ok(ret);
|
||||
|
@ -429,6 +448,12 @@ impl ImapConnection {
|
|||
}
|
||||
|
||||
pub fn send_literal(&mut self, data: &[u8]) -> Result<()> {
|
||||
if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() {
|
||||
if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) {
|
||||
*status = Err(MeliError::new("Connection timed out"));
|
||||
self.stream = Err(MeliError::new("Connection timed out"));
|
||||
}
|
||||
}
|
||||
if let Ok(ref mut stream) = self.stream {
|
||||
if let Ok(_) = stream.send_literal(data) {
|
||||
return Ok(());
|
||||
|
@ -453,6 +478,12 @@ impl ImapConnection {
|
|||
}
|
||||
|
||||
pub fn send_raw(&mut self, raw: &[u8]) -> Result<()> {
|
||||
if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() {
|
||||
if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) {
|
||||
*status = Err(MeliError::new("Connection timed out"));
|
||||
self.stream = Err(MeliError::new("Connection timed out"));
|
||||
}
|
||||
}
|
||||
if let Ok(ref mut stream) = self.stream {
|
||||
if let Ok(_) = stream.send_raw(raw) {
|
||||
return Ok(());
|
||||
|
@ -477,6 +508,12 @@ impl ImapConnection {
|
|||
}
|
||||
|
||||
pub fn set_nonblocking(&mut self, val: bool) -> Result<()> {
|
||||
if let (instant, ref mut status @ Ok(())) = *self.online.lock().unwrap() {
|
||||
if Instant::now().duration_since(instant) >= std::time::Duration::new(60 * 30, 0) {
|
||||
*status = Err(MeliError::new("Connection timed out"));
|
||||
self.stream = Err(MeliError::new("Connection timed out"));
|
||||
}
|
||||
}
|
||||
if let Ok(ref mut stream) = self.stream {
|
||||
if let Ok(_) = stream.set_nonblocking(val) {
|
||||
return Ok(());
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
use crate::backends::{BackendFolder, Folder, FolderHash, FolderPermissions, SpecialUsageMailbox};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::error::*;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ImapFolder {
|
||||
|
@ -28,11 +29,13 @@ pub struct ImapFolder {
|
|||
pub(super) name: String,
|
||||
pub(super) parent: Option<FolderHash>,
|
||||
pub(super) children: Vec<FolderHash>,
|
||||
pub usage: SpecialUsageMailbox,
|
||||
pub usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
pub no_select: bool,
|
||||
pub is_subscribed: bool,
|
||||
|
||||
pub permissions: Arc<Mutex<FolderPermissions>>,
|
||||
pub exists: Arc<Mutex<usize>>,
|
||||
pub unseen: Arc<Mutex<usize>>,
|
||||
}
|
||||
|
||||
impl BackendFolder for ImapFolder {
|
||||
|
@ -57,21 +60,11 @@ impl BackendFolder for ImapFolder {
|
|||
}
|
||||
|
||||
fn clone(&self) -> Folder {
|
||||
Box::new(ImapFolder {
|
||||
hash: self.hash,
|
||||
path: self.path.clone(),
|
||||
name: self.name.clone(),
|
||||
parent: self.parent,
|
||||
children: self.children.clone(),
|
||||
usage: self.usage,
|
||||
no_select: self.no_select,
|
||||
permissions: self.permissions.clone(),
|
||||
exists: self.exists.clone(),
|
||||
})
|
||||
Box::new(std::clone::Clone::clone(self))
|
||||
}
|
||||
|
||||
fn special_usage(&self) -> SpecialUsageMailbox {
|
||||
self.usage
|
||||
*self.usage.read().unwrap()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<FolderHash> {
|
||||
|
@ -81,4 +74,21 @@ impl BackendFolder for ImapFolder {
|
|||
fn permissions(&self) -> FolderPermissions {
|
||||
*self.permissions.lock().unwrap()
|
||||
}
|
||||
fn is_subscribed(&self) -> bool {
|
||||
self.is_subscribed
|
||||
}
|
||||
fn set_is_subscribed(&mut self, new_val: bool) -> Result<()> {
|
||||
self.is_subscribed = new_val;
|
||||
// FIXME: imap subscribe
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_special_usage(&mut self, new_val: SpecialUsageMailbox) -> Result<()> {
|
||||
*self.usage.write()? = new_val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn count(&self) -> Result<(usize, usize)> {
|
||||
Ok((*self.unseen.lock()?, *self.exists.lock()?))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,11 +93,11 @@ named!(
|
|||
if p.eq_ignore_ascii_case(b"\\NoSelect") {
|
||||
f.no_select = true;
|
||||
} else if p.eq_ignore_ascii_case(b"\\Sent") {
|
||||
f.usage = SpecialUsageMailbox::Sent;
|
||||
let _ = f.set_special_usage(SpecialUsageMailbox::Sent);
|
||||
} else if p.eq_ignore_ascii_case(b"\\Junk") {
|
||||
f.usage = SpecialUsageMailbox::Trash;
|
||||
let _ = f.set_special_usage(SpecialUsageMailbox::Trash);
|
||||
} else if p.eq_ignore_ascii_case(b"\\Drafts") {
|
||||
f.usage = SpecialUsageMailbox::Drafts;
|
||||
let _ = f.set_special_usage(SpecialUsageMailbox::Drafts);
|
||||
}
|
||||
}
|
||||
f.hash = get_path_hash!(path);
|
||||
|
|
|
@ -124,7 +124,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
|||
.read()
|
||||
.unwrap()
|
||||
.values()
|
||||
.find(|f| f.parent.is_none() && (f.usage == SpecialUsageMailbox::Inbox))
|
||||
.find(|f| f.parent.is_none() && (f.special_usage() == SpecialUsageMailbox::Inbox))
|
||||
.map(std::clone::Clone::clone)
|
||||
{
|
||||
Some(folder) => folder,
|
||||
|
@ -166,6 +166,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
|||
hash: folder_hash,
|
||||
kind: RefreshEventKind::Rescan,
|
||||
});
|
||||
*prev_exists = 0;
|
||||
uid_store.uid_index.lock().unwrap().clear();
|
||||
uid_store.hash_index.lock().unwrap().clear();
|
||||
uid_store.byte_cache.lock().unwrap().clear();
|
||||
|
@ -346,6 +347,11 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
|||
env.labels_mut().push(hash);
|
||||
}
|
||||
}
|
||||
if !env.is_seen() {
|
||||
*folder.unseen.lock().unwrap() += 1;
|
||||
}
|
||||
*folder.exists.lock().unwrap() += 1;
|
||||
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Create(Box::new(env)),
|
||||
|
@ -460,6 +466,9 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
|
|||
env.subject(),
|
||||
folder.path(),
|
||||
);
|
||||
if !env.is_seen() {
|
||||
*folder.unseen.lock().unwrap() += 1;
|
||||
}
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Create(Box::new(env)),
|
||||
|
@ -626,6 +635,9 @@ fn examine_updates(
|
|||
env.labels_mut().push(hash);
|
||||
}
|
||||
}
|
||||
if !env.is_seen() {
|
||||
*folder.unseen.lock().unwrap() += 1;
|
||||
}
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Create(Box::new(env)),
|
||||
|
@ -697,6 +709,9 @@ fn examine_updates(
|
|||
env.subject(),
|
||||
folder.path(),
|
||||
);
|
||||
if !env.is_seen() {
|
||||
*folder.unseen.lock().unwrap() += 1;
|
||||
}
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Create(Box::new(env)),
|
||||
|
|
|
@ -289,7 +289,10 @@ impl JmapType {
|
|||
s: &AccountSettings,
|
||||
is_subscribed: Box<dyn Fn(&str) -> bool + Send + Sync>,
|
||||
) -> Result<Box<dyn MailBackend>> {
|
||||
let online = Arc::new(Mutex::new(Err(MeliError::new("Account is uninitialised."))));
|
||||
let online = Arc::new(Mutex::new((
|
||||
std::time::Instant::now(),
|
||||
Err(MeliError::new("Account is uninitialised.")),
|
||||
)));
|
||||
let server_conf = JmapServerConf::new(s)?;
|
||||
|
||||
Ok(Box::new(JmapType {
|
||||
|
|
|
@ -33,10 +33,12 @@ pub struct JmapConnection {
|
|||
}
|
||||
|
||||
impl JmapConnection {
|
||||
pub fn new(server_conf: &JmapServerConf, online_status: Arc<Mutex<(Instant, Result<()>)>>) -> Result<Self> {
|
||||
pub fn new(
|
||||
server_conf: &JmapServerConf,
|
||||
online_status: Arc<Mutex<(Instant, Result<()>)>>,
|
||||
) -> Result<Self> {
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::new();
|
||||
let connection_start = std::time::Instant::now();
|
||||
headers.insert(
|
||||
header::ACCEPT,
|
||||
header::HeaderValue::from_static("application/json"),
|
||||
|
@ -70,28 +72,29 @@ impl JmapConnection {
|
|||
let res_text = req.text()?;
|
||||
|
||||
let session: JmapSession = serde_json::from_str(&res_text).map_err(|_| {
|
||||
let err = MeliError::new(format!("Could not connect to JMAP server endpoint for {}. Is your server hostname setting correct? (i.e. \"jmap.mailserver.org\") (Note: only session resource discovery via /.well-known/jmap is supported. DNS SRV records are not suppported.)", &server_conf.server_hostname);
|
||||
*online_status.lock().unwrap() = (Instant::new(), Err(err.clone()));
|
||||
let err = MeliError::new(format!("Could not connect to JMAP server endpoint for {}. Is your server hostname setting correct? (i.e. \"jmap.mailserver.org\") (Note: only session resource discovery via /.well-known/jmap is supported. DNS SRV records are not suppported.)", &server_conf.server_hostname));
|
||||
*online_status.lock().unwrap() = (Instant::now(), Err(err.clone()));
|
||||
err
|
||||
))?;
|
||||
}
|
||||
)?;
|
||||
if !session
|
||||
.capabilities
|
||||
.contains_key("urn:ietf:params:jmap:core")
|
||||
{
|
||||
let err = Err(MeliError::new(format!("Server {} did not return JMAP Core capability (urn:ietf:params:jmap:core). Returned capabilities were: {}", &server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::<Vec<&str>>().join(", "))));
|
||||
*online_status.lock().unwrap() = (Instant::new(), Err(err.clone()));
|
||||
return err;
|
||||
let err = MeliError::new(format!("Server {} did not return JMAP Core capability (urn:ietf:params:jmap:core). Returned capabilities were: {}", &server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::<Vec<&str>>().join(", ")));
|
||||
*online_status.lock().unwrap() = (Instant::now(), Err(err.clone()));
|
||||
return Err(err);
|
||||
}
|
||||
if !session
|
||||
.capabilities
|
||||
.contains_key("urn:ietf:params:jmap:mail")
|
||||
{
|
||||
let err = Err(MeliError::new(format!("Server {} does not support JMAP Mail capability (urn:ietf:params:jmap:mail). Returned capabilities were: {}", &server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::<Vec<&str>>().join(", "))));
|
||||
*online_status.lock().unwrap() = (Instant::new(), Err(err.clone()));
|
||||
return err;
|
||||
let err = MeliError::new(format!("Server {} does not support JMAP Mail capability (urn:ietf:params:jmap:mail). Returned capabilities were: {}", &server_conf.server_hostname, session.capabilities.keys().map(String::as_str).collect::<Vec<&str>>().join(", ")));
|
||||
*online_status.lock().unwrap() = (Instant::now(), Err(err.clone()));
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
*online_status.lock().unwrap() = (Instant::new(), Ok(()));
|
||||
*online_status.lock().unwrap() = (Instant::now(), Ok(()));
|
||||
let server_conf = server_conf.clone();
|
||||
Ok(JmapConnection {
|
||||
session,
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
use super::*;
|
||||
use crate::backends::{FolderPermissions, SpecialUsageMailbox};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct JmapFolder {
|
||||
|
@ -34,11 +35,11 @@ pub struct JmapFolder {
|
|||
pub parent_id: Option<String>,
|
||||
pub role: Option<String>,
|
||||
pub sort_order: u64,
|
||||
pub total_emails: u64,
|
||||
pub total_emails: Arc<Mutex<u64>>,
|
||||
pub total_threads: u64,
|
||||
pub unread_emails: u64,
|
||||
pub unread_emails: Arc<Mutex<u64>>,
|
||||
pub unread_threads: u64,
|
||||
pub usage: SpecialUsageMailbox,
|
||||
pub usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
}
|
||||
|
||||
impl BackendFolder for JmapFolder {
|
||||
|
@ -91,4 +92,24 @@ impl BackendFolder for JmapFolder {
|
|||
None => SpecialUsageMailbox::Normal,
|
||||
}
|
||||
}
|
||||
fn is_subscribed(&self) -> bool {
|
||||
self.is_subscribed
|
||||
}
|
||||
fn set_is_subscribed(&mut self, new_val: bool) -> Result<()> {
|
||||
self.is_subscribed = new_val;
|
||||
// FIXME: jmap subscribe
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_special_usage(&mut self, new_val: SpecialUsageMailbox) -> Result<()> {
|
||||
*self.usage.write()? = new_val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn count(&self) -> Result<(usize, usize)> {
|
||||
Ok((
|
||||
*self.unread_emails.lock()? as usize,
|
||||
*self.total_emails.lock()? as usize,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ impl BackendOp for JmapOp {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, value: bool) -> Result<()> {
|
||||
fn set_tag(&mut self, _envelope: &mut Envelope, _tag: String, _value: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ pub fn get_mailboxes(conn: &JmapConnection) -> Result<FnvHashMap<FolderHash, Jma
|
|||
|
||||
let res_text = res?.text()?;
|
||||
let mut v: MethodResponse = serde_json::from_str(&res_text).unwrap();
|
||||
*conn.online_status.lock().unwrap() = true;
|
||||
*conn.online_status.lock().unwrap() = (std::time::Instant::now(), Ok(()));
|
||||
let m = GetResponse::<MailboxObject>::try_from(v.method_responses.remove(0))?;
|
||||
let GetResponse::<MailboxObject> {
|
||||
list, account_id, ..
|
||||
|
@ -163,9 +163,9 @@ pub fn get_mailboxes(conn: &JmapConnection) -> Result<FnvHashMap<FolderHash, Jma
|
|||
role,
|
||||
usage: Default::default(),
|
||||
sort_order,
|
||||
total_emails,
|
||||
total_emails: Arc::new(Mutex::new(total_emails)),
|
||||
total_threads,
|
||||
unread_emails,
|
||||
unread_emails: Arc::new(Mutex::new(unread_emails)),
|
||||
unread_threads,
|
||||
},
|
||||
)
|
||||
|
@ -208,7 +208,7 @@ pub fn get_message_list(conn: &JmapConnection, folder: &JmapFolder) -> Result<Ve
|
|||
|
||||
let res_text = res?.text()?;
|
||||
let mut v: MethodResponse = serde_json::from_str(&res_text).unwrap();
|
||||
*conn.online_status.lock().unwrap() = true;
|
||||
*conn.online_status.lock().unwrap() = (std::time::Instant::now(), Ok(()));
|
||||
let m = QueryResponse::<EmailObject>::try_from(v.method_responses.remove(0))?;
|
||||
let QueryResponse::<EmailObject> { ids, .. } = m;
|
||||
Ok(ids)
|
||||
|
|
|
@ -33,6 +33,7 @@ use std::collections::hash_map::DefaultHasher;
|
|||
use std::fs;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
/// `BackendOp` implementor for Maildir
|
||||
#[derive(Debug)]
|
||||
|
@ -168,7 +169,7 @@ impl<'a> BackendOp for MaildirOp {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct MaildirFolder {
|
||||
hash: FolderHash,
|
||||
name: String,
|
||||
|
@ -176,8 +177,11 @@ pub struct MaildirFolder {
|
|||
path: PathBuf,
|
||||
parent: Option<FolderHash>,
|
||||
children: Vec<FolderHash>,
|
||||
usage: SpecialUsageMailbox,
|
||||
pub usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
pub is_subscribed: bool,
|
||||
permissions: FolderPermissions,
|
||||
pub total: Arc<Mutex<usize>>,
|
||||
pub unseen: Arc<Mutex<usize>>,
|
||||
}
|
||||
|
||||
impl MaildirFolder {
|
||||
|
@ -238,7 +242,8 @@ impl MaildirFolder {
|
|||
fs_path: pathbuf,
|
||||
parent,
|
||||
children,
|
||||
usage: SpecialUsageMailbox::Normal,
|
||||
usage: Arc::new(RwLock::new(SpecialUsageMailbox::Normal)),
|
||||
is_subscribed: true,
|
||||
permissions: FolderPermissions {
|
||||
create_messages: !read_only,
|
||||
remove_messages: !read_only,
|
||||
|
@ -249,6 +254,8 @@ impl MaildirFolder {
|
|||
delete_mailbox: !read_only,
|
||||
change_permissions: false,
|
||||
},
|
||||
unseen: Arc::new(Mutex::new(0)),
|
||||
total: Arc::new(Mutex::new(0)),
|
||||
};
|
||||
ret.is_valid()?;
|
||||
Ok(ret)
|
||||
|
@ -274,6 +281,7 @@ impl MaildirFolder {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl BackendFolder for MaildirFolder {
|
||||
fn hash(&self) -> FolderHash {
|
||||
self.hash
|
||||
|
@ -296,20 +304,11 @@ impl BackendFolder for MaildirFolder {
|
|||
}
|
||||
|
||||
fn clone(&self) -> Folder {
|
||||
Box::new(MaildirFolder {
|
||||
hash: self.hash,
|
||||
name: self.name.clone(),
|
||||
fs_path: self.fs_path.clone(),
|
||||
path: self.path.clone(),
|
||||
children: self.children.clone(),
|
||||
usage: self.usage,
|
||||
parent: self.parent,
|
||||
permissions: self.permissions,
|
||||
})
|
||||
Box::new(std::clone::Clone::clone(self))
|
||||
}
|
||||
|
||||
fn special_usage(&self) -> SpecialUsageMailbox {
|
||||
self.usage
|
||||
*self.usage.read().unwrap()
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<FolderHash> {
|
||||
|
@ -319,4 +318,20 @@ impl BackendFolder for MaildirFolder {
|
|||
fn permissions(&self) -> FolderPermissions {
|
||||
self.permissions
|
||||
}
|
||||
fn is_subscribed(&self) -> bool {
|
||||
self.is_subscribed
|
||||
}
|
||||
fn set_is_subscribed(&mut self, new_val: bool) -> Result<()> {
|
||||
self.is_subscribed = new_val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_special_usage(&mut self, new_val: SpecialUsageMailbox) -> Result<()> {
|
||||
*self.usage.write()? = new_val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn count(&self) -> Result<(usize, usize)> {
|
||||
Ok((*self.unseen.lock()?, *self.total.lock()?))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ impl MailBackend for MaildirType {
|
|||
Ok(self
|
||||
.folders
|
||||
.iter()
|
||||
.map(|(h, f)| (*h, f.clone() as Folder))
|
||||
.map(|(h, f)| (*h, BackendFolder::clone(f)))
|
||||
.collect())
|
||||
}
|
||||
|
||||
|
@ -342,6 +342,11 @@ impl MailBackend for MaildirType {
|
|||
debug!("watching {:?}", root_path);
|
||||
let hash_indexes = self.hash_indexes.clone();
|
||||
let folder_index = self.folder_index.clone();
|
||||
let folder_counts = self
|
||||
.folders
|
||||
.iter()
|
||||
.map(|(&k, v)| (k, (v.unseen.clone(), v.total.clone())))
|
||||
.collect::<FnvHashMap<FolderHash, (Arc<Mutex<usize>>, Arc<Mutex<usize>>)>>();
|
||||
let handle = thread::Builder::new()
|
||||
.name("folder watch".to_string())
|
||||
.spawn(move || {
|
||||
|
@ -397,6 +402,10 @@ impl MailBackend for MaildirType {
|
|||
env.subject(),
|
||||
pathbuf.display()
|
||||
);
|
||||
if !env.is_seen() {
|
||||
*folder_counts[&folder_hash].0.lock().unwrap() += 1;
|
||||
}
|
||||
*folder_counts[&folder_hash].1.lock().unwrap() += 1;
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Create(Box::new(env)),
|
||||
|
@ -505,6 +514,8 @@ impl MailBackend for MaildirType {
|
|||
e.removed = true;
|
||||
});
|
||||
|
||||
//FIXME: check if envelope was unseen to update unseen count
|
||||
*folder_counts[&folder_hash].1.lock().unwrap() += 1;
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Remove(hash),
|
||||
|
@ -579,6 +590,10 @@ impl MailBackend for MaildirType {
|
|||
env.subject(),
|
||||
dest.display()
|
||||
);
|
||||
if !env.is_seen() {
|
||||
*folder_counts[&folder_hash].0.lock().unwrap() += 1;
|
||||
}
|
||||
*folder_counts[&folder_hash].1.lock().unwrap() += 1;
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
kind: Create(Box::new(env)),
|
||||
|
@ -777,6 +792,8 @@ impl MaildirType {
|
|||
// TODO: Avoid clone
|
||||
let folder: &MaildirFolder = &self.folders[&self.owned_folder_idx(folder)];
|
||||
let folder_hash = folder.hash();
|
||||
let unseen = folder.unseen.clone();
|
||||
let total = folder.total.clone();
|
||||
let tx_final = w.tx();
|
||||
let path: PathBuf = folder.fs_path().into();
|
||||
let name = format!("parsing {:?}", folder.name());
|
||||
|
@ -785,6 +802,8 @@ impl MaildirType {
|
|||
let folder_index = self.folder_index.clone();
|
||||
|
||||
let closure = move |work_context: crate::async_workers::WorkContext| {
|
||||
let unseen = unseen.clone();
|
||||
let total = total.clone();
|
||||
let name = name.clone();
|
||||
work_context
|
||||
.set_name
|
||||
|
@ -829,6 +848,8 @@ impl MaildirType {
|
|||
count
|
||||
};
|
||||
for chunk in files.chunks(chunk_size) {
|
||||
let unseen = unseen.clone();
|
||||
let total = total.clone();
|
||||
let cache_dir = cache_dir.clone();
|
||||
let tx = tx.clone();
|
||||
let map = map.clone();
|
||||
|
@ -869,6 +890,10 @@ impl MaildirType {
|
|||
.lock()
|
||||
.unwrap()
|
||||
.insert(hash, folder_hash);
|
||||
if !env.is_seen() {
|
||||
*unseen.lock().unwrap() += 1;
|
||||
}
|
||||
*total.lock().unwrap() += 1;
|
||||
local_r.push(env);
|
||||
continue;
|
||||
}
|
||||
|
@ -908,6 +933,10 @@ impl MaildirType {
|
|||
let writer = io::BufWriter::new(f);
|
||||
bincode::serialize_into(writer, &e).unwrap();
|
||||
}
|
||||
if !e.is_seen() {
|
||||
*unseen.lock().unwrap() += 1;
|
||||
}
|
||||
*total.lock().unwrap() += 1;
|
||||
local_r.push(e);
|
||||
} else {
|
||||
debug!(
|
||||
|
|
|
@ -49,7 +49,7 @@ use std::io::Read;
|
|||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
const F_OFD_SETLKW: libc::c_int = 38;
|
||||
|
||||
|
@ -87,7 +87,11 @@ struct MboxFolder {
|
|||
content: Vec<u8>,
|
||||
children: Vec<FolderHash>,
|
||||
parent: Option<FolderHash>,
|
||||
usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
is_subscribed: bool,
|
||||
permissions: FolderPermissions,
|
||||
pub total: Arc<Mutex<usize>>,
|
||||
pub unseen: Arc<Mutex<usize>>,
|
||||
}
|
||||
|
||||
impl BackendFolder for MboxFolder {
|
||||
|
@ -115,8 +119,12 @@ impl BackendFolder for MboxFolder {
|
|||
path: self.path.clone(),
|
||||
content: self.content.clone(),
|
||||
children: self.children.clone(),
|
||||
usage: self.usage.clone(),
|
||||
is_subscribed: self.is_subscribed,
|
||||
parent: self.parent,
|
||||
permissions: self.permissions,
|
||||
unseen: self.unseen.clone(),
|
||||
total: self.total.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -129,12 +137,27 @@ impl BackendFolder for MboxFolder {
|
|||
}
|
||||
|
||||
fn special_usage(&self) -> SpecialUsageMailbox {
|
||||
SpecialUsageMailbox::Normal
|
||||
*self.usage.read().unwrap()
|
||||
}
|
||||
|
||||
fn permissions(&self) -> FolderPermissions {
|
||||
self.permissions
|
||||
}
|
||||
fn is_subscribed(&self) -> bool {
|
||||
self.is_subscribed
|
||||
}
|
||||
fn set_is_subscribed(&mut self, new_val: bool) -> Result<()> {
|
||||
self.is_subscribed = new_val;
|
||||
Ok(())
|
||||
}
|
||||
fn set_special_usage(&mut self, new_val: SpecialUsageMailbox) -> Result<()> {
|
||||
*self.usage.write()? = new_val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn count(&self) -> Result<(usize, usize)> {
|
||||
Ok((*self.unseen.lock()?, *self.total.lock()?))
|
||||
}
|
||||
}
|
||||
|
||||
/// `BackendOp` implementor for Mbox
|
||||
|
@ -631,6 +654,8 @@ impl MboxType {
|
|||
content: Vec::new(),
|
||||
children: Vec::new(),
|
||||
parent: None,
|
||||
usage: Arc::new(RwLock::new(SpecialUsageMailbox::Normal)),
|
||||
is_subscribed: true,
|
||||
permissions: FolderPermissions {
|
||||
create_messages: !read_only,
|
||||
remove_messages: !read_only,
|
||||
|
@ -641,6 +666,8 @@ impl MboxType {
|
|||
delete_mailbox: !read_only,
|
||||
change_permissions: false,
|
||||
},
|
||||
unseen: Arc::new(Mutex::new(0)),
|
||||
total: Arc::new(Mutex::new(0)),
|
||||
},
|
||||
);
|
||||
/*
|
||||
|
|
|
@ -16,7 +16,7 @@ use std::ffi::{CStr, CString};
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
pub mod bindings;
|
||||
use bindings::*;
|
||||
|
@ -67,10 +67,13 @@ struct NotmuchFolder {
|
|||
parent: Option<FolderHash>,
|
||||
name: String,
|
||||
path: String,
|
||||
usage: SpecialUsageMailbox,
|
||||
query_str: String,
|
||||
query: Option<*mut notmuch_query_t>,
|
||||
phantom: std::marker::PhantomData<&'static mut notmuch_query_t>,
|
||||
usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
|
||||
total: Arc<Mutex<usize>>,
|
||||
unseen: Arc<Mutex<usize>>,
|
||||
}
|
||||
|
||||
impl BackendFolder for NotmuchFolder {
|
||||
|
@ -101,12 +104,29 @@ impl BackendFolder for NotmuchFolder {
|
|||
}
|
||||
|
||||
fn special_usage(&self) -> SpecialUsageMailbox {
|
||||
self.usage
|
||||
*self.usage.read().unwrap()
|
||||
}
|
||||
|
||||
fn permissions(&self) -> FolderPermissions {
|
||||
FolderPermissions::default()
|
||||
}
|
||||
|
||||
fn is_subscribed(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set_is_subscribed(&mut self, _new_val: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_special_usage(&mut self, new_val: SpecialUsageMailbox) -> Result<()> {
|
||||
*self.usage.write()? = new_val;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn count(&self) -> Result<(usize, usize)> {
|
||||
Ok((*self.unseen.lock()?, *self.total.lock()?))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for NotmuchFolder {}
|
||||
|
@ -162,8 +182,10 @@ impl NotmuchDb {
|
|||
parent: None,
|
||||
query: None,
|
||||
query_str: query_str.to_string(),
|
||||
usage: SpecialUsageMailbox::Normal,
|
||||
usage: Arc::new(RwLock::new(SpecialUsageMailbox::Normal)),
|
||||
phantom: std::marker::PhantomData,
|
||||
total: Arc::new(Mutex::new(0)),
|
||||
unseen: Arc::new(Mutex::new(0)),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -770,17 +770,11 @@ impl Component for Listing {
|
|||
} else {
|
||||
return Some(String::new());
|
||||
};
|
||||
let envelopes = account.collection.envelopes.clone();
|
||||
let envelopes = envelopes.read().unwrap();
|
||||
format!(
|
||||
"Mailbox: {}, Messages: {}, New: {}",
|
||||
m.folder.name(),
|
||||
m.envelopes.len(),
|
||||
m.envelopes
|
||||
.iter()
|
||||
.map(|h| &envelopes[&h])
|
||||
.filter(|e| !e.is_seen())
|
||||
.count()
|
||||
m.folder.count().ok().map(|(v, _)| v).unwrap_or(0),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -903,20 +897,12 @@ impl Listing {
|
|||
) {
|
||||
match context.accounts[index].status(entries[&folder_idx].hash()) {
|
||||
Ok(_) => {
|
||||
let account = &context.accounts[index];
|
||||
let count = account[entries[&folder_idx].hash()]
|
||||
.unwrap()
|
||||
.envelopes
|
||||
.iter()
|
||||
.filter_map(|&h| {
|
||||
if account.collection.get_env(h).is_seen() {
|
||||
None
|
||||
} else {
|
||||
Some(())
|
||||
}
|
||||
})
|
||||
.count();
|
||||
lines.push((*depth, *inc, folder_idx, Some(count)));
|
||||
lines.push((
|
||||
*depth,
|
||||
*inc,
|
||||
folder_idx,
|
||||
entries[&folder_idx].count().ok().map(|(v, _)| v),
|
||||
));
|
||||
}
|
||||
Err(_) => {
|
||||
lines.push((*depth, *inc, folder_idx, None));
|
||||
|
|
|
@ -291,18 +291,12 @@ impl StatusPanel {
|
|||
self.content[(2, h + y + 1)].set_ch(' ');
|
||||
}
|
||||
}
|
||||
let count = a.ref_folders.values().fold((0, 0), |acc, f| {
|
||||
let count = f.count().unwrap_or((0, 0));
|
||||
(acc.0 + count.0, acc.1 + count.1)
|
||||
});
|
||||
let (mut column_width, _) = write_string_to_grid(
|
||||
&format!(
|
||||
"Messages total {}, unseen {}",
|
||||
a.collection.len(),
|
||||
a.collection
|
||||
.envelopes
|
||||
.read()
|
||||
.unwrap()
|
||||
.values()
|
||||
.filter(|e| !e.is_seen())
|
||||
.count()
|
||||
),
|
||||
&format!("Messages total {}, unseen {}", count.1, count.0),
|
||||
&mut self.content,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
|
@ -338,17 +332,7 @@ impl StatusPanel {
|
|||
);
|
||||
/* next column */
|
||||
write_string_to_grid(
|
||||
&format!(
|
||||
"Messages total {}, unseen {}",
|
||||
a.collection.len(),
|
||||
a.collection
|
||||
.envelopes
|
||||
.read()
|
||||
.unwrap()
|
||||
.values()
|
||||
.filter(|e| !e.is_seen())
|
||||
.count()
|
||||
),
|
||||
"Special Mailboxes:",
|
||||
&mut self.content,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
|
@ -356,6 +340,22 @@ impl StatusPanel {
|
|||
((5 + column_width, y + 2), (120 - 2, y + 2)),
|
||||
None,
|
||||
);
|
||||
for (i, f) in a
|
||||
.ref_folders
|
||||
.values()
|
||||
.filter(|f| f.special_usage() != SpecialUsageMailbox::Normal)
|
||||
.enumerate()
|
||||
{
|
||||
write_string_to_grid(
|
||||
&format!("{}: {}", f.path(), f.special_usage()),
|
||||
&mut self.content,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
Attr::Default,
|
||||
((5 + column_width, y + 3 + i), (120 - 2, y + 2)),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,6 +146,7 @@ pub struct Account {
|
|||
name: String,
|
||||
pub is_online: bool,
|
||||
pub(crate) folders: FnvHashMap<FolderHash, MailboxEntry>,
|
||||
pub(crate) ref_folders: FnvHashMap<FolderHash, Folder>,
|
||||
pub(crate) folder_confs: FnvHashMap<FolderHash, FileFolderConf>,
|
||||
pub(crate) folders_order: Vec<FolderHash>,
|
||||
pub(crate) folder_names: FnvHashMap<FolderHash, String>,
|
||||
|
@ -289,6 +290,7 @@ impl Account {
|
|||
name,
|
||||
is_online: false,
|
||||
folders: Default::default(),
|
||||
ref_folders: Default::default(),
|
||||
folder_confs: Default::default(),
|
||||
folders_order: Default::default(),
|
||||
folder_names: Default::default(),
|
||||
|
@ -309,7 +311,7 @@ impl Account {
|
|||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
let ref_folders: FnvHashMap<FolderHash, Folder> =
|
||||
let mut ref_folders: FnvHashMap<FolderHash, Folder> =
|
||||
match self.backend.read().unwrap().folders() {
|
||||
Ok(f) => f,
|
||||
Err(err) => {
|
||||
|
@ -325,7 +327,7 @@ impl Account {
|
|||
let mut folder_confs = FnvHashMap::default();
|
||||
|
||||
let mut sent_folder = None;
|
||||
for f in ref_folders.values() {
|
||||
for f in ref_folders.values_mut() {
|
||||
if !((self.settings.folder_confs.contains_key(f.path())
|
||||
&& self.settings.folder_confs[f.path()]
|
||||
.folder_conf()
|
||||
|
@ -342,18 +344,41 @@ impl Account {
|
|||
continue;
|
||||
}
|
||||
|
||||
if self.settings.folder_confs.contains_key(f.path()) {
|
||||
match self.settings.folder_confs[f.path()].folder_conf().usage {
|
||||
if let Some(conf) = self.settings.folder_confs.get_mut(f.path()) {
|
||||
conf.folder_conf.usage = if f.special_usage() != SpecialUsageMailbox::Normal {
|
||||
Some(f.special_usage())
|
||||
} else {
|
||||
let tmp = SpecialUsageMailbox::detect_usage(f.name());
|
||||
if tmp != Some(SpecialUsageMailbox::Normal) && tmp != None {
|
||||
let _ = f.set_special_usage(tmp.unwrap());
|
||||
}
|
||||
tmp
|
||||
};
|
||||
match conf.folder_conf.usage {
|
||||
Some(SpecialUsageMailbox::Sent) => {
|
||||
sent_folder = Some(f.hash());
|
||||
}
|
||||
None => {
|
||||
if f.special_usage() == SpecialUsageMailbox::Sent {
|
||||
sent_folder = Some(f.hash());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
folder_confs.insert(f.hash(), self.settings.folder_confs[f.path()].clone());
|
||||
folder_confs.insert(f.hash(), conf.clone());
|
||||
} else {
|
||||
let mut new = FileFolderConf::default();
|
||||
new.folder_conf.subscribe = super::ToggleFlag::InternalVal(true);
|
||||
new.folder_conf.usage = SpecialUsageMailbox::detect_usage(f.name());
|
||||
new.folder_conf.usage = if f.special_usage() != SpecialUsageMailbox::Normal {
|
||||
Some(f.special_usage())
|
||||
} else {
|
||||
let tmp = SpecialUsageMailbox::detect_usage(f.name());
|
||||
if tmp != Some(SpecialUsageMailbox::Normal) && tmp != None {
|
||||
let _ = f.set_special_usage(tmp.unwrap());
|
||||
}
|
||||
tmp
|
||||
};
|
||||
|
||||
folder_confs.insert(f.hash(), new);
|
||||
}
|
||||
folder_names.insert(f.hash(), f.path().to_string());
|
||||
|
@ -396,7 +421,6 @@ impl Account {
|
|||
workers.insert(
|
||||
*h,
|
||||
Account::new_worker(
|
||||
&folder_confs,
|
||||
f.clone(),
|
||||
&mut self.backend,
|
||||
&self.work_context,
|
||||
|
@ -440,6 +464,7 @@ impl Account {
|
|||
}
|
||||
|
||||
self.folders = folders;
|
||||
self.ref_folders = ref_folders;
|
||||
self.folder_confs = folder_confs;
|
||||
self.folders_order = folders_order;
|
||||
self.folder_names = folder_names;
|
||||
|
@ -450,7 +475,6 @@ impl Account {
|
|||
}
|
||||
|
||||
fn new_worker(
|
||||
folder_confs: &FnvHashMap<FolderHash, FileFolderConf>,
|
||||
folder: Folder,
|
||||
backend: &Arc<RwLock<Box<dyn MailBackend>>>,
|
||||
work_context: &WorkContext,
|
||||
|
@ -460,11 +484,11 @@ impl Account {
|
|||
let mut builder = AsyncBuilder::new();
|
||||
let our_tx = builder.tx();
|
||||
let folder_hash = folder.hash();
|
||||
let priority = match folder_confs[&folder.hash()].folder_conf().usage {
|
||||
Some(SpecialUsageMailbox::Inbox) => 0,
|
||||
Some(SpecialUsageMailbox::Sent) => 1,
|
||||
Some(SpecialUsageMailbox::Drafts) | Some(SpecialUsageMailbox::Trash) => 2,
|
||||
Some(_) | None => {
|
||||
let priority = match folder.special_usage() {
|
||||
SpecialUsageMailbox::Inbox => 0,
|
||||
SpecialUsageMailbox::Sent => 1,
|
||||
SpecialUsageMailbox::Drafts | SpecialUsageMailbox::Trash => 2,
|
||||
_ => {
|
||||
3 * folder
|
||||
.path()
|
||||
.split(if folder.path().contains('/') {
|
||||
|
@ -673,7 +697,6 @@ impl Account {
|
|||
let ref_folders: FnvHashMap<FolderHash, Folder> =
|
||||
self.backend.read().unwrap().folders().unwrap();
|
||||
let handle = Account::new_worker(
|
||||
&self.folder_confs,
|
||||
ref_folders[&folder_hash].clone(),
|
||||
&mut self.backend,
|
||||
&self.work_context,
|
||||
|
|
Loading…
Reference in New Issue