mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +03:00
Keep reactions when downloading partially downloaded message
This commit is contained in:
@@ -80,12 +80,46 @@ impl Context {
|
|||||||
let placeholder = Message::load_from_db(self, placeholder_msg_id).await?;
|
let placeholder = Message::load_from_db(self, placeholder_msg_id).await?;
|
||||||
self.sql
|
self.sql
|
||||||
.transaction(move |transaction| {
|
.transaction(move |transaction| {
|
||||||
transaction
|
// Move all the data from full message to placeholder.
|
||||||
.execute("DELETE FROM msgs WHERE id=?;", paramsv![placeholder_msg_id])?;
|
// `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(
|
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],
|
paramsv![placeholder_msg_id, full_msg_id],
|
||||||
)?;
|
)?;
|
||||||
|
transaction.execute("DELETE FROM msgs WHERE id=?;", paramsv![full_msg_id])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -291,8 +291,9 @@ mod tests {
|
|||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::constants::DC_CHAT_ID_TRASH;
|
use crate::constants::DC_CHAT_ID_TRASH;
|
||||||
use crate::contact::{Contact, Origin};
|
use crate::contact::{Contact, Origin};
|
||||||
|
use crate::download::DownloadState;
|
||||||
use crate::message::MessageState;
|
use crate::message::MessageState;
|
||||||
use crate::receive_imf::receive_imf;
|
use crate::receive_imf::{receive_imf, receive_imf_inner};
|
||||||
use crate::test_utils::TestContext;
|
use crate::test_utils::TestContext;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -478,4 +479,73 @@ Content-Disposition: reaction\n\
|
|||||||
|
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user