Skip to content

Commit fe8f77e

Browse files
committed
refactor: when leaving an Invited room also forget it
This behaviour was added only at the `RoomPreview::leave` method, but since we're slowly moving away from it we should move the forget action to the `Room::leave` method instead
1 parent 5c6238f commit fe8f77e

File tree

4 files changed

+80
-11
lines changed

4 files changed

+80
-11
lines changed

bindings/matrix-sdk-ffi/src/room_preview.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,7 @@ impl RoomPreview {
5959
let room =
6060
self.client.get_room(&self.inner.room_id).context("missing room for a room preview")?;
6161

62-
let should_forget = matches!(room.state(), matrix_sdk::RoomState::Invited);
63-
64-
room.leave().await.map_err(ClientError::from)?;
65-
66-
if should_forget {
67-
_ = self.forget().await;
68-
}
69-
70-
Ok(())
62+
Ok(room.leave().await?)
7163
}
7264

7365
/// Get the user who created the invite, if any.

crates/matrix-sdk/src/room/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ impl Room {
230230
}
231231

232232
/// Leave this room.
233+
/// If the room was in [`RoomState::Invited`] state, it'll also be forgotten
234+
/// automatically.
233235
///
234236
/// Only invited and joined rooms can be left.
235237
#[doc(alias = "reject_invitation")]
@@ -242,9 +244,20 @@ impl Room {
242244
))));
243245
}
244246

247+
// If the room was in Invited state we should also forget it when declining the
248+
// invite.
249+
let should_forget = matches!(self.state(), RoomState::Invited);
250+
245251
let request = leave_room::v3::Request::new(self.inner.room_id().to_owned());
246252
self.client.send(request).await?;
247253
self.client.base_client().room_left(self.room_id()).await?;
254+
255+
if should_forget {
256+
if let Err(error) = self.forget().await {
257+
warn!("Failed to forget room when leaving it: {error}");
258+
}
259+
}
260+
248261
Ok(())
249262
}
250263

crates/matrix-sdk/src/test_utils/mocks/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,13 @@ impl MatrixMockServer {
996996
self.mock_endpoint(mock, RoomLeaveEndpoint).expect_default_access_token()
997997
}
998998

999+
/// Creates a prebuilt mock for the endpoint used to forget a room.
1000+
pub fn mock_room_forget(&self) -> MockEndpoint<'_, RoomForgetEndpoint> {
1001+
let mock =
1002+
Mock::given(method("POST")).and(path_regex(r"^/_matrix/client/v3/rooms/.*/forget"));
1003+
self.mock_endpoint(mock, RoomForgetEndpoint).expect_default_access_token()
1004+
}
1005+
9991006
/// Create a prebuilt mock for the endpoint use to log out a session.
10001007
pub fn mock_logout(&self) -> MockEndpoint<'_, LogoutEndpoint> {
10011008
let mock = Mock::given(method("POST")).and(path("/_matrix/client/v3/logout"));
@@ -2639,6 +2646,17 @@ impl<'a> MockEndpoint<'a, RoomLeaveEndpoint> {
26392646
}
26402647
}
26412648

2649+
/// A prebuilt mock for the room forget endpoint.
2650+
pub struct RoomForgetEndpoint;
2651+
2652+
impl<'a> MockEndpoint<'a, RoomForgetEndpoint> {
2653+
/// Returns a successful response with some default data for the given room
2654+
/// id.
2655+
pub fn ok(self) -> MatrixMock<'a> {
2656+
self.respond_with(ResponseTemplate::new(200).set_body_json(json!({})))
2657+
}
2658+
}
2659+
26422660
/// A prebuilt mock for `POST /logout` request.
26432661
pub struct LogoutEndpoint;
26442662

crates/matrix-sdk/tests/integration/room/joined.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ use matrix_sdk_test::{
1919
event_factory::EventFactory,
2020
mocks::mock_encryption_state,
2121
test_json::{self, sync::CUSTOM_ROOM_POWER_LEVELS},
22-
GlobalAccountDataTestEvent, JoinedRoomBuilder, RoomAccountDataTestEvent, StateTestEvent,
23-
SyncResponseBuilder, DEFAULT_TEST_ROOM_ID,
22+
GlobalAccountDataTestEvent, InvitedRoomBuilder, JoinedRoomBuilder, RoomAccountDataTestEvent,
23+
StateTestEvent, SyncResponseBuilder, DEFAULT_TEST_ROOM_ID,
2424
};
2525
use ruma::{
2626
api::client::{membership::Invite3pidInit, receipt::create_receipt::v3::ReceiptType},
@@ -126,6 +126,52 @@ async fn test_leave_room() -> Result<(), anyhow::Error> {
126126
Ok(())
127127
}
128128

129+
#[async_test]
130+
async fn test_leave_joined_room_does_not_forget_it() -> Result<(), anyhow::Error> {
131+
let server = MatrixMockServer::new().await;
132+
let client = server.client_builder().build().await;
133+
let room_id = *DEFAULT_TEST_ROOM_ID;
134+
135+
server.mock_room_leave().ok(room_id).mock_once().mount().await;
136+
// The forget endpoint should never be called
137+
server.mock_room_forget().ok().never().mount().await;
138+
139+
let room = server.sync_joined_room(&client, room_id).await;
140+
141+
room.leave().await?;
142+
143+
assert_eq!(room.state(), RoomState::Left);
144+
145+
// The left room is still around and in the right state
146+
let left_room = client.get_room(room_id);
147+
assert!(left_room.is_some());
148+
assert_eq!(left_room.unwrap().state(), RoomState::Left);
149+
150+
Ok(())
151+
}
152+
153+
#[async_test]
154+
async fn test_leave_invited_room_also_forgets_it() -> Result<(), anyhow::Error> {
155+
let server = MatrixMockServer::new().await;
156+
let client = server.client_builder().build().await;
157+
let room_id = *DEFAULT_TEST_ROOM_ID;
158+
159+
server.mock_room_leave().ok(room_id).mock_once().mount().await;
160+
server.mock_room_forget().ok().mock_once().mount().await;
161+
162+
let invited_room_builder = InvitedRoomBuilder::new(room_id);
163+
let room = server.sync_room(&client, invited_room_builder).await;
164+
165+
room.leave().await?;
166+
167+
assert_eq!(room.state(), RoomState::Left);
168+
169+
let forgotten_room = client.get_room(room_id);
170+
assert!(forgotten_room.is_none());
171+
172+
Ok(())
173+
}
174+
129175
#[async_test]
130176
async fn test_ban_user() {
131177
let (client, server) = logged_in_client_with_server().await;

0 commit comments

Comments
 (0)