mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 05:46:30 +03:00
edit message's text (#6550)
> _greetings from the ice of the deutsche bahn 🚂🚃🚃🚃 always a pleasure to see how well delta chat meanwhile performs in bad networks :)_ this PR adds an API to request other chat members to replace the message text of an already sent message. scope is mainly to fix typos. this feature is known from whatsapp, telegram, signal, and is [requested](https://support.delta.chat/t/retract-edit-sent-messages/1918) [since](https://support.delta.chat/t/edit-messages-in-delta-chat/899) [years](https://github.com/deltachat/deltachat-android/issues/198). technically, a message with an [`Obsoletes:`](https://datatracker.ietf.org/doc/html/rfc2076#section-3.6) header is sent out. ``` From: alice@nine To: bob@nine Message-ID: 2000@nine In-Reply-To: 1000@nine Obsoletes: 1000@nine Edited: this is the new text ``` the body is the new text, prefixed by the static text `Edited:` (which is not a header). the latter is to make the message appear more nicely in Non-Delta-MUA. save for the `In-Reply-To` header. the `Edited:` prefix is removed by Delta Chat on receiving. headers should be protected and moved to e2ee part as usual. corrected message text is flagged, and UI should show this state, in practise as "Edited" beside the date. in case, the original message is not found, nothing happens and the correction message is trashes (assuming the original was deleted). question: is the `Obsoletes:` header a good choice? i _thought_ there is some more specifica RFC, but i cannot find sth. in any case, it should be an header that is not used otherwise by MUA, to make sure no wanted messages disappear. what is NOT done and out of scope: - optimise if messages are not yet sent out. this is doable, but introduces quite some cornercaes and may not be worth the effort - replaces images or other attachments. this is also a bit cornercasy and beyond "typo fixing", and better be handled by "delete for me and others" (which may come soon, having the idea now, it seems easy :) - get edit history in any way. not sure if this is worth the effort, remember, as being a private messenger, we assume trust among chat members. it is also questionable wrt privacy, seized devices etc. - add text where nothing was before; again, scope is "typo fixing", better avoid cornercases - saved messages are not edited (this is anyway questionable) - quoted texts, that are used for the case the original message is deleted, are not updated - edits are ignored when the original message is not there yet (out of order, not yet downloaded) - message status indicator does not show if edits are sent out or not - similar to reactions, webxdc updates, sync messages. signal has the same issue :) still, connectivity should show if there are messages pending <img width="366" alt="Screenshot 2025-02-17 at 17 25 02" src="https://github.com/user-attachments/assets/a4a53996-438b-47ef-9004-2c9062eea5d7" /> corresponding iOS branch (no PR yet): https://github.com/deltachat/deltachat-ios/compare/main...r10s/edit-messages --------- Co-authored-by: l <link2xt@testrun.org>
This commit is contained in:
@@ -1039,6 +1039,23 @@ uint32_t dc_send_msg_sync (dc_context_t* context, uint32
|
||||
uint32_t dc_send_text_msg (dc_context_t* context, uint32_t chat_id, const char* text_to_send);
|
||||
|
||||
|
||||
/**
|
||||
* Send chat members a request to edit the given message's text.
|
||||
*
|
||||
* Only outgoing messages sent by self can be edited.
|
||||
* Edited messages should be flagged as such in the UI, see dc_msg_is_edited().
|
||||
* UI is informed about changes using the event #DC_EVENT_MSGS_CHANGED.
|
||||
* If the text is not changed, no event and no edit request message are sent.
|
||||
*
|
||||
* @memberof dc_context_t
|
||||
* @param context The context object as returned from dc_context_new().
|
||||
* @param msg_id The message ID of the message to edit.
|
||||
* @param new_text The new text.
|
||||
* This must not be NULL nor empty.
|
||||
*/
|
||||
void dc_send_edit_request (dc_context_t* context, uint32_t msg_id, const char* new_text);
|
||||
|
||||
|
||||
/**
|
||||
* Send invitation to a videochat.
|
||||
*
|
||||
@@ -4432,6 +4449,20 @@ int dc_msg_is_sent (const dc_msg_t* msg);
|
||||
int dc_msg_is_forwarded (const dc_msg_t* msg);
|
||||
|
||||
|
||||
/**
|
||||
* Check if the message was edited.
|
||||
*
|
||||
* Edited messages should be marked by the UI as such,
|
||||
* e.g. by the text "Edited" beside the time.
|
||||
* To edit messages, use dc_send_edit_request().
|
||||
*
|
||||
* @memberof dc_msg_t
|
||||
* @param msg The message object.
|
||||
* @return 1=message is edited, 0=message not edited.
|
||||
*/
|
||||
int dc_msg_is_edited (const dc_msg_t* msg);
|
||||
|
||||
|
||||
/**
|
||||
* Check if the message is an informational message, created by the
|
||||
* device or by another users. Such messages are not "typed" by the user but
|
||||
|
||||
@@ -1041,6 +1041,23 @@ pub unsafe extern "C" fn dc_send_text_msg(
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_send_edit_request(
|
||||
context: *mut dc_context_t,
|
||||
msg_id: u32,
|
||||
new_text: *const libc::c_char,
|
||||
) {
|
||||
if context.is_null() || new_text.is_null() {
|
||||
eprintln!("ignoring careless call to dc_send_edit_request()");
|
||||
return;
|
||||
}
|
||||
let ctx = &*context;
|
||||
let new_text = to_string_lossy(new_text);
|
||||
|
||||
block_on(chat::send_edit_request(ctx, MsgId::new(msg_id), new_text))
|
||||
.unwrap_or_log_default(ctx, "Failed to send text edit")
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_send_videochat_invitation(
|
||||
context: *mut dc_context_t,
|
||||
@@ -3683,6 +3700,16 @@ pub unsafe extern "C" fn dc_msg_is_forwarded(msg: *mut dc_msg_t) -> libc::c_int
|
||||
ffi_msg.message.is_forwarded().into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_edited(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
eprintln!("ignoring careless call to dc_msg_is_edited()");
|
||||
return 0;
|
||||
}
|
||||
let ffi_msg = &*msg;
|
||||
ffi_msg.message.is_edited().into()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_msg_is_info(msg: *mut dc_msg_t) -> libc::c_int {
|
||||
if msg.is_null() {
|
||||
|
||||
Reference in New Issue
Block a user