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 0d2eaf5
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 10 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
71 changes: 66 additions & 5 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 @@ -1998,7 +2013,7 @@ mod tests {
},
AnySyncStateEvent, EmptyStateKey, StateEventType, StateUnsigned, SyncStateEvent,
},
owned_event_id, owned_user_id, room_alias_id, room_id,
owned_event_id, owned_room_id, owned_user_id, room_alias_id, room_id,
serde::Raw,
time::SystemTime,
user_id, DeviceId, EventEncryptionAlgorithm, EventId, MilliSecondsSinceUnixEpoch,
Expand All @@ -2014,8 +2029,9 @@ mod tests {
use crate::{
rooms::RoomNotableTags,
store::{IntoStateStore, MemoryStore, StateChanges, StateStore, StoreConfig},
test_utils::logged_in_base_client,
BaseClient, MinimalStateEvent, OriginalMinimalStateEvent, RoomDisplayName,
RoomInfoNotableUpdateReasons, SessionMeta,
RoomInfoNotableUpdateReasons, RoomStateFilter, SessionMeta,
};

#[test]
Expand Down Expand Up @@ -3535,4 +3551,49 @@ 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 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 0d2eaf5

Please sign in to comment.