mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
allow removing quotes on existing drafts (#2950)
allow `dc_msg_set_quote(msg, NULL)` and `msg.set_quote(None)` to simplify draft handling keeping message-ids (as needed for webxdc updates). closes #2948
This commit is contained in:
@@ -4165,7 +4165,8 @@ void dc_msg_latefiling_mediasize (dc_msg_t* msg, int width, int hei
|
||||
*
|
||||
* @memberof dc_msg_t
|
||||
* @param msg The message object to set the reply to.
|
||||
* @param quote The quote to set for msg.
|
||||
* @param quote The quote to set for the message object given as `msg`.
|
||||
* NULL removes an previously set quote.
|
||||
*/
|
||||
void dc_msg_set_quote (dc_msg_t* msg, const dc_msg_t* quote);
|
||||
|
||||
|
||||
@@ -3372,17 +3372,21 @@ pub unsafe extern "C" fn dc_msg_set_quote(msg: *mut dc_msg_t, quote: *const dc_m
|
||||
return;
|
||||
}
|
||||
let ffi_msg = &mut *msg;
|
||||
let ffi_quote = &*quote;
|
||||
|
||||
if ffi_msg.context != ffi_quote.context {
|
||||
eprintln!("ignoring attempt to quote message from a different context");
|
||||
return;
|
||||
}
|
||||
let quote_msg = if quote.is_null() {
|
||||
None
|
||||
} else {
|
||||
let ffi_quote = &*quote;
|
||||
if ffi_msg.context != ffi_quote.context {
|
||||
eprintln!("ignoring attempt to quote message from a different context");
|
||||
return;
|
||||
}
|
||||
Some(&ffi_quote.message)
|
||||
};
|
||||
|
||||
block_on(async move {
|
||||
ffi_msg
|
||||
.message
|
||||
.set_quote(&*ffi_msg.context, &ffi_quote.message)
|
||||
.set_quote(&*ffi_msg.context, quote_msg)
|
||||
.await
|
||||
.log_err(&*ffi_msg.context, "failed to set quote")
|
||||
.ok();
|
||||
|
||||
54
src/chat.rs
54
src/chat.rs
@@ -3441,6 +3441,58 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_change_quotes_on_reused_message_object() -> Result<()> {
|
||||
let t = TestContext::new_alice().await;
|
||||
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "chat").await?;
|
||||
let quote1 =
|
||||
Message::load_from_db(&t, send_text_msg(&t, chat_id, "quote1".to_string()).await?)
|
||||
.await?;
|
||||
let quote2 =
|
||||
Message::load_from_db(&t, send_text_msg(&t, chat_id, "quote2".to_string()).await?)
|
||||
.await?;
|
||||
|
||||
// save a draft
|
||||
let mut draft = Message::new(Viewtype::Text);
|
||||
draft.set_text(Some("draft text".to_string()));
|
||||
chat_id.set_draft(&t, Some(&mut draft)).await?;
|
||||
|
||||
let test = Message::load_from_db(&t, draft.id).await?;
|
||||
assert_eq!(test.text, Some("draft text".to_string()));
|
||||
assert!(test.quoted_text().is_none());
|
||||
assert!(test.quoted_message(&t).await?.is_none());
|
||||
|
||||
// add quote to same message object
|
||||
draft.set_quote(&t, Some("e1)).await?;
|
||||
chat_id.set_draft(&t, Some(&mut draft)).await?;
|
||||
|
||||
let test = Message::load_from_db(&t, draft.id).await?;
|
||||
assert_eq!(test.text, Some("draft text".to_string()));
|
||||
assert_eq!(test.quoted_text(), Some("quote1".to_string()));
|
||||
assert_eq!(test.quoted_message(&t).await?.unwrap().id, quote1.id);
|
||||
|
||||
// change quote on same message object
|
||||
draft.set_text(Some("another draft text".to_string()));
|
||||
draft.set_quote(&t, Some("e2)).await?;
|
||||
chat_id.set_draft(&t, Some(&mut draft)).await?;
|
||||
|
||||
let test = Message::load_from_db(&t, draft.id).await?;
|
||||
assert_eq!(test.text, Some("another draft text".to_string()));
|
||||
assert_eq!(test.quoted_text(), Some("quote2".to_string()));
|
||||
assert_eq!(test.quoted_message(&t).await?.unwrap().id, quote2.id);
|
||||
|
||||
// remove quote on same message object
|
||||
draft.set_quote(&t, None).await?;
|
||||
chat_id.set_draft(&t, Some(&mut draft)).await?;
|
||||
|
||||
let test = Message::load_from_db(&t, draft.id).await?;
|
||||
assert_eq!(test.text, Some("another draft text".to_string()));
|
||||
assert!(test.quoted_text().is_none());
|
||||
assert!(test.quoted_message(&t).await?.is_none());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_add_contact_to_chat_ex_add_self() {
|
||||
// Adding self to a contact should succeed, even though it's pointless.
|
||||
@@ -4746,7 +4798,7 @@ mod tests {
|
||||
// Bob quotes received message and sends a reply to Alice.
|
||||
let mut reply = Message::new(Viewtype::Text);
|
||||
reply.set_text(Some("Reply".to_owned()));
|
||||
reply.set_quote(&bob, &received_msg).await?;
|
||||
reply.set_quote(&bob, Some(&received_msg)).await?;
|
||||
let sent_reply = bob.send_msg(bob_chat.id, &mut reply).await;
|
||||
alice.recv_msg(&sent_reply).await;
|
||||
let received_reply = alice.get_last_msg().await;
|
||||
|
||||
@@ -756,36 +756,41 @@ impl Message {
|
||||
///
|
||||
/// The message itself is not required to exist in the database,
|
||||
/// it may even be deleted from the database by the time the message is prepared.
|
||||
pub async fn set_quote(&mut self, context: &Context, quote: &Message) -> Result<()> {
|
||||
ensure!(
|
||||
!quote.rfc724_mid.is_empty(),
|
||||
"Message without Message-Id cannot be quoted"
|
||||
);
|
||||
self.in_reply_to = Some(quote.rfc724_mid.clone());
|
||||
pub async fn set_quote(&mut self, context: &Context, quote: Option<&Message>) -> Result<()> {
|
||||
if let Some(quote) = quote {
|
||||
ensure!(
|
||||
!quote.rfc724_mid.is_empty(),
|
||||
"Message without Message-Id cannot be quoted"
|
||||
);
|
||||
self.in_reply_to = Some(quote.rfc724_mid.clone());
|
||||
|
||||
if quote
|
||||
.param
|
||||
.get_bool(Param::GuaranteeE2ee)
|
||||
.unwrap_or_default()
|
||||
{
|
||||
self.param.set(Param::GuaranteeE2ee, "1");
|
||||
if quote
|
||||
.param
|
||||
.get_bool(Param::GuaranteeE2ee)
|
||||
.unwrap_or_default()
|
||||
{
|
||||
self.param.set(Param::GuaranteeE2ee, "1");
|
||||
}
|
||||
|
||||
let text = quote.get_text().unwrap_or_default();
|
||||
self.param.set(
|
||||
Param::Quote,
|
||||
if text.is_empty() {
|
||||
// Use summary, similar to "Image" to avoid sending empty quote.
|
||||
quote
|
||||
.get_summary(context, None)
|
||||
.await?
|
||||
.truncated_text(500)
|
||||
.to_string()
|
||||
} else {
|
||||
text
|
||||
},
|
||||
);
|
||||
} else {
|
||||
self.in_reply_to = None;
|
||||
self.param.remove(Param::Quote);
|
||||
}
|
||||
|
||||
let text = quote.get_text().unwrap_or_default();
|
||||
self.param.set(
|
||||
Param::Quote,
|
||||
if text.is_empty() {
|
||||
// Use summary, similar to "Image" to avoid sending empty quote.
|
||||
quote
|
||||
.get_summary(context, None)
|
||||
.await?
|
||||
.truncated_text(500)
|
||||
.to_string()
|
||||
} else {
|
||||
text
|
||||
},
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1850,7 +1855,9 @@ mod tests {
|
||||
assert!(!msg.rfc724_mid.is_empty());
|
||||
|
||||
let mut msg2 = Message::new(Viewtype::Text);
|
||||
msg2.set_quote(ctx, &msg).await.expect("can't set quote");
|
||||
msg2.set_quote(ctx, Some(&msg))
|
||||
.await
|
||||
.expect("can't set quote");
|
||||
assert!(msg2.quoted_text() == msg.get_text());
|
||||
|
||||
let quoted_msg = msg2
|
||||
|
||||
@@ -1688,7 +1688,7 @@ mod tests {
|
||||
let mut new_msg = Message::new(Viewtype::Text);
|
||||
new_msg.set_text(Some("Hi".to_string()));
|
||||
if let Some(q) = quote {
|
||||
new_msg.set_quote(t, q).await?;
|
||||
new_msg.set_quote(t, Some(q)).await?;
|
||||
}
|
||||
let sent = t.send_msg(group_id, &mut new_msg).await;
|
||||
get_subject(t, sent).await
|
||||
@@ -1857,7 +1857,7 @@ mod tests {
|
||||
}
|
||||
|
||||
if reply {
|
||||
new_msg.set_quote(&t, &incoming_msg).await.unwrap();
|
||||
new_msg.set_quote(&t, Some(&incoming_msg)).await.unwrap();
|
||||
}
|
||||
|
||||
let mf = MimeFactory::from_msg(&t, &new_msg, false).await.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user