Skip to content

Commit

Permalink
feat(room): Separate RoomState::Ban from RoomState::Left.
Browse files Browse the repository at this point in the history
This is needed to tell apart rooms in left and banned state in places like `RoomInfo` or `RoomPreview`.

The banned rooms will still count as left rooms in the sync processes.
  • Loading branch information
jmartinesp committed Dec 13, 2024
1 parent 6dcefe4 commit 184ce24
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 37 deletions.
2 changes: 2 additions & 0 deletions bindings/matrix-sdk-ffi/src/room.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub enum Membership {
Joined,
Left,
Knocked,
Banned,
}

impl From<RoomState> for Membership {
Expand All @@ -59,6 +60,7 @@ impl From<RoomState> for Membership {
RoomState::Joined => Membership::Joined,
RoomState::Left => Membership::Left,
RoomState::Knocked => Membership::Knocked,
RoomState::Ban => Membership::Banned,
}
}
}
Expand Down
112 changes: 80 additions & 32 deletions crates/matrix-sdk-base/src/rooms/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,14 @@ pub enum RoomState {
Invited,
/// The room is in a knocked state.
Knocked,
/// The room is in a banned state.
Ban,
}

impl From<&MembershipState> for RoomState {
fn from(membership_state: &MembershipState) -> Self {
// We consider Ban, Knock and Leave to be Left, because they all mean we are not
// in the room.
match membership_state {
MembershipState::Ban => Self::Left,
MembershipState::Ban => Self::Ban,
MembershipState::Invite => Self::Invited,
MembershipState::Join => Self::Joined,
MembershipState::Knock => Self::Knocked,
Expand Down Expand Up @@ -480,6 +480,7 @@ impl Room {
},
}
}
RoomState::Ban => Ok(false),

// TODO: implement logic once we have the stripped events as we'd have with an Invite
RoomState::Knocked => Ok(false),
Expand Down Expand Up @@ -1330,6 +1331,11 @@ impl RoomInfo {
self.set_state(RoomState::Knocked);
}

/// Mark this Room as banned.
pub fn mark_as_banned(&mut self) {
self.set_state(RoomState::Ban);
}

/// Set the membership RoomState of this Room
pub fn set_state(&mut self, room_state: RoomState) {
if room_state != self.room_state {
Expand Down Expand Up @@ -1886,6 +1892,8 @@ bitflags! {
const LEFT = 0b00000100;
/// The room is in a knocked state.
const KNOCKED = 0b00001000;
/// The room is in a banned state.
const BANNED = 0b00010000;
}
}

Expand All @@ -1901,6 +1909,7 @@ impl RoomStateFilter {
RoomState::Left => Self::LEFT,
RoomState::Invited => Self::INVITED,
RoomState::Knocked => Self::KNOCKED,
RoomState::Ban => Self::BANNED,
};

self.contains(bit_state)
Expand All @@ -1919,6 +1928,12 @@ impl RoomStateFilter {
if self.contains(Self::INVITED) {
states.push(RoomState::Invited);
}
if self.contains(Self::KNOCKED) {
states.push(RoomState::Knocked);
}
if self.contains(Self::BANNED) {
states.push(RoomState::Ban);
}

states
}
Expand Down Expand Up @@ -1980,43 +1995,30 @@ mod tests {
test_json::{sync_events::PINNED_EVENTS, TAG},
ALICE, BOB, CAROL,
};
use ruma::{
api::client::sync::sync_events::v3::RoomSummary as RumaSummary,
device_id, event_id,
events::{
call::member::{
ActiveFocus, ActiveLivekitFocus, Application, CallApplicationContent,
CallMemberEventContent, CallMemberStateKey, Focus, LegacyMembershipData,
LegacyMembershipDataInit, LivekitFocus, OriginalSyncCallMemberEvent,
},
room::{
canonical_alias::RoomCanonicalAliasEventContent,
encryption::{OriginalSyncRoomEncryptionEvent, RoomEncryptionEventContent},
member::{MembershipState, RoomMemberEventContent, StrippedRoomMemberEvent},
name::RoomNameEventContent,
pinned_events::RoomPinnedEventsEventContent,
},
AnySyncStateEvent, EmptyStateKey, StateEventType, StateUnsigned, SyncStateEvent,
use ruma::{api::client::sync::sync_events::v3::RoomSummary as RumaSummary, device_id, event_id, events::{
call::member::{
ActiveFocus, ActiveLivekitFocus, Application, CallApplicationContent,
CallMemberEventContent, CallMemberStateKey, Focus, LegacyMembershipData,
LegacyMembershipDataInit, LivekitFocus, OriginalSyncCallMemberEvent,
},
owned_event_id, owned_user_id, room_alias_id, room_id,
serde::Raw,
time::SystemTime,
user_id, DeviceId, EventEncryptionAlgorithm, EventId, MilliSecondsSinceUnixEpoch,
OwnedEventId, OwnedUserId, UserId,
};
room::{
canonical_alias::RoomCanonicalAliasEventContent,
encryption::{OriginalSyncRoomEncryptionEvent, RoomEncryptionEventContent},
member::{MembershipState, RoomMemberEventContent, StrippedRoomMemberEvent},
name::RoomNameEventContent,
pinned_events::RoomPinnedEventsEventContent,
},
AnySyncStateEvent, EmptyStateKey, StateEventType, StateUnsigned, SyncStateEvent,
}, owned_event_id, owned_room_id, owned_user_id, room_alias_id, room_id, serde::Raw, time::SystemTime, user_id, DeviceId, EventEncryptionAlgorithm, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId, UserId};
use serde_json::json;
use similar_asserts::assert_eq;
use stream_assert::{assert_pending, assert_ready};

use super::{compute_display_name_from_heroes, Room, RoomHero, RoomInfo, RoomState, SyncInfo};
#[cfg(any(feature = "experimental-sliding-sync", feature = "e2e-encryption"))]
use crate::latest_event::LatestEvent;
use crate::{
rooms::RoomNotableTags,
store::{IntoStateStore, MemoryStore, StateChanges, StateStore, StoreConfig},
BaseClient, MinimalStateEvent, OriginalMinimalStateEvent, RoomDisplayName,
RoomInfoNotableUpdateReasons, SessionMeta,
};
use crate::{rooms::RoomNotableTags, store::{IntoStateStore, MemoryStore, StateChanges, StateStore, StoreConfig}, BaseClient, MinimalStateEvent, OriginalMinimalStateEvent, RoomDisplayName, RoomInfoNotableUpdateReasons, RoomStateFilter, SessionMeta};
use crate::test_utils::logged_in_base_client;

#[test]
#[cfg(feature = "experimental-sliding-sync")]
Expand Down Expand Up @@ -3535,4 +3537,50 @@ mod tests {
assert_eq!(room.prev_state(), Some(RoomState::Joined));
assert_eq!(room.state(), RoomState::Left);
}

#[async_test]
async fn test_room_filters() {
let client = logged_in_base_client(None).await;
let user_id = user_id!("@me:example.org");

let joined_room_id = owned_room_id!("!joined:example.org");
client.get_or_create_room(&joined_room_id, RoomState::Joined);

let invited_room_id = owned_room_id!("!invited:example.org");
client.get_or_create_room(&invited_room_id, RoomState::Invited);

let left_room_id = owned_room_id!("!left:example.org");
client.get_or_create_room(&left_room_id, RoomState::Left);

let knocked_room_id = owned_room_id!("!knocked:example.org");
client.get_or_create_room(&knocked_room_id, RoomState::Knocked);

let banned_room_id = owned_room_id!("!banned:example.org");
client.get_or_create_room(&banned_room_id, RoomState::Ban);

let joined_rooms = client.rooms_filtered(RoomStateFilter::JOINED);
assert_eq!(joined_rooms.len(), 1);
assert_eq!(joined_rooms[0].state(), RoomState::Joined);
assert_eq!(joined_rooms[0].room_id, joined_room_id);

let invited_rooms = client.rooms_filtered(RoomStateFilter::INVITED);
assert_eq!(invited_rooms.len(), 1);
assert_eq!(invited_rooms[0].state(), RoomState::Invited);
assert_eq!(invited_rooms[0].room_id, invited_room_id);

let left_rooms = client.rooms_filtered(RoomStateFilter::LEFT);
assert_eq!(left_rooms.len(), 1);
assert_eq!(left_rooms[0].state(), RoomState::Left);
assert_eq!(left_rooms[0].room_id, left_room_id);

let knocked_rooms = client.rooms_filtered(RoomStateFilter::KNOCKED);
assert_eq!(knocked_rooms.len(), 1);
assert_eq!(knocked_rooms[0].state(), RoomState::Knocked);
assert_eq!(knocked_rooms[0].room_id, knocked_room_id);

let banned_rooms = client.rooms_filtered(RoomStateFilter::BANNED);
assert_eq!(banned_rooms.len(), 1);
assert_eq!(banned_rooms[0].state(), RoomState::Ban);
assert_eq!(banned_rooms[0].room_id, banned_room_id);
}
}
19 changes: 14 additions & 5 deletions crates/matrix-sdk-base/src/sliding_sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl BaseClient {
.or_insert_with(JoinedRoomUpdate::default)
.account_data
.append(&mut raw.to_vec()),
RoomState::Left => new_rooms
RoomState::Left | RoomState::Ban => new_rooms
.leave
.entry(room_id.to_owned())
.or_insert_with(LeftRoomUpdate::default)
Expand Down Expand Up @@ -546,7 +546,7 @@ impl BaseClient {
))
}

RoomState::Left => Ok((
RoomState::Left | RoomState::Ban => Ok((
room_info,
None,
Some(LeftRoomUpdate::new(
Expand Down Expand Up @@ -1247,7 +1247,7 @@ mod tests {
room.required_state.push(make_state_event(
user_b_id,
user_a_id.as_str(),
RoomMemberEventContent::new(membership),
RoomMemberEventContent::new(membership.clone()),
None,
));
let response = response_with_room(room_id, room);
Expand All @@ -1256,8 +1256,17 @@ mod tests {
.await
.expect("Failed to process sync");

// The room is left.
assert_eq!(client.get_room(room_id).unwrap().state(), RoomState::Left);
match membership {
MembershipState::Leave => {
// The room is left.
assert_eq!(client.get_room(room_id).unwrap().state(), RoomState::Left);
}
MembershipState::Ban => {
// The room is banned.
assert_eq!(client.get_room(room_id).unwrap().state(), RoomState::Ban);
}
_ => panic!("Unexpected membership state found: {membership}"),
}

// And it is added to the list of left rooms only.
assert!(!sync_resp.rooms.join.contains_key(room_id));
Expand Down

0 comments on commit 184ce24

Please sign in to comment.