Small fixes
parent
44fdc0765e
commit
3ac2c12e7a
|
@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
|
||||
- Add `select` command to select threads that match search query
|
||||
- Add support for mass copying/deleting/flagging/moving of messages
|
||||
- IMAP: add support for COMPRESS=DEFLATE and others
|
||||
Extension use can be configured with individual flags such as `use_deflate`
|
||||
- Rename EXECUTE mode to COMMAND
|
||||
- add async IMAP backend
|
||||
- add in-app SMTP support
|
||||
- ui: Show decoded source by default when viewing an Envelope's source
|
||||
- ui: Add search in pagers
|
||||
- Add managesieve REPL binary for managesieve script management
|
||||
|
|
|
@ -65,7 +65,7 @@ quote = "^1.0"
|
|||
proc-macro2 = "1.0.18"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
lto = "fat"
|
||||
opt-level = "z"
|
||||
debug = false
|
||||
|
||||
|
|
|
@ -306,10 +306,19 @@ impl MailBackend for ImapType {
|
|||
fn is_online_async(&self) -> ResultFuture<()> {
|
||||
let connection = self.connection.clone();
|
||||
Ok(Box::pin(async move {
|
||||
let mut conn = connection.lock().await;
|
||||
conn.connect().await?;
|
||||
|
||||
Ok(())
|
||||
match timeout(std::time::Duration::from_secs(3), connection.lock()).await {
|
||||
Ok(mut conn) => {
|
||||
debug!("is_online_async");
|
||||
match debug!(timeout(std::time::Duration::from_secs(3), conn.connect()).await) {
|
||||
Ok(Ok(())) => Ok(()),
|
||||
Err(err) | Ok(Err(err)) => {
|
||||
conn.stream = Err(err.clone());
|
||||
debug!(conn.connect().await)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -1627,3 +1636,15 @@ async fn fetch_hlpr(
|
|||
};
|
||||
Ok(payload)
|
||||
}
|
||||
|
||||
use futures::future::{self, Either};
|
||||
|
||||
async fn timeout<O>(dur: std::time::Duration, f: impl Future<Output = O>) -> Result<O> {
|
||||
futures::pin_mut!(f);
|
||||
match future::select(f, smol::Timer::after(dur)).await {
|
||||
Either::Left((out, _)) => Ok(out),
|
||||
Either::Right(_) => {
|
||||
Err(MeliError::new("Timed out.").set_kind(crate::error::ErrorKind::Network))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -396,9 +396,6 @@ impl ImapStream {
|
|||
last_line_idx += pos + "\r\n".len();
|
||||
}
|
||||
}
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(MeliError::from(e).set_err_kind(crate::error::ErrorKind::Network));
|
||||
}
|
||||
|
@ -634,6 +631,7 @@ impl ImapConnection {
|
|||
if let Err(err) =
|
||||
try_await(async { self.stream.as_mut()?.send_command(command).await }).await
|
||||
{
|
||||
self.stream = Err(err.clone());
|
||||
if err.kind.is_network() {
|
||||
self.connect().await?;
|
||||
}
|
||||
|
@ -646,6 +644,7 @@ impl ImapConnection {
|
|||
pub async fn send_literal(&mut self, data: &[u8]) -> Result<()> {
|
||||
if let Err(err) = try_await(async { self.stream.as_mut()?.send_literal(data).await }).await
|
||||
{
|
||||
self.stream = Err(err.clone());
|
||||
if err.kind.is_network() {
|
||||
self.connect().await?;
|
||||
}
|
||||
|
@ -657,6 +656,7 @@ impl ImapConnection {
|
|||
|
||||
pub async fn send_raw(&mut self, raw: &[u8]) -> Result<()> {
|
||||
if let Err(err) = try_await(async { self.stream.as_mut()?.send_raw(raw).await }).await {
|
||||
self.stream = Err(err.clone());
|
||||
if err.kind.is_network() {
|
||||
self.connect().await?;
|
||||
}
|
||||
|
@ -862,27 +862,12 @@ async fn read(
|
|||
}
|
||||
*prev_failure = None;
|
||||
}
|
||||
Err(e)
|
||||
if e.kind() == std::io::ErrorKind::WouldBlock
|
||||
|| e.kind() == std::io::ErrorKind::Interrupted =>
|
||||
{
|
||||
debug!(&e);
|
||||
if let Some(prev_failure) = prev_failure.as_ref() {
|
||||
if Instant::now().duration_since(*prev_failure)
|
||||
>= std::time::Duration::new(60 * 5, 0)
|
||||
{
|
||||
*err = Some(e.to_string());
|
||||
*break_flag = true;
|
||||
}
|
||||
} else {
|
||||
*prev_failure = Some(Instant::now());
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
debug!(&conn.stream);
|
||||
debug!(&e);
|
||||
*err = Some(e.to_string());
|
||||
*break_flag = true;
|
||||
*prev_failure = Some(Instant::now());
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
@ -66,7 +66,8 @@ impl BackendOp for ImapOp {
|
|||
if !exists_in_cache {
|
||||
let mut response = String::with_capacity(8 * 1024);
|
||||
{
|
||||
let mut conn = connection.lock().await;
|
||||
let mut conn =
|
||||
timeout(std::time::Duration::from_secs(3), connection.lock()).await?;
|
||||
conn.examine_mailbox(mailbox_hash, &mut response, false)
|
||||
.await?;
|
||||
conn.send_command(format!("UID FETCH {} (FLAGS RFC822)", uid).as_bytes())
|
||||
|
|
|
@ -155,7 +155,7 @@ impl Collection {
|
|||
new_hash: EnvelopeHash,
|
||||
mailbox_hash: MailboxHash,
|
||||
) -> bool {
|
||||
if !self.envelopes.write().unwrap().contains_key(&old_hash) {
|
||||
if !self.envelopes.read().unwrap().contains_key(&old_hash) {
|
||||
return false;
|
||||
}
|
||||
let mut envelope = self.envelopes.write().unwrap().remove(&old_hash).unwrap();
|
||||
|
|
|
@ -75,6 +75,7 @@ impl AccountSettings {
|
|||
#[serde(default)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MailboxConf {
|
||||
#[serde(alias = "rename")]
|
||||
pub alias: Option<String>,
|
||||
#[serde(default = "false_val")]
|
||||
pub autoload: bool,
|
||||
|
|
|
@ -903,9 +903,6 @@ async fn read_lines<'r>(
|
|||
Ok(b) => {
|
||||
ret.push_str(unsafe { std::str::from_utf8_unchecked(&buf[0..b]) });
|
||||
}
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
|
||||
panic!("block");
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(MeliError::from(e).set_kind(crate::error::ErrorKind::Network));
|
||||
}
|
||||
|
|
|
@ -384,7 +384,7 @@ impl StatusPanel {
|
|||
.enumerate()
|
||||
{
|
||||
write_string_to_grid(
|
||||
&format!("{}: {}", f.path(), f.special_usage()),
|
||||
&format!("{}: {}", f.special_usage(), f.path()),
|
||||
&mut self.content,
|
||||
self.theme_default.fg,
|
||||
self.theme_default.bg,
|
||||
|
|
|
@ -733,12 +733,10 @@ impl ThreadView {
|
|||
let total_rows = height!(area);
|
||||
|
||||
let pager_ratio = context.runtime_settings.pager.pager_ratio;
|
||||
let bottom_entity_rows = (pager_ratio * total_rows) / 100;
|
||||
let mut bottom_entity_rows = (pager_ratio * total_rows) / 100;
|
||||
|
||||
if bottom_entity_rows > total_rows {
|
||||
clear_area(grid, area, crate::conf::value(context, "theme_default"));
|
||||
context.dirty_areas.push_back(area);
|
||||
return;
|
||||
bottom_entity_rows = total_rows.saturating_sub(1);
|
||||
}
|
||||
|
||||
let mut mid = get_y(upper_left) + total_rows - bottom_entity_rows;
|
||||
|
@ -952,6 +950,9 @@ impl Component for ThreadView {
|
|||
self.dirty = false;
|
||||
return;
|
||||
}
|
||||
if !self.is_dirty() {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If user has selected another mail to view, change to it */
|
||||
if self.new_expanded_pos != self.expanded_pos {
|
||||
|
|
|
@ -1063,7 +1063,7 @@ impl fmt::Display for ProgressSpinner {
|
|||
impl Component for ProgressSpinner {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if self.dirty {
|
||||
let theme_attr = crate::conf::value(context, "theme_default");
|
||||
let theme_attr = crate::conf::value(context, "status.bar");
|
||||
clear_area(grid, area, theme_attr);
|
||||
let stage = self.stage;
|
||||
self.stage = (self.stage + 1).wrapping_rem(Self::KINDS[self.kind].len());
|
||||
|
|
Loading…
Reference in New Issue