diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index 35ec906b8..e39587455 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -1408,6 +1408,17 @@ impl BaseClient { self.store.room(room_id) } + /// Forget the room with the given room ID. + /// + /// The room will be dropped from the room list and the store. + /// + /// # Arguments + /// + /// * `room_id` - The id of the room that should be forgotten. + pub async fn forget_room(&self, room_id: &RoomId) -> StoreResult<()> { + self.store.forget_room(room_id).await + } + /// Get the olm machine. #[cfg(feature = "e2e-encryption")] pub async fn olm_machine(&self) -> RwLockReadGuard<'_, Option> { diff --git a/crates/matrix-sdk-base/src/store/mod.rs b/crates/matrix-sdk-base/src/store/mod.rs index 9c774a769..471a17c67 100644 --- a/crates/matrix-sdk-base/src/store/mod.rs +++ b/crates/matrix-sdk-base/src/store/mod.rs @@ -304,6 +304,17 @@ impl Store { }) .clone() } + + /// Forget the room with the given room ID. + /// + /// # Arguments + /// + /// * `room_id` - The id of the room that should be forgotten. + pub(crate) async fn forget_room(&self, room_id: &RoomId) -> Result<()> { + self.inner.remove_room(room_id).await?; + self.rooms.write().unwrap().remove(room_id); + Ok(()) + } } #[cfg(not(tarpaulin_include))] diff --git a/crates/matrix-sdk-base/src/store/observable_map.rs b/crates/matrix-sdk-base/src/store/observable_map.rs index e15124a95..1650d08a1 100644 --- a/crates/matrix-sdk-base/src/store/observable_map.rs +++ b/crates/matrix-sdk-base/src/store/observable_map.rs @@ -130,6 +130,18 @@ mod impl_non_wasm32 { pub(crate) fn stream(&self) -> (Vector, impl Stream>>) { self.values.subscribe().into_values_and_batched_stream() } + + /// Remove a `V` value based on their ID, if it exists. + /// + /// Returns the removed value. + pub(crate) fn remove(&mut self, key: &L) -> Option + where + K: Borrow, + L: Hash + Eq + ?Sized, + { + let position = self.mapping.remove(key)?; + Some(self.values.remove(position)) + } } } @@ -184,6 +196,17 @@ mod impl_wasm32 { pub(crate) fn iter(&self) -> impl Iterator { self.0.values() } + + /// Remove a `V` value based on their ID, if it exists. + /// + /// Returns the removed value. + pub(crate) fn remove(&mut self, key: &L) -> Option + where + K: Borrow, + L: Hash + Eq + Ord + ?Sized, + { + self.0.remove(key) + } } } @@ -249,6 +272,33 @@ mod tests { assert_eq!(map.get(&'c'), Some(&'G')); } + #[test] + fn test_remove() { + let mut map = ObservableMap::::new(); + + assert!(map.get(&'a').is_none()); + assert!(map.get(&'b').is_none()); + assert!(map.get(&'c').is_none()); + + // new items + map.insert('a', 'e'); + map.insert('b', 'f'); + + assert_eq!(map.get(&'a'), Some(&'e')); + assert_eq!(map.get(&'b'), Some(&'f')); + assert!(map.get(&'c').is_none()); + + // remove one item + assert_eq!(map.remove(&'b'), Some('f')); + + assert_eq!(map.get(&'a'), Some(&'e')); + assert_eq!(map.get(&'b'), None); + assert_eq!(map.get(&'c'), None); + + // remove a non-existent item + assert_eq!(map.remove(&'c'), None); + } + #[test] fn test_iter() { let mut map = ObservableMap::::new(); @@ -293,6 +343,12 @@ mod tests { assert_pending!(stream); + // remove one item + map.remove(&'b'); + assert_next_eq!(stream, vec![VectorDiff::Remove { index: 0 }]); + + assert_pending!(stream); + drop(map); assert_closed!(stream); } diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs index 0db017a3a..cdcc8bfad 100644 --- a/crates/matrix-sdk/src/room/mod.rs +++ b/crates/matrix-sdk/src/room/mod.rs @@ -2663,7 +2663,7 @@ impl Room { } } - self.client.store().remove_room(self.inner.room_id()).await?; + self.client.base_client().forget_room(self.inner.room_id()).await?; Ok(()) } diff --git a/crates/matrix-sdk/tests/integration/room/left.rs b/crates/matrix-sdk/tests/integration/room/left.rs index e9fef434c..13042ae1b 100644 --- a/crates/matrix-sdk/tests/integration/room/left.rs +++ b/crates/matrix-sdk/tests/integration/room/left.rs @@ -48,6 +48,8 @@ async fn test_forget_non_direct_room() { assert_eq!(room.state(), RoomState::Left); room.forget().await.unwrap(); + + assert!(client.get_room(&DEFAULT_TEST_ROOM_ID).is_none()); } #[async_test] @@ -100,6 +102,8 @@ async fn test_forget_direct_room() { .await; room.forget().await.unwrap(); + + assert!(client.get_room(&DEFAULT_TEST_ROOM_ID).is_none()); } #[async_test]