From 85ec8ce4a7865d9f457f81a7059e78954a1d9b7a Mon Sep 17 00:00:00 2001 From: iequidoo Date: Tue, 14 Apr 2026 08:36:04 -0300 Subject: [PATCH] feat: Get rid of MessageState::{OutPreparing, OutMdnRcvd} in the db `OutPreparing` is deprecated since 2024-12-07, replace it with `OutDraft` to let the user review such messages if any. `OutMdnRcvd` is not used in the db for new messages since a30c6ae1f79490291cc8e355111d0421372cfee1, `OutDelivered` is stored instead. --- deltachat-ffi/deltachat.h | 9 ------ deltachat-ffi/src/lot.rs | 2 -- .../src/deltachat_rpc_client/const.py | 1 - python/src/deltachat/chat.py | 29 ------------------- python/src/deltachat/message.py | 5 ---- src/chat.rs | 11 +++---- src/message.rs | 14 +++------ src/sql/migrations.rs | 12 ++++++++ src/webxdc.rs | 2 +- 9 files changed, 21 insertions(+), 64 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 5de7d8deb..ba81c8fcd 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4020,8 +4020,6 @@ int dc_msg_get_viewtype (const dc_msg_t* msg); * Marked as read on IMAP and MDN may be sent. Use dc_markseen_msgs() to mark messages as being seen. * * Outgoing message states: - * - @ref DC_STATE_OUT_PREPARING - For files which need time to be prepared before they can be sent, - * the message enters this state before @ref DC_STATE_OUT_PENDING. Deprecated. * - @ref DC_STATE_OUT_DRAFT - Message saved as draft using dc_set_draft() * - @ref DC_STATE_OUT_PENDING - The user has pressed the "send" button but the * message is not yet sent and is pending in some way. Maybe we're offline (no checkmark). @@ -5604,13 +5602,6 @@ int64_t dc_lot_get_timestamp (const dc_lot_t* lot); */ #define DC_STATE_IN_SEEN 16 -/** - * Outgoing message being prepared. See dc_msg_get_state() for details. - * - * @deprecated 2024-12-07 - */ -#define DC_STATE_OUT_PREPARING 18 - /** * Outgoing message drafted. See dc_msg_get_state() for details. */ diff --git a/deltachat-ffi/src/lot.rs b/deltachat-ffi/src/lot.rs index f6dda66c6..1c8c0af5b 100644 --- a/deltachat-ffi/src/lot.rs +++ b/deltachat-ffi/src/lot.rs @@ -230,7 +230,6 @@ pub enum LotState { MsgInFresh = 10, MsgInNoticed = 13, MsgInSeen = 16, - MsgOutPreparing = 18, MsgOutDraft = 19, MsgOutPending = 20, MsgOutFailed = 24, @@ -246,7 +245,6 @@ impl From for LotState { InFresh => LotState::MsgInFresh, InNoticed => LotState::MsgInNoticed, InSeen => LotState::MsgInSeen, - OutPreparing => LotState::MsgOutPreparing, OutDraft => LotState::MsgOutDraft, OutPending => LotState::MsgOutPending, OutFailed => LotState::MsgOutFailed, diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/const.py b/deltachat-rpc-client/src/deltachat_rpc_client/const.py index cee9536be..d3068fe9b 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/const.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/const.py @@ -190,7 +190,6 @@ class MessageState(IntEnum): IN_FRESH = 10 IN_NOTICED = 13 IN_SEEN = 16 - OUT_PREPARING = 18 OUT_DRAFT = 19 OUT_PENDING = 20 OUT_FAILED = 24 diff --git a/python/src/deltachat/chat.py b/python/src/deltachat/chat.py index a11bc8074..e9d15ac67 100644 --- a/python/src/deltachat/chat.py +++ b/python/src/deltachat/chat.py @@ -271,15 +271,6 @@ class Chat: sent out. This is the same object as was passed in, which has been modified with the new state of the core. """ - if msg.is_out_preparing(): - assert msg.id != 0 - # get a fresh copy of dc_msg, the core needs it - maybe_msg = Message.from_db(self.account, msg.id) - if maybe_msg is not None: - msg = maybe_msg - else: - raise ValueError("message does not exist") - sent_id = lib.dc_send_msg(self.account._dc_context, self.id, msg._dc_msg) if sent_id == 0: raise ValueError("message could not be sent") @@ -333,26 +324,6 @@ class Chat: raise ValueError("message could not be sent") return Message.from_db(self.account, sent_id) - def send_prepared(self, message): - """send a previously prepared message. - - :param message: a :class:`Message` instance previously returned by - :meth:`prepare_file`. - :raises ValueError: if message can not be sent. - :returns: a :class:`deltachat.message.Message` instance as sent out. - """ - assert message.id != 0 and message.is_out_preparing() - # get a fresh copy of dc_msg, the core needs it - msg = Message.from_db(self.account, message.id) - - # pass 0 as chat-id because core-docs say it's ok when out-preparing - sent_id = lib.dc_send_msg(self.account._dc_context, 0, msg._dc_msg) - if sent_id == 0: - raise ValueError("message could not be sent") - assert sent_id == msg.id - # modify message in place to avoid bad state for the caller - msg._dc_msg = Message.from_db(self.account, sent_id)._dc_msg - def set_draft(self, message): """set message as draft. diff --git a/python/src/deltachat/message.py b/python/src/deltachat/message.py index 6734c6edb..409408f48 100644 --- a/python/src/deltachat/message.py +++ b/python/src/deltachat/message.py @@ -351,17 +351,12 @@ class Message: def is_outgoing(self): """Return True if Message is outgoing.""" return lib.dc_msg_get_state(self._dc_msg) in ( - const.DC_STATE_OUT_PREPARING, const.DC_STATE_OUT_PENDING, const.DC_STATE_OUT_FAILED, const.DC_STATE_OUT_MDN_RCVD, const.DC_STATE_OUT_DELIVERED, ) - def is_out_preparing(self): - """Return True if Message is outgoing, but its file is being prepared.""" - return self._msgstate == const.DC_STATE_OUT_PREPARING - def is_out_pending(self): """Return True if Message is outgoing, but is pending (no single checkmark).""" return self._msgstate == const.DC_STATE_OUT_PENDING diff --git a/src/chat.rs b/src/chat.rs index 51feae7e9..cfcdccf65 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2625,7 +2625,7 @@ pub async fn send_msg(context: &Context, chat_id: ChatId, msg: &mut Message) -> "chat_id cannot be a special chat: {chat_id}" ); - if msg.state != MessageState::Undefined && msg.state != MessageState::OutPreparing { + if msg.state != MessageState::Undefined { msg.param.remove(Param::GuaranteeE2ee); msg.param.remove(Param::ForcePlaintext); // create_send_msg_jobs() will update `param` in the db. @@ -2733,10 +2733,7 @@ async fn prepare_send_msg( None }; - if matches!( - msg.state, - MessageState::Undefined | MessageState::OutPreparing - ) + if msg.state == MessageState::Undefined // Legacy SecureJoin "v*-request" messages are unencrypted. && msg.param.get_cmd() != SystemMessage::SecurejoinMessage && chat.is_encrypted(context).await? @@ -2949,8 +2946,8 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) - UPDATE msgs SET timestamp=( SELECT MAX(timestamp) FROM msgs WHERE - -- From `InFresh` to `OutMdnRcvd` inclusive except `OutDraft`. - state IN(10,13,16,18,20,24,26,28) AND + -- From `InFresh` to `OutDelivered` inclusive, except `OutDraft`. + state IN(10,13,16,18,20,24,26) AND hidden IN(0,1) AND chat_id=? ), diff --git a/src/message.rs b/src/message.rs index d292f5224..c6c0849fd 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1389,13 +1389,8 @@ pub enum MessageState { /// IMAP and MDN may be sent. InSeen = 16, - /// For files which need time to be prepared before they can be - /// sent, the message enters this state before - /// OutPending. - /// - /// Deprecated 2024-12-07. - OutPreparing = 18, - + // Deprecated 2024-12-07. Removed 2026-04. + // OutPreparing = 18, /// Message saved as draft. OutDraft = 19, @@ -1428,7 +1423,6 @@ impl std::fmt::Display for MessageState { Self::InFresh => "Fresh", Self::InNoticed => "Noticed", Self::InSeen => "Seen", - Self::OutPreparing => "Preparing", Self::OutDraft => "Draft", Self::OutPending => "Pending", Self::OutFailed => "Failed", @@ -1445,7 +1439,7 @@ impl MessageState { use MessageState::*; matches!( self, - OutPreparing | OutPending | OutDelivered | OutMdnRcvd // OutMdnRcvd can still fail because it could be a group message and only some recipients failed. + OutPending | OutDelivered | OutMdnRcvd // OutMdnRcvd can still fail because it could be a group message and only some recipients failed. ) } @@ -1454,7 +1448,7 @@ impl MessageState { use MessageState::*; matches!( self, - OutPreparing | OutDraft | OutPending | OutFailed | OutDelivered | OutMdnRcvd + OutDraft | OutPending | OutFailed | OutDelivered | OutMdnRcvd ) } diff --git a/src/sql/migrations.rs b/src/sql/migrations.rs index 23cc6be11..e9049c0de 100644 --- a/src/sql/migrations.rs +++ b/src/sql/migrations.rs @@ -2360,6 +2360,18 @@ ALTER TABLE contacts ADD COLUMN name_normalized TEXT; .await?; } + inc_and_check(&mut migration_version, 151)?; + if dbversion < migration_version { + sql.execute_migration( + " +UPDATE msgs SET state=26 WHERE state=28; -- Change OutMdnRcvd to OutDelivered. +UPDATE msgs SET state=19 WHERE state=18; -- Change OutPreparing to OutDraft. + ", + migration_version, + ) + .await?; + } + let new_version = sql .get_raw_config_int(VERSION_CFG) .await? diff --git a/src/webxdc.rs b/src/webxdc.rs index 29184d23f..d6d001b93 100644 --- a/src/webxdc.rs +++ b/src/webxdc.rs @@ -544,7 +544,7 @@ impl Context { let send_now = !matches!( instance.state, - MessageState::Undefined | MessageState::OutPreparing | MessageState::OutDraft + MessageState::Undefined | MessageState::OutDraft ); status_update.uid = Some(create_id());