diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index c217d6125..13fb95069 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -1052,7 +1052,7 @@ pub unsafe extern "C" fn dc_can_send_edit_request( } let ctx = &*context; - block_on(message::can_send_edit_request(ctx, MsgId::new(msg_id))) + block_on(chat::can_send_edit_request(ctx, MsgId::new(msg_id))) .log_err(ctx) .unwrap_or_default() as libc::c_int } diff --git a/src/chat.rs b/src/chat.rs index 939c57840..49ea4b75f 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -3131,10 +3131,26 @@ pub async fn send_text_msg( send_msg(context, chat_id, &mut msg).await } +/// Returns true if the message can be edited. +pub async fn can_send_edit_request(context: &Context, msg_id: MsgId) -> Result { + let msg = Message::load_from_db(context, msg_id).await?; + if msg.from_id != ContactId::SELF + || msg.is_info() + || msg.viewtype == Viewtype::VideochatInvitation + || msg.has_html() + || msg.text.is_empty() + { + return Ok(false); + } + let chat = Chat::load_from_db(context, msg.get_chat_id()).await?; + let can_send = chat.can_send(context).await?; + Ok(can_send) +} + /// Sends chat members a request to edit the given message's text. pub async fn send_edit_request(context: &Context, msg_id: MsgId, new_text: String) -> Result<()> { ensure!( - message::can_send_edit_request(context, msg_id).await?, + can_send_edit_request(context, msg_id).await?, "Message cannot be edited" ); ensure!(!new_text.trim().is_empty(), "Edited text cannot be empty"); diff --git a/src/chat/chat_tests.rs b/src/chat/chat_tests.rs index 34f3f9746..c5dfb992e 100644 --- a/src/chat/chat_tests.rs +++ b/src/chat/chat_tests.rs @@ -3646,6 +3646,58 @@ async fn test_one_to_one_chat_no_group_member_timestamps() { assert!(!payload.contains("Chat-Group-Member-Timestamps:")); } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn text_can_send_edit_request() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = tcm.alice().await; + let bob = tcm.bob().await; + let chat_id = alice + .create_group_with_members(ProtectionStatus::Unprotected, "My Group", &[&bob]) + .await; + + // Alice can edit her message + let sent1 = alice.send_text(chat_id, "foo").await; + assert!(can_send_edit_request(&alice, sent1.sender_msg_id).await?); + + // Bob cannot edit Alice's message + let msg = bob.recv_msg(&sent1).await; + assert!(!can_send_edit_request(&bob, msg.id).await?); + + // HTML messages cannot be edited + let mut msg = Message::new_text("plain text".to_string()); + msg.set_html(Some("html text".to_string())); + let sent2 = alice.send_msg(chat_id, &mut msg).await; + assert!(!can_send_edit_request(&alice, sent2.sender_msg_id).await?); + + // Info messages cannot be edited + set_chat_name(&alice, chat_id, "bar").await?; + let msg = alice.get_last_msg().await; + assert!(msg.is_info()); + assert_eq!(msg.from_id, ContactId::SELF); + assert!(!can_send_edit_request(&alice, msg.id).await?); + + // Videochat invitations cannot be edited + alice + .set_config(Config::WebrtcInstance, Some("https://foo.bar")) + .await?; + let msg_id = send_videochat_invitation(&alice, chat_id).await?; + assert!(!can_send_edit_request(&alice, msg_id).await?); + + // If not text was given initally, there is nothing to edit + // (this also avoids complexity in UI element changes; focus is typos and rewordings) + let mut msg = Message::new(Viewtype::File); + msg.make_vcard(&alice, &[ContactId::SELF]).await?; + let sent3 = alice.send_msg(chat_id, &mut msg).await; + assert!(msg.text.is_empty()); + assert!(!can_send_edit_request(&alice, sent3.sender_msg_id).await?); + + // Messages in left groups cannot be edited any longer (as one cannot send to that group) + remove_contact_from_chat(&alice, chat_id, ContactId::SELF).await?; + assert!(!can_send_edit_request(&alice, sent1.sender_msg_id).await?); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_send_edit_request() -> Result<()> { let mut tcm = TestContextManager::new(); diff --git a/src/message.rs b/src/message.rs index fb51850a5..0841c7420 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1500,22 +1500,6 @@ pub async fn get_msg_read_receipts( .await } -/// Returns true if the message can be edited. -pub async fn can_send_edit_request(context: &Context, msg_id: MsgId) -> Result { - let msg = Message::load_from_db(context, msg_id).await?; - if msg.from_id != ContactId::SELF - || msg.is_info() - || msg.viewtype == Viewtype::VideochatInvitation - || msg.has_html() - || msg.text.is_empty() - { - return Ok(false); - } - let chat = Chat::load_from_db(context, msg.get_chat_id()).await?; - let can_send = chat.can_send(context).await?; - Ok(can_send) -} - pub(crate) fn guess_msgtype_from_suffix(msg: &Message) -> Option<(Viewtype, &'static str)> { msg.param .get(Param::Filename) diff --git a/src/message/message_tests.rs b/src/message/message_tests.rs index 93424001e..27a2f6953 100644 --- a/src/message/message_tests.rs +++ b/src/message/message_tests.rs @@ -783,55 +783,3 @@ async fn test_sanitize_filename_message() -> Result<()> { Ok(()) } - -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn text_can_send_edit_request() -> Result<()> { - let mut tcm = TestContextManager::new(); - let alice = tcm.alice().await; - let bob = tcm.bob().await; - let chat_id = alice - .create_group_with_members(ProtectionStatus::Unprotected, "My Group", &[&bob]) - .await; - - // Alice can edit her message - let sent1 = alice.send_text(chat_id, "foo").await; - assert!(can_send_edit_request(&alice, sent1.sender_msg_id).await?); - - // Bob cannot edit Alice's message - let msg = bob.recv_msg(&sent1).await; - assert!(!can_send_edit_request(&bob, msg.id).await?); - - // HTML messages cannot be edited - let mut msg = Message::new_text("plain text".to_string()); - msg.set_html(Some("html text".to_string())); - let sent2 = alice.send_msg(chat_id, &mut msg).await; - assert!(!can_send_edit_request(&alice, sent2.sender_msg_id).await?); - - // Info messages cannot be edited - chat::set_chat_name(&alice, chat_id, "bar").await?; - let msg = alice.get_last_msg().await; - assert!(msg.is_info()); - assert_eq!(msg.from_id, ContactId::SELF); - assert!(!can_send_edit_request(&alice, msg.id).await?); - - // Videochat invitations cannot be edited - alice - .set_config(Config::WebrtcInstance, Some("https://foo.bar")) - .await?; - let msg_id = chat::send_videochat_invitation(&alice, chat_id).await?; - assert!(!can_send_edit_request(&alice, msg_id).await?); - - // If not text was given initally, there is nothing to edit - // (this also avoids complexity in UI element changes; focus is typos and rewordings) - let mut msg = Message::new(Viewtype::File); - msg.make_vcard(&alice, &[ContactId::SELF]).await?; - let sent3 = alice.send_msg(chat_id, &mut msg).await; - assert!(msg.text.is_empty()); - assert!(!can_send_edit_request(&alice, sent3.sender_msg_id).await?); - - // Messages in left groups cannot be edited any longer (as one cannot send to that group) - chat::remove_contact_from_chat(&alice, chat_id, ContactId::SELF).await?; - assert!(!can_send_edit_request(&alice, sent1.sender_msg_id).await?); - - Ok(()) -}