mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-15 19:45:34 -04:00
ui: Group timeline reaction metadata into a new struct
This commit is contained in:
committed by
Jonas Platte
parent
340e0b7a03
commit
689d022b7a
@@ -16,13 +16,13 @@ use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use chrono::{Datelike, Local, TimeZone};
|
||||
use eyeball_im::ObservableVector;
|
||||
use indexmap::{map::Entry, IndexMap, IndexSet};
|
||||
use indexmap::{map::Entry, IndexMap};
|
||||
use matrix_sdk::deserialized_responses::EncryptionInfo;
|
||||
use ruma::{
|
||||
events::{
|
||||
reaction::ReactionEventContent,
|
||||
receipt::{Receipt, ReceiptType},
|
||||
relation::{Annotation, Replacement},
|
||||
relation::Replacement,
|
||||
room::{
|
||||
encrypted::RoomEncryptedEventContent,
|
||||
member::RoomMemberEventContent,
|
||||
@@ -51,6 +51,7 @@ use super::{
|
||||
},
|
||||
find_read_marker,
|
||||
item::{new_timeline_item, timeline_item},
|
||||
reactions::Reactions,
|
||||
read_receipts::maybe_add_implicit_read_receipt,
|
||||
rfind_event_by_id, rfind_event_item, EventTimelineItem, Message, OtherState, ReactionGroup,
|
||||
ReactionSenderData, Sticker, TimelineDetails, TimelineInnerState, TimelineItem,
|
||||
@@ -214,8 +215,7 @@ pub(super) struct TimelineEventHandler<'a> {
|
||||
flow: Flow,
|
||||
items: &'a mut ObservableVector<Arc<TimelineItem>>,
|
||||
next_internal_id: &'a mut u64,
|
||||
reaction_map: &'a mut HashMap<EventItemIdentifier, (ReactionSenderData, Annotation)>,
|
||||
pending_reactions: &'a mut HashMap<OwnedEventId, IndexSet<OwnedEventId>>,
|
||||
reactions: &'a mut Reactions,
|
||||
fully_read_event: &'a mut Option<OwnedEventId>,
|
||||
event_should_update_fully_read_marker: &'a mut bool,
|
||||
track_read_receipts: bool,
|
||||
@@ -251,8 +251,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
flow,
|
||||
items: &mut state.items,
|
||||
next_internal_id: &mut state.next_internal_id,
|
||||
reaction_map: &mut state.reaction_map,
|
||||
pending_reactions: &mut state.pending_reactions,
|
||||
reactions: &mut state.reactions,
|
||||
fully_read_event: &mut state.fully_read_event,
|
||||
event_should_update_fully_read_marker: &mut state.event_should_update_fully_read_marker,
|
||||
track_read_receipts,
|
||||
@@ -494,7 +493,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
return;
|
||||
};
|
||||
|
||||
let pending = self.pending_reactions.entry(event_id.to_owned()).or_default();
|
||||
let pending = self.reactions.pending.entry(event_id.to_owned()).or_default();
|
||||
|
||||
pending.insert(reaction_event_id);
|
||||
}
|
||||
@@ -502,7 +501,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
if let Flow::Remote { txn_id: Some(txn_id), .. } = &self.flow {
|
||||
let id = EventItemIdentifier::TransactionId(txn_id.clone());
|
||||
// Remove the local echo from the reaction map.
|
||||
if self.reaction_map.remove(&id).is_none() {
|
||||
if self.reactions.map.remove(&id).is_none() {
|
||||
warn!(
|
||||
"Received reaction with transaction ID, but didn't \
|
||||
find matching reaction in reaction_map"
|
||||
@@ -513,7 +512,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
sender_id: self.meta.sender.clone(),
|
||||
timestamp: self.meta.timestamp,
|
||||
};
|
||||
self.reaction_map.insert(reaction_id, (reaction_sender_data, c.relates_to));
|
||||
self.reactions.map.insert(reaction_id, (reaction_sender_data, c.relates_to));
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@@ -526,7 +525,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
#[instrument(skip_all, fields(redacts_event_id = ?redacts))]
|
||||
fn handle_redaction(&mut self, redacts: OwnedEventId, _content: RoomRedactionEventContent) {
|
||||
let id = EventItemIdentifier::EventId(redacts.clone());
|
||||
if let Some((_, rel)) = self.reaction_map.remove(&id) {
|
||||
if let Some((_, rel)) = self.reactions.map.remove(&id) {
|
||||
update_timeline_item!(self, &rel.event_id, "redaction", |event_item| {
|
||||
let Some(remote_event_item) = event_item.as_remote() else {
|
||||
error!("inconsistent state: redaction received on a non-remote event item");
|
||||
@@ -561,7 +560,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
});
|
||||
|
||||
if self.result.items_updated == 0 {
|
||||
if let Some(reactions) = self.pending_reactions.get_mut(&rel.event_id) {
|
||||
if let Some(reactions) = self.reactions.pending.get_mut(&rel.event_id) {
|
||||
if !reactions.remove(&redacts.clone()) {
|
||||
error!(
|
||||
"inconsistent state: reaction from reaction_map not in reaction list \
|
||||
@@ -609,7 +608,7 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
_content: RoomRedactionEventContent,
|
||||
) {
|
||||
let id = EventItemIdentifier::TransactionId(redacts);
|
||||
if let Some((_, rel)) = self.reaction_map.remove(&id) {
|
||||
if let Some((_, rel)) = self.reactions.map.remove(&id) {
|
||||
update_timeline_item!(self, &rel.event_id, "redaction", |event_item| {
|
||||
let Some(remote_event_item) = event_item.as_remote() else {
|
||||
error!("inconsistent state: redaction received on a non-remote event item");
|
||||
@@ -1000,13 +999,13 @@ impl<'a> TimelineEventHandler<'a> {
|
||||
match &self.flow {
|
||||
Flow::Local { .. } => None,
|
||||
Flow::Remote { event_id, .. } => {
|
||||
let reactions = self.pending_reactions.remove(event_id)?;
|
||||
let reactions = self.reactions.pending.remove(event_id)?;
|
||||
let mut bundled = IndexMap::new();
|
||||
|
||||
for reaction_event_id in reactions {
|
||||
let reaction_id = EventItemIdentifier::EventId(reaction_event_id);
|
||||
let Some((reaction_sender_data, annotation)) =
|
||||
self.reaction_map.get(&reaction_id)
|
||||
self.reactions.map.get(&reaction_id)
|
||||
else {
|
||||
error!(
|
||||
"inconsistent state: reaction from pending_reactions not in reaction_map"
|
||||
|
||||
@@ -20,7 +20,7 @@ use eyeball_im::{ObservableVector, ObservableVectorEntry, VectorSubscriber};
|
||||
#[cfg(any(test, feature = "testing"))]
|
||||
use eyeball_im_util::{FilterMapVectorSubscriber, VectorExt};
|
||||
use imbl::Vector;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
#[cfg(all(test, feature = "e2e-encryption"))]
|
||||
use matrix_sdk::crypto::OlmMachine;
|
||||
@@ -63,7 +63,7 @@ use super::{
|
||||
},
|
||||
event_item::EventItemIdentifier,
|
||||
item::{new_timeline_item, timeline_item},
|
||||
reactions::ReactionToggleResult,
|
||||
reactions::{ReactionToggleResult, Reactions},
|
||||
rfind_event_by_id, rfind_event_item,
|
||||
traits::RoomDataProvider,
|
||||
AnnotationKey, EventSendState, EventTimelineItem, InReplyToDetails, Message, Profile,
|
||||
@@ -83,11 +83,7 @@ pub(super) struct TimelineInner<P: RoomDataProvider = Room> {
|
||||
pub(super) struct TimelineInnerState {
|
||||
pub(super) items: ObservableVector<Arc<TimelineItem>>,
|
||||
pub(super) next_internal_id: u64,
|
||||
/// Reaction event / txn ID => sender and reaction data.
|
||||
pub(super) reaction_map: HashMap<EventItemIdentifier, (ReactionSenderData, Annotation)>,
|
||||
/// ID of event that is not in the timeline yet => List of reaction event
|
||||
/// IDs.
|
||||
pub(super) pending_reactions: HashMap<OwnedEventId, IndexSet<OwnedEventId>>,
|
||||
pub(super) reactions: Reactions,
|
||||
pub(super) fully_read_event: Option<OwnedEventId>,
|
||||
/// Whether the fully-read marker item should try to be updated when an
|
||||
/// event is added.
|
||||
@@ -1225,7 +1221,7 @@ impl TimelineInnerState {
|
||||
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.items.clear();
|
||||
self.reaction_map.clear();
|
||||
self.reactions.clear();
|
||||
self.fully_read_event = None;
|
||||
self.event_should_update_fully_read_marker = false;
|
||||
}
|
||||
@@ -1368,7 +1364,7 @@ fn update_timeline_reaction(
|
||||
// (should the local echo already be up-to-date after event handling?)
|
||||
if let Some(txn_id) = local_echo_to_remove {
|
||||
let id = EventItemIdentifier::TransactionId(txn_id.clone());
|
||||
if state.reaction_map.remove(&id).is_none() {
|
||||
if state.reactions.map.remove(&id).is_none() {
|
||||
warn!(
|
||||
"Tried to remove reaction by transaction ID, but didn't \
|
||||
find matching reaction in the reaction map"
|
||||
@@ -1377,7 +1373,7 @@ fn update_timeline_reaction(
|
||||
}
|
||||
// Add the remote echo to the reaction_map
|
||||
if let Some(event_id) = remote_echo_to_add {
|
||||
state.reaction_map.insert(
|
||||
state.reactions.map.insert(
|
||||
EventItemIdentifier::EventId(event_id.clone()),
|
||||
(reaction_sender_data, annotation.clone()),
|
||||
);
|
||||
|
||||
@@ -12,7 +12,15 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use ruma::{MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use indexmap::IndexSet;
|
||||
use ruma::{
|
||||
events::relation::Annotation, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId,
|
||||
OwnedUserId,
|
||||
};
|
||||
|
||||
use super::event_item::EventItemIdentifier;
|
||||
|
||||
/// Data associated with a reaction sender. It can be used to display
|
||||
/// a details UI component for a reaction with both sender
|
||||
@@ -25,6 +33,22 @@ pub struct ReactionSenderData {
|
||||
pub timestamp: MilliSecondsSinceUnixEpoch,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub(super) struct Reactions {
|
||||
/// Reaction event / txn ID => sender and reaction data.
|
||||
pub(super) map: HashMap<EventItemIdentifier, (ReactionSenderData, Annotation)>,
|
||||
/// ID of event that is not in the timeline yet => List of reaction event
|
||||
/// IDs.
|
||||
pub(super) pending: HashMap<OwnedEventId, IndexSet<OwnedEventId>>,
|
||||
}
|
||||
|
||||
impl Reactions {
|
||||
pub(super) fn clear(&mut self) {
|
||||
self.map.clear();
|
||||
self.pending.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of toggling a reaction
|
||||
///
|
||||
/// Holds the data required to update the state of the reaction in the timeline
|
||||
|
||||
Reference in New Issue
Block a user