melib: make MailBackend::is_online() return Result<()>

Return Result<()> instead of bool to indicate connection status in order
to be able to show errors to user.
memfd
Manos Pitsidianakis 2019-12-14 18:46:12 +02:00
parent 18a8d22b85
commit 2e38ea11e2
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
12 changed files with 172 additions and 70 deletions

View File

@ -245,7 +245,7 @@ pub enum FolderOperation {
type NewFolderName = String; type NewFolderName = String;
pub trait MailBackend: ::std::fmt::Debug + Send + Sync { pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
fn is_online(&self) -> bool; fn is_online(&self) -> Result<()>;
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>; fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>;
fn watch( fn watch(
&self, &self,

View File

@ -45,6 +45,7 @@ use std::collections::{hash_map::DefaultHasher, BTreeMap};
use std::hash::Hasher; use std::hash::Hasher;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::time::Instant;
pub type UID = usize; pub type UID = usize;
pub static SUPPORTED_CAPABILITIES: &'static [&'static str] = pub static SUPPORTED_CAPABILITIES: &'static [&'static str] =
@ -123,7 +124,7 @@ pub struct UIDStore {
#[derive(Debug)] #[derive(Debug)]
pub struct ImapType { pub struct ImapType {
account_name: String, account_name: String,
online: Arc<Mutex<bool>>, online: Arc<Mutex<(Instant, Result<()>)>>,
is_subscribed: Arc<IsSubscribedFn>, is_subscribed: Arc<IsSubscribedFn>,
connection: Arc<Mutex<ImapConnection>>, connection: Arc<Mutex<ImapConnection>>,
server_conf: ImapServerConf, server_conf: ImapServerConf,
@ -135,8 +136,8 @@ pub struct ImapType {
} }
impl MailBackend for ImapType { impl MailBackend for ImapType {
fn is_online(&self) -> bool { fn is_online(&self) -> Result<()> {
*self.online.lock().unwrap() self.online.lock().unwrap().1.clone()
} }
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> { fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
macro_rules! exit_on_error { macro_rules! exit_on_error {
@ -285,7 +286,7 @@ impl MailBackend for ImapType {
) -> Result<std::thread::ThreadId> { ) -> Result<std::thread::ThreadId> {
let folders = self.folders.clone(); let folders = self.folders.clone();
let tag_index = self.tag_index.clone(); let tag_index = self.tag_index.clone();
let conn = ImapConnection::new_connection(&self.server_conf); let conn = ImapConnection::new_connection(&self.server_conf, self.online.clone());
let main_conn = self.connection.clone(); let main_conn = self.connection.clone();
let is_online = self.online.clone(); let is_online = self.online.clone();
let uid_store = self.uid_store.clone(); let uid_store = self.uid_store.clone();
@ -342,7 +343,6 @@ impl MailBackend for ImapType {
f.children.retain(|c| keys.contains(c)); f.children.retain(|c| keys.contains(c));
} }
drop(uid_lock); drop(uid_lock);
*self.online.lock().unwrap() = true;
Ok(folders Ok(folders
.iter() .iter()
.map(|(h, f)| (*h, Box::new(Clone::clone(f)) as Folder)) .map(|(h, f)| (*h, Box::new(Clone::clone(f)) as Folder))
@ -510,11 +510,15 @@ impl ImapType {
use_starttls, use_starttls,
danger_accept_invalid_certs, danger_accept_invalid_certs,
}; };
let connection = ImapConnection::new_connection(&server_conf); let online = Arc::new(Mutex::new((
Instant::now(),
Err(MeliError::new("Account is uninitialised.")),
)));
let connection = ImapConnection::new_connection(&server_conf, online.clone());
Ok(Box::new(ImapType { Ok(Box::new(ImapType {
account_name: s.name().to_string(), account_name: s.name().to_string(),
online: Arc::new(Mutex::new(false)), online,
server_conf, server_conf,
is_subscribed: Arc::new(IsSubscribedFn(is_subscribed)), is_subscribed: Arc::new(IsSubscribedFn(is_subscribed)),
@ -532,7 +536,7 @@ impl ImapType {
} }
pub fn shell(&mut self) { pub fn shell(&mut self) {
let mut conn = ImapConnection::new_connection(&self.server_conf); let mut conn = ImapConnection::new_connection(&self.server_conf, self.online.clone());
let mut res = String::with_capacity(8 * 1024); let mut res = String::with_capacity(8 * 1024);
conn.send_command(b"NOOP").unwrap(); conn.send_command(b"NOOP").unwrap();
conn.read_response(&mut res).unwrap(); conn.read_response(&mut res).unwrap();

View File

@ -29,6 +29,8 @@ use fnv::FnvHashSet;
use native_tls::TlsConnector; use native_tls::TlsConnector;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use super::protocol_parser; use super::protocol_parser;
use super::{Capabilities, ImapServerConf}; use super::{Capabilities, ImapServerConf};
@ -44,6 +46,7 @@ pub struct ImapConnection {
pub stream: Result<ImapStream>, pub stream: Result<ImapStream>,
pub server_conf: ImapServerConf, pub server_conf: ImapServerConf,
pub capabilities: Capabilities, pub capabilities: Capabilities,
pub online: Arc<Mutex<(Instant, Result<()>)>>,
} }
impl Drop for ImapStream { impl Drop for ImapStream {
@ -317,11 +320,15 @@ impl ImapStream {
} }
impl ImapConnection { impl ImapConnection {
pub fn new_connection(server_conf: &ImapServerConf) -> ImapConnection { pub fn new_connection(
server_conf: &ImapServerConf,
online: Arc<Mutex<(Instant, Result<()>)>>,
) -> ImapConnection {
ImapConnection { ImapConnection {
stream: Err(MeliError::new("Offline".to_string())), stream: Err(MeliError::new("Offline".to_string())),
server_conf: server_conf.clone(), server_conf: server_conf.clone(),
capabilities: Capabilities::default(), capabilities: Capabilities::default(),
online,
} }
} }
@ -331,7 +338,16 @@ impl ImapConnection {
return Ok(()); return Ok(());
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.read_response(ret); let ret = stream.read_response(ret);
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);
@ -346,7 +362,16 @@ impl ImapConnection {
return Ok(()); return Ok(());
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.read_lines(ret, &termination_string); let ret = stream.read_lines(ret, &termination_string);
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);
@ -361,7 +386,16 @@ impl ImapConnection {
return Ok(()); return Ok(());
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.wait_for_continuation_request(); let ret = stream.wait_for_continuation_request();
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);
@ -376,7 +410,16 @@ impl ImapConnection {
return Ok(ret); return Ok(ret);
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.send_command(command); let ret = stream.send_command(command);
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);
@ -391,7 +434,16 @@ impl ImapConnection {
return Ok(()); return Ok(());
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.send_literal(data); let ret = stream.send_literal(data);
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);
@ -406,8 +458,16 @@ impl ImapConnection {
return Ok(()); return Ok(());
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.send_raw(raw); let ret = stream.send_raw(raw);
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);
@ -422,7 +482,16 @@ impl ImapConnection {
return Ok(()); return Ok(());
} }
} }
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?; let new_stream = ImapStream::new_connection(&self.server_conf);
if new_stream.is_err() {
*self.online.lock().unwrap() = (
Instant::now(),
Err(new_stream.as_ref().unwrap_err().clone()),
);
} else {
*self.online.lock().unwrap() = (Instant::now(), Ok(()));
}
let (capabilities, mut stream) = new_stream?;
let ret = stream.set_nonblocking(val); let ret = stream.set_nonblocking(val);
if ret.is_ok() { if ret.is_ok() {
self.stream = Ok(stream); self.stream = Ok(stream);

View File

@ -25,7 +25,7 @@ use std::sync::{Arc, Mutex, RwLock};
/// Arguments for IMAP watching functions /// Arguments for IMAP watching functions
pub struct ImapWatchKit { pub struct ImapWatchKit {
pub conn: ImapConnection, pub conn: ImapConnection,
pub is_online: Arc<Mutex<bool>>, pub is_online: Arc<Mutex<(Instant, Result<()>)>>,
pub main_conn: Arc<Mutex<ImapConnection>>, pub main_conn: Arc<Mutex<ImapConnection>>,
pub uid_store: Arc<UIDStore>, pub uid_store: Arc<UIDStore>,
pub folders: Arc<RwLock<FnvHashMap<FolderHash, ImapFolder>>>, pub folders: Arc<RwLock<FnvHashMap<FolderHash, ImapFolder>>>,
@ -62,7 +62,7 @@ pub fn poll_with_examine(kit: ImapWatchKit) -> Result<()> {
tag_index, tag_index,
} = kit; } = kit;
loop { loop {
if *is_online.lock().unwrap() { if is_online.lock().unwrap().1.is_ok() {
break; break;
} }
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -114,7 +114,7 @@ pub fn idle(kit: ImapWatchKit) -> Result<()> {
tag_index, tag_index,
} = kit; } = kit;
loop { loop {
if *is_online.lock().unwrap() { if is_online.lock().unwrap().1.is_ok() {
break; break;
} }
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));

View File

@ -31,6 +31,7 @@ use reqwest::blocking::Client;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::time::Instant;
#[macro_export] #[macro_export]
macro_rules! _impl { macro_rules! _impl {
@ -182,7 +183,7 @@ pub struct Store {
#[derive(Debug)] #[derive(Debug)]
pub struct JmapType { pub struct JmapType {
account_name: String, account_name: String,
online: Arc<Mutex<bool>>, online: Arc<Mutex<(Instant, Result<()>)>>,
is_subscribed: Arc<IsSubscribedFn>, is_subscribed: Arc<IsSubscribedFn>,
server_conf: JmapServerConf, server_conf: JmapServerConf,
connection: Arc<JmapConnection>, connection: Arc<JmapConnection>,
@ -192,8 +193,8 @@ pub struct JmapType {
} }
impl MailBackend for JmapType { impl MailBackend for JmapType {
fn is_online(&self) -> bool { fn is_online(&self) -> Result<()> {
*self.online.lock().unwrap() self.online.lock().unwrap().1.clone()
} }
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> { fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
let mut w = AsyncBuilder::new(); let mut w = AsyncBuilder::new();
@ -277,7 +278,7 @@ impl JmapType {
s: &AccountSettings, s: &AccountSettings,
is_subscribed: Box<dyn Fn(&str) -> bool + Send + Sync>, is_subscribed: Box<dyn Fn(&str) -> bool + Send + Sync>,
) -> Result<Box<dyn MailBackend>> { ) -> Result<Box<dyn MailBackend>> {
let online = Arc::new(Mutex::new(false)); let online = Arc::new(Mutex::new(Err(MeliError::new("Account is uninitialised."))));
let server_conf = JmapServerConf::new(s)?; let server_conf = JmapServerConf::new(s)?;
Ok(Box::new(JmapType { Ok(Box::new(JmapType {

View File

@ -26,16 +26,17 @@ pub struct JmapConnection {
pub session: JmapSession, pub session: JmapSession,
pub request_no: Arc<Mutex<usize>>, pub request_no: Arc<Mutex<usize>>,
pub client: Arc<Mutex<Client>>, pub client: Arc<Mutex<Client>>,
pub online_status: Arc<Mutex<bool>>, pub online_status: Arc<Mutex<(Instant, Result<()>)>>,
pub server_conf: JmapServerConf, pub server_conf: JmapServerConf,
pub account_id: Arc<Mutex<String>>, pub account_id: Arc<Mutex<String>>,
pub method_call_states: Arc<Mutex<FnvHashMap<&'static str, String>>>, pub method_call_states: Arc<Mutex<FnvHashMap<&'static str, String>>>,
} }
impl JmapConnection { impl JmapConnection {
pub fn new(server_conf: &JmapServerConf, online_status: Arc<Mutex<bool>>) -> Result<Self> { pub fn new(server_conf: &JmapServerConf, online_status: Arc<Mutex<(Instant, Result<()>)>>) -> Result<Self> {
use reqwest::header; use reqwest::header;
let mut headers = header::HeaderMap::new(); let mut headers = header::HeaderMap::new();
let connection_start = std::time::Instant::now();
headers.insert( headers.insert(
header::ACCEPT, header::ACCEPT,
header::HeaderValue::from_static("application/json"), header::HeaderValue::from_static("application/json"),
@ -68,20 +69,29 @@ impl JmapConnection {
.send()?; .send()?;
let res_text = req.text()?; let res_text = req.text()?;
let session: JmapSession = serde_json::from_str(&res_text).map_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)))?; 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()));
err
))?;
if !session if !session
.capabilities .capabilities
.contains_key("urn:ietf:params:jmap:core") .contains_key("urn:ietf:params:jmap:core")
{ {
return 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(", ")))); 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;
} }
if !session if !session
.capabilities .capabilities
.contains_key("urn:ietf:params:jmap:mail") .contains_key("urn:ietf:params:jmap:mail")
{ {
return 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(", ")))); 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;
} }
*online_status.lock().unwrap() = (Instant::new(), Ok(()));
let server_conf = server_conf.clone(); let server_conf = server_conf.clone();
Ok(JmapConnection { Ok(JmapConnection {
session, session,

View File

@ -184,8 +184,8 @@ fn move_to_cur(p: PathBuf) -> Result<PathBuf> {
} }
impl MailBackend for MaildirType { impl MailBackend for MaildirType {
fn is_online(&self) -> bool { fn is_online(&self) -> Result<()> {
true Ok(())
} }
fn folders(&self) -> Result<FnvHashMap<FolderHash, Folder>> { fn folders(&self) -> Result<FnvHashMap<FolderHash, Folder>> {

View File

@ -370,8 +370,8 @@ pub struct MboxType {
} }
impl MailBackend for MboxType { impl MailBackend for MboxType {
fn is_online(&self) -> bool { fn is_online(&self) -> Result<()> {
true Ok(())
} }
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> { fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
let mut w = AsyncBuilder::new(); let mut w = AsyncBuilder::new();

View File

@ -242,8 +242,8 @@ impl NotmuchDb {
} }
impl MailBackend for NotmuchDb { impl MailBackend for NotmuchDb {
fn is_online(&self) -> bool { fn is_online(&self) -> Result<()> {
true Ok(())
} }
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> { fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
let mut w = AsyncBuilder::new(); let mut w = AsyncBuilder::new();

View File

@ -295,29 +295,10 @@ impl Component for Listing {
} }
if right_component_width == total_cols { if right_component_width == total_cols {
if !context.is_online(self.cursor_pos.0) { if let Err(err) = context.is_online(self.cursor_pos.0) {
clear_area(grid, area); clear_area(grid, area);
write_string_to_grid( let (x, _) = write_string_to_grid(
"offline", "offline: ",
grid,
Color::Byte(243),
Color::Default,
Attr::Default,
area,
None,
);
context.dirty_areas.push_back(area);
return;
}
self.component.draw(grid, area, context);
} else if right_component_width == 0 {
self.draw_menu(grid, area, context);
} else {
self.draw_menu(grid, (upper_left, (mid, get_y(bottom_right))), context);
if !context.is_online(self.cursor_pos.0) {
clear_area(grid, (set_x(upper_left, mid + 1), bottom_right));
write_string_to_grid(
"offline",
grid, grid,
Color::Byte(243), Color::Byte(243),
Color::Default, Color::Default,
@ -325,11 +306,49 @@ impl Component for Listing {
(set_x(upper_left, mid + 1), bottom_right), (set_x(upper_left, mid + 1), bottom_right),
None, None,
); );
write_string_to_grid(
&err.to_string(),
grid,
Color::Red,
Color::Default,
Attr::Default,
(set_x(upper_left, x + 1), bottom_right),
None,
);
context.dirty_areas.push_back(area); context.dirty_areas.push_back(area);
return; return;
} else {
self.component.draw(grid, area, context);
}
} else if right_component_width == 0 {
self.draw_menu(grid, area, context);
} else {
self.draw_menu(grid, (upper_left, (mid, get_y(bottom_right))), context);
if let Err(err) = context.is_online(self.cursor_pos.0) {
clear_area(grid, (set_x(upper_left, mid + 1), bottom_right));
let (x, _) = write_string_to_grid(
"offline: ",
grid,
Color::Byte(243),
Color::Default,
Attr::Default,
(set_x(upper_left, mid + 1), bottom_right),
None,
);
write_string_to_grid(
&err.to_string(),
grid,
Color::Red,
Color::Default,
Attr::Default,
(set_x(upper_left, x + 1), bottom_right),
None,
);
context.dirty_areas.push_back(area);
} else {
self.component
.draw(grid, (set_x(upper_left, mid + 1), bottom_right), context);
} }
self.component
.draw(grid, (set_x(upper_left, mid + 1), bottom_right), context);
} }
self.dirty = false; self.dirty = false;
} }

View File

@ -991,12 +991,12 @@ impl Account {
/* Call only in Context::is_online, since only Context can launch the watcher threads if an /* Call only in Context::is_online, since only Context can launch the watcher threads if an
* account goes from offline to online. */ * account goes from offline to online. */
pub fn is_online(&mut self) -> bool { pub fn is_online(&mut self) -> Result<()> {
let ret = self.backend.read().unwrap().is_online(); let ret = self.backend.read().unwrap().is_online();
if ret != self.is_online && ret { if ret.is_ok() != self.is_online && ret.is_ok() {
self.init(); self.init();
} }
self.is_online = ret; self.is_online = ret.is_ok();
ret ret
} }

View File

@ -135,14 +135,15 @@ impl Context {
} }
} }
pub fn is_online(&mut self, account_pos: usize) -> bool { pub fn is_online(&mut self, account_pos: usize) -> Result<()> {
let Context { let Context {
ref mut accounts, ref mut accounts,
ref mut mailbox_hashes, ref mut mailbox_hashes,
.. ..
} = self; } = self;
let was_online = accounts[account_pos].is_online; let was_online = accounts[account_pos].is_online;
if accounts[account_pos].is_online() { let ret = accounts[account_pos].is_online();
if ret.is_ok() {
if !was_online { if !was_online {
for folder in accounts[account_pos].list_folders() { for folder in accounts[account_pos].list_folders() {
debug!("hash & folder: {:?} {}", folder.hash(), folder.name()); debug!("hash & folder: {:?} {}", folder.hash(), folder.name());
@ -157,10 +158,8 @@ impl Context {
*/ */
accounts[account_pos].watch(); accounts[account_pos].watch();
} }
true
} else {
false
} }
ret
} }
pub fn work_controller(&self) -> &WorkController { pub fn work_controller(&self) -> &WorkController {
@ -291,7 +290,7 @@ impl State {
s.switch_to_alternate_screen(); s.switch_to_alternate_screen();
debug!("inserting mailbox hashes:"); debug!("inserting mailbox hashes:");
for i in 0..s.context.accounts.len() { for i in 0..s.context.accounts.len() {
if s.context.is_online(i) && s.context.accounts[i].is_empty() { if s.context.is_online(i).is_ok() && s.context.accounts[i].is_empty() {
return Err(MeliError::new(format!( return Err(MeliError::new(format!(
"Account {} has no folders configured.", "Account {} has no folders configured.",
s.context.accounts[i].name() s.context.accounts[i].name()
@ -722,7 +721,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) { if self.context.is_online(i).is_ok() {
ctr += 1; ctr += 1;
} }
} }