diff --git a/Cargo.lock b/Cargo.lock index bd7a0009..790d7c5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,12 +216,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "async-once-cell" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" - [[package]] name = "async-recursion" version = "1.1.1" @@ -2978,7 +2972,7 @@ dependencies = [ [[package]] name = "matrix-sdk" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "anymap2", "aquamarine", @@ -3035,7 +3029,7 @@ dependencies = [ [[package]] name = "matrix-sdk-base" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "as_variant", "async-trait", @@ -3062,7 +3056,7 @@ dependencies = [ [[package]] name = "matrix-sdk-common" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "async-trait", "eyeball-im", @@ -3085,7 +3079,7 @@ dependencies = [ [[package]] name = "matrix-sdk-crypto" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "aes", "aquamarine", @@ -3126,7 +3120,7 @@ dependencies = [ [[package]] name = "matrix-sdk-indexeddb" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "anyhow", "async-trait", @@ -3154,7 +3148,7 @@ dependencies = [ [[package]] name = "matrix-sdk-qrcode" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "byteorder", "qrcode", @@ -3166,7 +3160,7 @@ dependencies = [ [[package]] name = "matrix-sdk-sqlite" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "as_variant", "async-trait", @@ -3190,7 +3184,7 @@ dependencies = [ [[package]] name = "matrix-sdk-store-encryption" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "base64", "blake3", @@ -3209,10 +3203,9 @@ dependencies = [ [[package]] name = "matrix-sdk-ui" version = "0.11.0" -source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=4d2c261ff85f607c3af09be89044047dc84bdfec#4d2c261ff85f607c3af09be89044047dc84bdfec" +source = "git+https://github.com/matrix-org/matrix-rust-sdk.git?rev=1348525447e99cb27ddca2e23885d9bab3837297#1348525447e99cb27ddca2e23885d9bab3837297" dependencies = [ "as_variant", - "async-once-cell", "async-rx", "async-stream", "async_cell", diff --git a/Cargo.toml b/Cargo.toml index 71c2a387..23349225 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ sourceview = { package = "sourceview5", version = "0.9" } [dependencies.matrix-sdk] # version = "0.11" git = "https://github.com/matrix-org/matrix-rust-sdk.git" -rev = "4d2c261ff85f607c3af09be89044047dc84bdfec" +rev = "1348525447e99cb27ddca2e23885d9bab3837297" features = [ "socks", "sso-login", @@ -84,12 +84,12 @@ features = [ [dependencies.matrix-sdk-store-encryption] # version = "0.11" git = "https://github.com/matrix-org/matrix-rust-sdk.git" -rev = "4d2c261ff85f607c3af09be89044047dc84bdfec" +rev = "1348525447e99cb27ddca2e23885d9bab3837297" [dependencies.matrix-sdk-ui] # version = "0.11" git = "https://github.com/matrix-org/matrix-rust-sdk.git" -rev = "4d2c261ff85f607c3af09be89044047dc84bdfec" +rev = "1348525447e99cb27ddca2e23885d9bab3837297" [dependencies.ruma] # version = "0.12.2" diff --git a/src/session/model/room/timeline/event/mod.rs b/src/session/model/room/timeline/event/mod.rs index 51dcb52d..abfbf3b1 100644 --- a/src/session/model/room/timeline/event/mod.rs +++ b/src/session/model/room/timeline/event/mod.rs @@ -187,7 +187,7 @@ mod imp { let item = Arc::new(item); let prev_item = self.item.replace(Some(item.clone())); - self.reactions.update(&item.content().reactions()); + self.reactions.update(item.content().reactions()); self.update_read_receipts(item.read_receipts()); let prev_source = prev_item.as_ref().and_then(|i| i.original_json()); diff --git a/src/session/model/room/timeline/event/reaction_list.rs b/src/session/model/room/timeline/event/reaction_list.rs index 846c4759..2c9db040 100644 --- a/src/session/model/room/timeline/event/reaction_list.rs +++ b/src/session/model/room/timeline/event/reaction_list.rs @@ -51,42 +51,59 @@ mod imp { impl ReactionList { /// Update the reaction list with the given reactions. - pub(super) fn update(&self, new_reactions: &ReactionsByKeyBySender) { - let changed = { - let old_reactions = self.reactions.borrow(); - - old_reactions.len() != new_reactions.len() - || new_reactions - .keys() - .zip(old_reactions.keys()) - .any(|(new_key, old_key)| new_key != old_key) - }; + pub(super) fn update(&self, new_reactions: Option<&ReactionsByKeyBySender>) { + let mut pos = 0usize; - if changed { + let (removed, added) = { let mut reactions = self.reactions.borrow_mut(); - let user = self.user.get().expect("user is initialized"); - let prev_len = reactions.len(); - let new_len = new_reactions.len(); - *reactions = new_reactions + // Update the first groups with identical keys. + for ((new_key, group_reactions), (old_key, group)) in new_reactions .iter() - .map(|(key, reactions)| { - let group = ReactionGroup::new(key, user); - group.update(reactions); - (key.clone(), group) - }) - .collect(); - - // We cannot have the borrow active when items_changed is emitted because that - // will probably cause reads of the reactions field. - std::mem::drop(reactions); - - self.obj().items_changed(0, prev_len as u32, new_len as u32); - } else { - let reactions = self.reactions.borrow(); - for (reactions, group) in new_reactions.values().zip(reactions.values()) { - group.update(reactions); + .flat_map(|new_reactions| new_reactions.iter()) + .zip(reactions.iter()) + { + if new_key == old_key { + group.update(group_reactions); + pos += 1; + } else { + // Stop as soon as the keys do not match. + break; + } + } + + // Remove all the groups after the mismatch, if any. + let removed = reactions.len() - pos; + if removed > 0 { + reactions.truncate(pos); + } + + // Add new groups for the new keys, if any. + let new_len = new_reactions + .map(|new_reactions| new_reactions.len()) + .unwrap_or_default(); + let added = new_len - pos; + if added > 0 { + let user = self.user.get().expect("user should be initialized"); + reactions.extend( + new_reactions + .iter() + .flat_map(|new_reactions| new_reactions.iter()) + .skip(pos) + .map(|(key, group_reactions)| { + let group = ReactionGroup::new(key, user); + group.update(group_reactions); + (key.clone(), group) + }), + ); } + + (removed, added) + }; + + if removed != 0 || added != 0 { + self.obj() + .items_changed(pos as u32, removed as u32, added as u32); } } @@ -113,7 +130,7 @@ impl ReactionList { } /// Update the reaction list with the given reactions. - pub(crate) fn update(&self, new_reactions: &ReactionsByKeyBySender) { + pub(crate) fn update(&self, new_reactions: Option<&ReactionsByKeyBySender>) { self.imp().update(new_reactions); }