mirror of
https://github.com/chatmail/core.git
synced 2026-04-25 01:16:29 +03:00
Connectivity view (instead of spamming the user with error_network when sth fails) (#2319)
See https://support.delta.chat/t/discussion-how-to-show-error-states/1363/10 <!-- comment --> It turns out that it's pretty easy to distinguish between lots of states (currently Error/NotConnected, Connecting…, Getting new messages… and Connected). What's not that easy is distinguishing between an actual error and no network, because if the server just doesn't respond, it could mean that we don't have network or that we are trying ipv6, but only ipv4 works. **WRT debouncing:** Sending of EVENT_CONNECTIVITY_CHANGED is not debounced, but emitted every time one of the 3 threads (Inbox, Mvbox and Sentbox) has a network error, starts fetching data, or is done fetching data. This means that it is emitted: - 9 times when dc_maybe_network() is called or we get network connection - 12 times when we lose network connection Some measurements: dc_get_connectivity() takes a little more than 1ms (in my measurements back in March), dc_get_connectivity_html() takes 10-20ms. This means that it's no immmediate problem to call them very often, might increase battery drain though. For the UI it may be a lot of work to update the title everytime; at least Android is smart enough to update the title only once. Possible problems (we don't have to worry about them now I think): - Due to the scan_folders feature, if the user has lots of folders, the state could be "Connecting..." for quite a long time, generally DC seemed a little unresponsive to me because it took so long for "Connecting..." to go away. Telegram has a state "Updating..." that sometimes comes after "Connecting...". To be done in other PRs: - Better handle the case that the password was changed on the server and authenticating fails, see https://github.com/deltachat/deltachat-core-rust/issues/1923 and https://github.com/deltachat/deltachat-core-rust/issues/1768 - maybe event debouncing (except for "Connected" connectivity events) fix https://github.com/deltachat/deltachat-android/issues/1760
This commit is contained in:
@@ -2,7 +2,6 @@ use super::Imap;
|
||||
|
||||
use anyhow::{bail, format_err, Result};
|
||||
use async_imap::extensions::idle::IdleResponse;
|
||||
use async_imap::types::UnsolicitedResponse;
|
||||
use async_std::prelude::*;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
@@ -32,24 +31,11 @@ impl Imap {
|
||||
let timeout = Duration::from_secs(23 * 60);
|
||||
let mut info = Default::default();
|
||||
|
||||
if self.server_sent_unsolicited_exists(context) {
|
||||
return Ok(info);
|
||||
}
|
||||
|
||||
if let Some(session) = self.session.take() {
|
||||
// if we have unsolicited responses we directly return
|
||||
let mut unsolicited_exists = false;
|
||||
while let Ok(response) = session.unsolicited_responses.try_recv() {
|
||||
match response {
|
||||
UnsolicitedResponse::Exists(_) => {
|
||||
warn!(context, "skip idle, got unsolicited EXISTS {:?}", response);
|
||||
unsolicited_exists = true;
|
||||
}
|
||||
_ => info!(context, "ignoring unsolicited response {:?}", response),
|
||||
}
|
||||
}
|
||||
|
||||
if unsolicited_exists {
|
||||
self.session = Some(session);
|
||||
return Ok(info);
|
||||
}
|
||||
|
||||
if let Ok(info) = self.idle_interrupt.try_recv() {
|
||||
info!(context, "skip idle, got interrupt {:?}", info);
|
||||
self.session = Some(session);
|
||||
@@ -181,7 +167,7 @@ impl Imap {
|
||||
}
|
||||
Err(err) => {
|
||||
error!(context, "could not fetch from folder: {:#}", err);
|
||||
self.trigger_reconnect()
|
||||
self.trigger_reconnect(context).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,9 +61,19 @@ impl Imap {
|
||||
|
||||
// Don't scan folders that are watched anyway
|
||||
if !watched_folders.contains(&folder.name().to_string()) && !is_drafts {
|
||||
self.fetch_new_messages(context, folder.name(), false)
|
||||
.await
|
||||
.ok_or_log_msg(context, "Can't fetch new msgs in scanned folder");
|
||||
// Drain leftover unsolicited EXISTS messages
|
||||
self.server_sent_unsolicited_exists(context);
|
||||
|
||||
loop {
|
||||
self.fetch_new_messages(context, folder.name(), false)
|
||||
.await
|
||||
.ok_or_log_msg(context, "Can't fetch new msgs in scanned folder");
|
||||
|
||||
// If the server sent an unsocicited EXISTS during the fetch, we need to fetch again
|
||||
if !self.server_sent_unsolicited_exists(context) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ impl Imap {
|
||||
info!(context, "close/expunge succeeded");
|
||||
}
|
||||
Err(err) => {
|
||||
self.trigger_reconnect();
|
||||
self.trigger_reconnect(context).await;
|
||||
return Err(Error::CloseExpungeFailed(err));
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ impl Imap {
|
||||
if self.session.is_none() {
|
||||
self.config.selected_folder = None;
|
||||
self.config.selected_folder_needs_expunge = false;
|
||||
self.trigger_reconnect();
|
||||
self.trigger_reconnect(context).await;
|
||||
return Err(Error::NoSession);
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ impl Imap {
|
||||
Ok(NewlySelected::Yes)
|
||||
}
|
||||
Err(async_imap::error::Error::ConnectionLost) => {
|
||||
self.trigger_reconnect();
|
||||
self.trigger_reconnect(context).await;
|
||||
self.config.selected_folder = None;
|
||||
Err(Error::ConnectionLost)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ impl Imap {
|
||||
}
|
||||
Err(err) => {
|
||||
self.config.selected_folder = None;
|
||||
self.trigger_reconnect();
|
||||
self.trigger_reconnect(context).await;
|
||||
Err(Error::Other(err.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user