Skip to content

Commit

Permalink
Merge pull request #3062 from zecakeh/ambiguity-changes
Browse files Browse the repository at this point in the history
sdk: Allow to track ambiguity changes per-room
  • Loading branch information
Hywan authored Feb 5, 2024
2 parents 87a07d9 + e0bda80 commit 6e685e2
Show file tree
Hide file tree
Showing 14 changed files with 704 additions and 57 deletions.
2 changes: 2 additions & 0 deletions crates/matrix-sdk-base/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# unreleased

- Replace the `Notification` type from Ruma in `SyncResponse` and `StateChanges` by a custom one
- The ambiguity maps in `SyncResponse` are moved to `JoinedRoom` and `LeftRoom`
- `AmbiguityCache` contains the room member's user ID

# 0.7.0

Expand Down
13 changes: 11 additions & 2 deletions crates/matrix-sdk-base/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,8 @@ impl BaseClient {
let notification_count = new_info.unread_notifications.into();
room_info.update_notification_count(notification_count);

let ambiguity_changes = ambiguity_cache.changes.remove(&room_id).unwrap_or_default();

new_rooms.join.insert(
room_id,
JoinedRoom::new(
Expand All @@ -857,6 +859,7 @@ impl BaseClient {
new_info.account_data.events,
new_info.ephemeral.events,
notification_count,
ambiguity_changes,
),
);

Expand Down Expand Up @@ -901,10 +904,17 @@ impl BaseClient {
self.handle_room_account_data(&room_id, &new_info.account_data.events, &mut changes)
.await;

let ambiguity_changes = ambiguity_cache.changes.remove(&room_id).unwrap_or_default();

changes.add_room(room_info);
new_rooms.leave.insert(
room_id,
LeftRoom::new(timeline, new_info.state.events, new_info.account_data.events),
LeftRoom::new(
timeline,
new_info.state.events,
new_info.account_data.events,
ambiguity_changes,
),
);
}

Expand Down Expand Up @@ -961,7 +971,6 @@ impl BaseClient {
presence: response.presence.events,
account_data: response.account_data.events,
to_device,
ambiguity_changes: AmbiguityChanges { changes: ambiguity_cache.changes },
notifications,
};

Expand Down
16 changes: 14 additions & 2 deletions crates/matrix-sdk-base/src/deserialized_responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

//! SDK-specific variations of response types from Ruma.
use std::{collections::BTreeMap, fmt};
use std::{collections::BTreeMap, fmt, iter};

pub use matrix_sdk_common::deserialized_responses::*;
use ruma::{
Expand All @@ -34,9 +34,12 @@ use serde::Serialize;

/// A change in ambiguity of room members that an `m.room.member` event
/// triggers.
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct AmbiguityChange {
/// The user ID of the member that is contained in the state key of the
/// `m.room.member` event.
pub member_id: OwnedUserId,
/// Is the member that is contained in the state key of the `m.room.member`
/// event itself ambiguous because of the event.
pub member_ambiguous: bool,
Expand All @@ -46,6 +49,15 @@ pub struct AmbiguityChange {
pub ambiguated_member: Option<OwnedUserId>,
}

impl AmbiguityChange {
/// Get an iterator over the user IDs listed in this `AmbiguityChange`.
pub fn user_ids(&self) -> impl Iterator<Item = &UserId> {
iter::once(&*self.member_id)
.chain(self.disambiguated_member.as_deref())
.chain(self.ambiguated_member.as_deref())
}
}

/// Collection of ambiguity changes that room member events trigger.
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
Expand Down
6 changes: 4 additions & 2 deletions crates/matrix-sdk-base/src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use crate::latest_event::{is_suitable_for_latest_event, LatestEvent, PossibleLat
#[cfg(feature = "e2e-encryption")]
use crate::RoomMemberships;
use crate::{
deserialized_responses::AmbiguityChanges,
error::Result,
read_receipts::{compute_unread_counts, PreviousEventsProvider},
rooms::RoomState,
Expand Down Expand Up @@ -299,7 +298,6 @@ impl BaseClient {

Ok(SyncResponse {
rooms: new_rooms,
ambiguity_changes: AmbiguityChanges { changes: ambiguity_cache.changes },
notifications,
// FIXME not yet supported by sliding sync.
presence: Default::default(),
Expand Down Expand Up @@ -415,6 +413,8 @@ impl BaseClient {
let notification_count = room_data.unread_notifications.clone().into();
room_info.update_notification_count(notification_count);

let ambiguity_changes = ambiguity_cache.changes.remove(room_id).unwrap_or_default();

match room_info.state() {
RoomState::Joined => {
// Ephemeral events are added separately, because we might not
Expand All @@ -430,6 +430,7 @@ impl BaseClient {
room_account_data.unwrap_or_default(),
ephemeral,
notification_count,
ambiguity_changes,
)),
None,
None,
Expand All @@ -443,6 +444,7 @@ impl BaseClient {
timeline,
raw_state_events,
room_account_data.unwrap_or_default(),
ambiguity_changes,
)),
None,
)),
Expand Down
1 change: 1 addition & 0 deletions crates/matrix-sdk-base/src/store/ambiguity_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl AmbiguityCache {
self.update(room_id, old_map, new_map);

let change = AmbiguityChange {
member_id: member_event.state_key().clone(),
disambiguated_member,
ambiguated_member,
member_ambiguous: ambiguous,
Expand Down
25 changes: 18 additions & 7 deletions crates/matrix-sdk-base/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ use ruma::{
},
push::Action,
serde::Raw,
OwnedRoomId,
OwnedEventId, OwnedRoomId,
};
use serde::{Deserialize, Serialize};

use crate::{
debug::{DebugInvitedRoom, DebugListOfRawEvents, DebugListOfRawEventsNoId},
deserialized_responses::{AmbiguityChanges, RawAnySyncOrStrippedTimelineEvent},
deserialized_responses::{AmbiguityChange, RawAnySyncOrStrippedTimelineEvent},
};

/// Internal representation of a `/sync` response.
Expand All @@ -50,8 +50,6 @@ pub struct SyncResponse {
pub account_data: Vec<Raw<AnyGlobalAccountDataEvent>>,
/// Messages sent directly between devices.
pub to_device: Vec<Raw<AnyToDeviceEvent>>,
/// Collection of ambiguity changes that room member events trigger.
pub ambiguity_changes: AmbiguityChanges,
/// New notifications per room.
pub notifications: BTreeMap<OwnedRoomId, Vec<Notification>>,
}
Expand All @@ -63,7 +61,6 @@ impl fmt::Debug for SyncResponse {
.field("rooms", &self.rooms)
.field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
.field("to_device", &DebugListOfRawEventsNoId(&self.to_device))
.field("ambiguity_changes", &self.ambiguity_changes)
.field("notifications", &self.notifications)
.finish_non_exhaustive()
}
Expand Down Expand Up @@ -108,6 +105,11 @@ pub struct JoinedRoom {
/// The ephemeral events in the room that aren't recorded in the timeline or
/// state of the room. e.g. typing.
pub ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
/// Collection of ambiguity changes that room member events trigger.
///
/// This is a map of event ID of the `m.room.member` event to the
/// details of the ambiguity change.
pub ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
}

#[cfg(not(tarpaulin_include))]
Expand All @@ -119,6 +121,7 @@ impl fmt::Debug for JoinedRoom {
.field("state", &DebugListOfRawEvents(&self.state))
.field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
.field("ephemeral", &self.ephemeral)
.field("ambiguity_changes", &self.ambiguity_changes)
.finish()
}
}
Expand All @@ -130,8 +133,9 @@ impl JoinedRoom {
account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
unread_notifications: UnreadNotificationsCount,
ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
) -> Self {
Self { unread_notifications, timeline, state, account_data, ephemeral }
Self { unread_notifications, timeline, state, account_data, ephemeral, ambiguity_changes }
}
}

Expand Down Expand Up @@ -167,15 +171,21 @@ pub struct LeftRoom {
pub state: Vec<Raw<AnySyncStateEvent>>,
/// The private data that this user has attached to this room.
pub account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
/// Collection of ambiguity changes that room member events trigger.
///
/// This is a map of event ID of the `m.room.member` event to the
/// details of the ambiguity change.
pub ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
}

impl LeftRoom {
pub(crate) fn new(
timeline: Timeline,
state: Vec<Raw<AnySyncStateEvent>>,
account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
) -> Self {
Self { timeline, state, account_data }
Self { timeline, state, account_data, ambiguity_changes }
}
}

Expand All @@ -186,6 +196,7 @@ impl fmt::Debug for LeftRoom {
.field("timeline", &self.timeline)
.field("state", &DebugListOfRawEvents(&self.state))
.field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
.field("ambiguity_changes", &self.ambiguity_changes)
.finish()
}
}
Expand Down
24 changes: 19 additions & 5 deletions crates/matrix-sdk-ui/src/event_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ use std::{collections::BTreeMap, fmt::Debug, sync::Arc};
use async_trait::async_trait;
use matrix_sdk::{sync::RoomUpdate, Client, Room};
use matrix_sdk_base::{
deserialized_responses::SyncTimelineEvent,
deserialized_responses::{AmbiguityChange, SyncTimelineEvent},
sync::{JoinedRoom, LeftRoom, Timeline},
};
use ruma::{
events::{AnyRoomAccountDataEvent, AnySyncEphemeralRoomEvent},
serde::Raw,
OwnedRoomId, RoomId,
OwnedEventId, OwnedRoomId, RoomId,
};
use tokio::{
spawn,
Expand Down Expand Up @@ -246,8 +246,13 @@ impl RoomEventGraphInner {
}

async fn handle_joined_room_update(&self, updates: JoinedRoom) -> Result<()> {
self.handle_timeline(updates.timeline, updates.ephemeral.clone(), updates.account_data)
.await?;
self.handle_timeline(
updates.timeline,
updates.ephemeral.clone(),
updates.account_data,
updates.ambiguity_changes,
)
.await?;
Ok(())
}

Expand All @@ -256,6 +261,7 @@ impl RoomEventGraphInner {
timeline: Timeline,
ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
) -> Result<()> {
let room_id = self.room.room_id();

Expand All @@ -278,13 +284,15 @@ impl RoomEventGraphInner {
prev_batch: timeline.prev_batch,
ephemeral,
account_data,
ambiguity_changes,
});

Ok(())
}

async fn handle_left_room_update(&self, updates: LeftRoom) -> Result<()> {
self.handle_timeline(updates.timeline, Vec::new(), Vec::new()).await?;
self.handle_timeline(updates.timeline, Vec::new(), Vec::new(), updates.ambiguity_changes)
.await?;
Ok(())
}

Expand Down Expand Up @@ -350,6 +358,7 @@ impl RoomEventGraphInner {
prev_batch: None,
account_data: Default::default(),
ephemeral: Default::default(),
ambiguity_changes: Default::default(),
});

Ok(())
Expand All @@ -374,5 +383,10 @@ pub enum RoomEventGraphUpdate {
/// XXX: this is temporary, until read receipts are handled in the event
/// graph
ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
/// Collection of ambiguity changes that room member events trigger.
///
/// This is a map of event ID of the `m.room.member` event to the
/// details of the ambiguity change.
ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
},
}
8 changes: 8 additions & 0 deletions crates/matrix-sdk-ui/src/timeline/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ impl TimelineBuilder {
prev_batch,
account_data,
ephemeral,
ambiguity_changes,
} => {
trace!("Received new events");

Expand All @@ -211,9 +212,16 @@ impl TimelineBuilder {
state: Default::default(),
account_data,
ephemeral,
ambiguity_changes: Default::default(),
};
inner.handle_joined_room_update(update).await;

let member_ambiguity_changes = ambiguity_changes
.values()
.flat_map(|change| change.user_ids())
.collect::<BTreeSet<_>>();
inner.force_update_sender_profiles(&member_ambiguity_changes).await;

sync_response_notify.notify_waiters();
}
}
Expand Down
Loading

0 comments on commit 6e685e2

Please sign in to comment.