mirror of
https://github.com/chatmail/core.git
synced 2026-09-22 13:01:21 +03:00
fix: do not emit events in set_profile_image() if contact avatar is unchanged
Previously `changed` variable was always set to `true`.
This commit is contained in:
@@ -1926,17 +1926,15 @@ pub(crate) async fn set_profile_image(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut contact = Contact::get_by_id(context, contact_id).await?;
|
let mut contact = Contact::get_by_id(context, contact_id).await?;
|
||||||
let changed = match profile_image {
|
let profile_image_opt = match profile_image {
|
||||||
AvatarAction::Change(profile_image) => {
|
AvatarAction::Change(profile_image) => Some(profile_image),
|
||||||
contact.param.set(Param::ProfileImage, profile_image);
|
AvatarAction::Delete => None,
|
||||||
true
|
|
||||||
}
|
|
||||||
AvatarAction::Delete => {
|
|
||||||
contact.param.remove(Param::ProfileImage);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
let changed = contact.param.get(Param::ProfileImage) != profile_image_opt.map(|s| s.as_str());
|
||||||
if changed {
|
if changed {
|
||||||
|
contact
|
||||||
|
.param
|
||||||
|
.set_optional(Param::ProfileImage, profile_image_opt);
|
||||||
contact.update_param(context).await?;
|
contact.update_param(context).await?;
|
||||||
context.emit_event(EventType::ContactsChanged(Some(contact_id)));
|
context.emit_event(EventType::ContactsChanged(Some(contact_id)));
|
||||||
chatlist_events::emit_chatlist_item_changed_for_contact_chat(context, contact_id).await;
|
chatlist_events::emit_chatlist_item_changed_for_contact_chat(context, contact_id).await;
|
||||||
|
|||||||
@@ -1479,3 +1479,74 @@ async fn test_name_changes() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tests that ChatlistItemChanged event is not emitted if the same contact avatar is received.
|
||||||
|
///
|
||||||
|
/// We don't test ContactsChanged event because it is emitted in any case due to "last seen" update.
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
async fn test_same_avatar_no_changed_event() -> Result<()> {
|
||||||
|
let mut tcm = TestContextManager::new();
|
||||||
|
|
||||||
|
let alice = &tcm.alice().await;
|
||||||
|
let bob = &tcm.bob().await;
|
||||||
|
let bob2 = &tcm.bob().await;
|
||||||
|
|
||||||
|
// Create chat with Bob.
|
||||||
|
// No messages will be sent to it,
|
||||||
|
// but it should be updated when Bob's avatar changes.
|
||||||
|
let alice_bob_chat = alice.create_chat(bob).await;
|
||||||
|
|
||||||
|
async fn wait_for_chatlist_event(context: &TestContext, expected_chat_id: ChatId) {
|
||||||
|
context
|
||||||
|
.evtracker
|
||||||
|
.get_matching(|evt| {
|
||||||
|
matches!(evt, EventType::ChatlistItemChanged { chat_id } if *chat_id == Some(expected_chat_id))
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One event is for adding E2EE notice ("Messages are end-to-end encrypted")
|
||||||
|
// and another event is for creating the chat itself.
|
||||||
|
wait_for_chatlist_event(alice, alice_bob_chat.id).await;
|
||||||
|
wait_for_chatlist_event(alice, alice_bob_chat.id).await;
|
||||||
|
|
||||||
|
// Create a group chat and single chat with Bob.
|
||||||
|
// Bob will send messages to group chat,
|
||||||
|
// but single chat should get ChatlistItemChanged event
|
||||||
|
// when avatar changes.
|
||||||
|
let alice_group_id = alice.create_group_with_members("test group", &[bob]).await;
|
||||||
|
let alice_sent_msg = alice.send_text(alice_group_id, "testing").await;
|
||||||
|
let bob_group_id = bob.recv_msg(&alice_sent_msg).await.chat_id;
|
||||||
|
bob_group_id.accept(bob).await?;
|
||||||
|
let bob2_group_id = bob2.recv_msg(&alice_sent_msg).await.chat_id;
|
||||||
|
bob2_group_id.accept(bob2).await?;
|
||||||
|
|
||||||
|
// Bob sets the same avatar on two devices at the same time.
|
||||||
|
// Receiving the same avatar should only emit the event about contact change once.
|
||||||
|
for profile in &[bob, bob2] {
|
||||||
|
let avatar_src = profile.get_blobdir().join("avatar.png");
|
||||||
|
tokio::fs::write(&avatar_src, test_utils::AVATAR_900x900_BYTES).await?;
|
||||||
|
profile
|
||||||
|
.set_config(Config::Selfavatar, Some(avatar_src.to_str().unwrap()))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avatar is changed by a group message,
|
||||||
|
// so chatlist item for single chat should be refreshed.
|
||||||
|
let sent = bob.send_text(bob_group_id, "Avatar change").await;
|
||||||
|
alice.recv_msg(&sent).await;
|
||||||
|
wait_for_chatlist_event(alice, alice_bob_chat.id).await;
|
||||||
|
|
||||||
|
// Avatar is the same, so single chat is not updated.
|
||||||
|
let sent2 = bob2.send_text(bob2_group_id, "No avatar change").await;
|
||||||
|
alice.recv_msg(&sent2).await;
|
||||||
|
let event_opt = alice
|
||||||
|
.evtracker
|
||||||
|
.get_matching_opt(alice, |evt| {
|
||||||
|
matches!(evt, EventType::ChatlistItemChanged { chat_id } if *chat_id == Some(alice_bob_chat.id))
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
assert_eq!(event_opt, None);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user