Keep reactions when downloading partially downloaded message

This commit is contained in:
link2xt
2022-10-22 09:55:43 +00:00
parent e5c9fea52d
commit b5d238f7f4
2 changed files with 108 additions and 4 deletions

View File

@@ -80,12 +80,46 @@ impl Context {
let placeholder = Message::load_from_db(self, placeholder_msg_id).await?;
self.sql
.transaction(move |transaction| {
transaction
.execute("DELETE FROM msgs WHERE id=?;", paramsv![placeholder_msg_id])?;
// Move all the data from full message to placeholder.
// `id` stays the same, so foreign key constraints are not violated.
// For example, `reactions.msg_id` foreign key keeps pointing
// to the same message.
transaction.execute(
"UPDATE msgs SET id=? WHERE id=?",
"UPDATE msgs
SET
rfc724_mid=full.rfc724_mid,
chat_id=full.chat_id,
from_id=full.from_id,
to_id=full.to_id,
timestamp=full.timestamp,
type=full.type,
state=full.state,
msgrmsg=full.msgrmsg,
bytes=full.bytes,
txt=full.txt,
txt_raw=full.txt_raw,
param=full.param,
starred=full.starred,
timestamp_sent=full.timestamp_sent,
timestamp_rcvd=full.timestamp_rcvd,
hidden=full.hidden,
mime_headers=full.mime_headers,
mime_in_reply_to=full.mime_in_reply_to,
mime_references=full.mime_references,
move_state=full.move_state,
location_id=full.location_id,
error=full.error,
ephemeral_timer=full.ephemeral_timer,
ephemeral_timestamp=full.ephemeral_timestamp,
mime_modified=full.mime_modified,
subject=full.subject,
download_state=full.download_state,
hop_info=full.hop_info
FROM msgs AS full
WHERE msgs.id=?1 AND full.id=?2",
paramsv![placeholder_msg_id, full_msg_id],
)?;
transaction.execute("DELETE FROM msgs WHERE id=?;", paramsv![full_msg_id])?;
Ok(())
})
.await?;

View File

@@ -291,8 +291,9 @@ mod tests {
use crate::config::Config;
use crate::constants::DC_CHAT_ID_TRASH;
use crate::contact::{Contact, Origin};
use crate::download::DownloadState;
use crate::message::MessageState;
use crate::receive_imf::receive_imf;
use crate::receive_imf::{receive_imf, receive_imf_inner};
use crate::test_utils::TestContext;
#[test]
@@ -478,4 +479,73 @@ Content-Disposition: reaction\n\
Ok(())
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_partial_download_and_reaction() -> Result<()> {
let alice = TestContext::new_alice().await;
let bob = TestContext::new_bob().await;
alice
.create_chat_with_contact("Bob", "bob@example.net")
.await;
let msg_header = "From: Bob <bob@example.net>\n\
To: Alice <alice@example.org>\n\
Chat-Version: 1.0\n\
Subject: subject\n\
Message-ID: <first@example.org>\n\
Date: Sun, 14 Nov 2021 00:10:00 +0000\
Content-Type: text/plain";
let msg_full = format!("{}\n\n100k text...", msg_header);
// Alice downloads message from Bob partially.
let alice_received_message = receive_imf_inner(
&alice,
"first@example.org",
msg_header.as_bytes(),
false,
Some(100000),
false,
)
.await?
.unwrap();
let alice_msg_id = *alice_received_message.msg_ids.get(0).unwrap();
// Bob downloads own message on the other device.
let bob_received_message = receive_imf(&bob, msg_full.as_bytes(), false)
.await?
.unwrap();
let bob_msg_id = *bob_received_message.msg_ids.get(0).unwrap();
// Bob reacts to own message.
send_reaction(&bob, bob_msg_id, "👍").await.unwrap();
let bob_reaction_msg = bob.pop_sent_msg().await;
// Alice receives a reaction.
alice.recv_msg_opt(&bob_reaction_msg).await.unwrap();
let reactions = get_msg_reactions(&alice, alice_msg_id).await?;
assert_eq!(reactions.to_string(), "👍1");
let msg = Message::load_from_db(&alice, alice_msg_id).await?;
assert_eq!(msg.download_state(), DownloadState::Available);
// Alice downloads full message.
receive_imf_inner(
&alice,
"first@example.org",
msg_full.as_bytes(),
false,
None,
false,
)
.await?;
// Check that reaction is still on the message after full download.
let msg = Message::load_from_db(&alice, alice_msg_id).await?;
assert_eq!(msg.download_state(), DownloadState::Done);
let reactions = get_msg_reactions(&alice, alice_msg_id).await?;
assert_eq!(reactions.to_string(), "👍1");
Ok(())
}
}