Compare commits

..

1 Commits

Author SHA1 Message Date
WofWca
e1fbdd0ec1 refactor: un-nest handle_edit_delete
Back before e10f95b3ea
(https://github.com/chatmail/core/pull/6664) this code was inlined
into `add_parts()` so it couldn't utilize early returns.
Now it can.

I only decided not to touch the `edit_msg_showpadlock` part,
because I don't understand the intended meaning of the condition
(this might be a bug).
2026-05-15 10:19:05 +04:00
5 changed files with 75 additions and 77 deletions

View File

@@ -7056,6 +7056,11 @@ void dc_event_unref(dc_event_t* event);
/// `%1$s` will be replaced by a possibly more detailed, typically english, error description.
#define DC_STR_ERROR 112
/// "Not supported by your provider."
///
/// Used in the connectivity view.
#define DC_STR_NOT_SUPPORTED_BY_PROVIDER 113
/// "Messages"
///
/// Used as a subtitle in quota context; can be plural always.

View File

@@ -3,13 +3,13 @@
use std::collections::BTreeMap;
use std::time::Duration;
use anyhow::{Context as _, Result};
use anyhow::{Context as _, Result, anyhow};
use async_imap::types::{Quota, QuotaResource};
use crate::EventType;
use crate::context::Context;
use crate::imap::session::Session as ImapSession;
use crate::tools::{self, time_elapsed};
use crate::{EventType, stock_str};
/// quota icon in connectivity is "yellow".
pub const QUOTA_WARN_THRESHOLD_PERCENTAGE: u64 = 80;
@@ -17,25 +17,13 @@ pub const QUOTA_WARN_THRESHOLD_PERCENTAGE: u64 = 80;
/// quota icon in connectivity is "red".
pub const QUOTA_ERROR_THRESHOLD_PERCENTAGE: u64 = 95;
/// [QuotaInfo] error.
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Quota info not supported by the provider
#[error("Quota info not supported by the provider")]
NotSupportedByProvider,
/// Any other error: network, parsing, etc.
#[error("{0:#}")]
Other(#[from] anyhow::Error),
}
/// Server quota information with an update timestamp.
#[derive(Debug)]
pub struct QuotaInfo {
/// Recently loaded quota information.
/// set to `Err()` if the provider does not support quota or on other errors,
/// set to `Ok()` for valid quota information.
pub(crate) recent: Result<BTreeMap<String, Vec<QuotaResource>>, Error>,
pub(crate) recent: Result<BTreeMap<String, Vec<QuotaResource>>>,
/// When the structure was modified.
pub(crate) modified: tools::Time,
@@ -88,11 +76,9 @@ impl Context {
info!(self, "Transport {transport_id}: Updating quota.");
let quota = if session.can_check_quota() {
get_unique_quota_roots_and_usage(session, folder)
.await
.map_err(Error::Other)
get_unique_quota_roots_and_usage(session, folder).await
} else {
Err(Error::NotSupportedByProvider)
Err(anyhow!(stock_str::not_supported_by_provider(self)))
};
self.quota.write().await.insert(

View File

@@ -2352,71 +2352,74 @@ async fn handle_edit_delete(
from_id: ContactId,
) -> Result<()> {
if let Some(rfc724_mid) = mime_parser.get_header(HeaderDef::ChatEdit) {
if let Some(original_msg_id) = rfc724_mid_exists(context, rfc724_mid).await? {
if let Some(mut original_msg) =
Message::load_from_db_optional(context, original_msg_id).await?
{
if original_msg.from_id == from_id {
if let Some(part) = mime_parser.parts.first() {
let edit_msg_showpadlock = part
.param
.get_bool(Param::GuaranteeE2ee)
.unwrap_or_default();
if edit_msg_showpadlock || !original_msg.get_showpadlock() {
let new_text =
part.msg.strip_prefix(EDITED_PREFIX).unwrap_or(&part.msg);
chat::save_text_edit_to_db(context, &mut original_msg, new_text)
.await?;
} else {
warn!(context, "Edit message: Not encrypted.");
}
}
} else {
warn!(context, "Edit message: Bad sender.");
}
} else {
warn!(context, "Edit message: Database entry does not exist.");
}
} else {
let Some(original_msg_id) = rfc724_mid_exists(context, rfc724_mid).await? else {
warn!(
context,
"Edit message: rfc724_mid {rfc724_mid:?} not found."
);
return Ok(());
};
let Some(mut original_msg) =
Message::load_from_db_optional(context, original_msg_id).await?
else {
warn!(context, "Edit message: Database entry does not exist.");
return Ok(());
};
if original_msg.from_id != from_id {
warn!(context, "Edit message: Bad sender.");
return Ok(());
}
let Some(part) = mime_parser.parts.first() else {
return Ok(());
};
let edit_msg_showpadlock = part
.param
.get_bool(Param::GuaranteeE2ee)
.unwrap_or_default();
if edit_msg_showpadlock || !original_msg.get_showpadlock() {
let new_text = part.msg.strip_prefix(EDITED_PREFIX).unwrap_or(&part.msg);
chat::save_text_edit_to_db(context, &mut original_msg, new_text).await?;
} else {
warn!(context, "Edit message: Not encrypted.");
}
} else if let Some(rfc724_mid_list) = mime_parser.get_header(HeaderDef::ChatDelete)
&& let Some(part) = mime_parser.parts.first()
{
// See `message::delete_msgs_ex()`, unlike edit requests, DC doesn't send unencrypted
// deletion requests, so there's no need to support them.
if part.param.get_bool(Param::GuaranteeE2ee).unwrap_or(false) {
let mut modified_chat_ids = BTreeSet::new();
let mut msg_ids = Vec::new();
let rfc724_mid_vec: Vec<&str> = rfc724_mid_list.split_whitespace().collect();
for rfc724_mid in rfc724_mid_vec {
let rfc724_mid = rfc724_mid.trim_start_matches('<').trim_end_matches('>');
if let Some(msg_id) = message::rfc724_mid_exists(context, rfc724_mid).await? {
if let Some(msg) = Message::load_from_db_optional(context, msg_id).await? {
if msg.from_id == from_id {
message::delete_msg_locally(context, &msg).await?;
msg_ids.push(msg.id);
modified_chat_ids.insert(msg.chat_id);
} else {
warn!(context, "Delete message: Bad sender.");
}
} else {
warn!(context, "Delete message: Database entry does not exist.");
}
} else {
warn!(context, "Delete message: {rfc724_mid:?} not found.");
// Insert a tombstone so that the message will be ignored if it arrives later within a period specified in prune_tombstones().
insert_tombstone(context, rfc724_mid).await?;
}
}
message::delete_msgs_locally_done(context, &msg_ids, modified_chat_ids).await?;
} else {
if part.param.get_bool(Param::GuaranteeE2ee) != Some(true) {
warn!(context, "Delete message: Not encrypted.");
return Ok(());
}
let mut modified_chat_ids = BTreeSet::new();
let mut msg_ids = Vec::new();
let rfc724_mid_vec: Vec<&str> = rfc724_mid_list.split_whitespace().collect();
for rfc724_mid in rfc724_mid_vec {
let rfc724_mid = rfc724_mid.trim_start_matches('<').trim_end_matches('>');
let Some(msg_id) = message::rfc724_mid_exists(context, rfc724_mid).await? else {
warn!(context, "Delete message: {rfc724_mid:?} not found.");
// Insert a tombstone so that the message will be ignored if it arrives later within a period specified in prune_tombstones().
insert_tombstone(context, rfc724_mid).await?;
continue;
};
let Some(msg) = Message::load_from_db_optional(context, msg_id).await? else {
warn!(context, "Delete message: Database entry does not exist.");
continue;
};
if msg.from_id != from_id {
warn!(context, "Delete message: Bad sender.");
continue;
}
message::delete_msg_locally(context, &msg).await?;
msg_ids.push(msg.id);
modified_chat_ids.insert(msg.chat_id);
}
message::delete_msgs_locally_done(context, &msg_ids, modified_chat_ids).await?;
}
Ok(())
}

View File

@@ -418,11 +418,7 @@ impl Context {
};
match &quota.recent {
Err(e) => {
// If not supported by the provider,
// just skip the "quota" section.
if !matches!(e, crate::quota::Error::NotSupportedByProvider) {
ret += &escaper::encode_minimal(&e.to_string());
}
ret += &escaper::encode_minimal(&e.to_string());
}
Ok(quota) => {
if quota.is_empty() {

View File

@@ -189,6 +189,9 @@ pub enum StockMessage {
#[strum(props(fallback = "Error: %1$s"))]
Error = 112,
#[strum(props(fallback = "Not supported by your provider."))]
NotSupportedByProvider = 113,
#[strum(props(fallback = "Messages"))]
Messages = 114,
@@ -1134,6 +1137,11 @@ pub(crate) fn error(context: &Context, error: &str) -> String {
translated(context, StockMessage::Error).replace1(error)
}
/// Stock string: `Not supported by your provider.`.
pub(crate) fn not_supported_by_provider(context: &Context) -> String {
translated(context, StockMessage::NotSupportedByProvider)
}
/// Stock string: `Messages`.
/// Used as a subtitle in quota context; can be plural always.
pub(crate) fn messages(context: &Context) -> String {