Skip to content

Commit a2a4ef8

Browse files
committed
Make the SpaceService constructor non-async and instead automatically setup a client subscription when requesting the joined services subscription.
1 parent 0b14496 commit a2a4ef8

File tree

4 files changed

+70
-45
lines changed

4 files changed

+70
-45
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,8 +1261,8 @@ impl Client {
12611261
SyncServiceBuilder::new((*self.inner).clone(), self.utd_hook_manager.get().cloned())
12621262
}
12631263

1264-
pub async fn spaces_service(&self) -> Arc<SpaceService> {
1265-
let inner = UISpaceService::new((*self.inner).clone()).await;
1264+
pub fn spaces_service(&self) -> Arc<SpaceService> {
1265+
let inner = UISpaceService::new((*self.inner).clone());
12661266
Arc::new(SpaceService::new(inner))
12671267
}
12681268

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,16 @@ impl SpaceService {
4545

4646
#[matrix_sdk_ffi_macros::export]
4747
impl SpaceService {
48-
pub fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
49-
self.inner.joined_spaces().into_iter().map(Into::into).collect()
48+
pub async fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
49+
self.inner.joined_spaces().await.into_iter().map(Into::into).collect()
5050
}
5151

52-
pub fn subscribe_to_joined_spaces(
52+
#[allow(clippy::unused_async)]
53+
// This method doesn't need to be async but if its not the FFI layer panics
54+
// with "there is no no reactor running, must be called from the context
55+
// of a Tokio 1.x runtime" error because the underlying method spawns an
56+
// async task.
57+
pub async fn subscribe_to_joined_spaces(
5358
&self,
5459
listener: Box<dyn SpaceServiceJoinedSpacesListener>,
5560
) -> Arc<TaskHandle> {

crates/matrix-sdk-ui/src/spaces/mod.rs

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
1919
use eyeball::{SharedObservable, Subscriber};
2020
use futures_util::pin_mut;
21-
use matrix_sdk::{Client, deserialized_responses::SyncOrStrippedState};
21+
use matrix_sdk::{Client, deserialized_responses::SyncOrStrippedState, locks::Mutex};
2222
use matrix_sdk_common::executor::{JoinHandle, spawn};
2323
use ruma::{
2424
OwnedRoomId,
@@ -41,52 +41,62 @@ pub struct SpaceService {
4141

4242
joined_spaces: SharedObservable<Vec<SpaceServiceRoom>>,
4343

44-
room_update_handle: JoinHandle<()>,
44+
room_update_handle: Mutex<Option<JoinHandle<()>>>,
4545
}
4646

4747
impl Drop for SpaceService {
4848
fn drop(&mut self) {
49-
self.room_update_handle.abort();
49+
if let Some(handle) = &*self.room_update_handle.lock() {
50+
handle.abort();
51+
}
5052
}
5153
}
5254

5355
impl SpaceService {
54-
pub async fn new(client: Client) -> Self {
55-
let joined_spaces = SharedObservable::new(Vec::new());
56-
57-
joined_spaces.set(Self::joined_spaces_for(&client).await);
58-
59-
let client_clone = client.clone();
60-
let joined_spaces_clone = joined_spaces.clone();
61-
let all_room_updates_receiver = client.subscribe_to_all_room_updates();
62-
63-
let handle = spawn(async move {
64-
pin_mut!(all_room_updates_receiver);
56+
pub fn new(client: Client) -> Self {
57+
Self {
58+
client,
59+
joined_spaces: SharedObservable::new(Vec::new()),
60+
room_update_handle: Mutex::new(None),
61+
}
62+
}
6563

66-
loop {
67-
match all_room_updates_receiver.recv().await {
68-
Ok(_) => {
69-
let new_spaces = Self::joined_spaces_for(&client_clone).await;
70-
if new_spaces != joined_spaces_clone.get() {
71-
joined_spaces_clone.set(new_spaces);
64+
pub fn subscribe_to_joined_spaces(&self) -> Subscriber<Vec<SpaceServiceRoom>> {
65+
if self.room_update_handle.lock().is_none() {
66+
let client_clone = self.client.clone();
67+
let joined_spaces_clone = self.joined_spaces.clone();
68+
let all_room_updates_receiver = self.client.subscribe_to_all_room_updates();
69+
70+
*self.room_update_handle.lock() = Some(spawn(async move {
71+
pin_mut!(all_room_updates_receiver);
72+
73+
loop {
74+
match all_room_updates_receiver.recv().await {
75+
Ok(_) => {
76+
let new_spaces = Self::joined_spaces_for(&client_clone).await;
77+
if new_spaces != joined_spaces_clone.get() {
78+
joined_spaces_clone.set(new_spaces);
79+
}
80+
}
81+
Err(err) => {
82+
error!("error when listening to room updates: {err}");
7283
}
73-
}
74-
Err(err) => {
75-
error!("error when listening to room updates: {err}");
7684
}
7785
}
78-
}
79-
});
80-
81-
Self { client, joined_spaces, room_update_handle: handle }
82-
}
86+
}));
87+
}
8388

84-
pub fn subscribe_to_joined_spaces(&self) -> Subscriber<Vec<SpaceServiceRoom>> {
8589
self.joined_spaces.subscribe()
8690
}
8791

88-
pub fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
89-
self.joined_spaces.get()
92+
pub async fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
93+
let spaces = Self::joined_spaces_for(&self.client).await;
94+
95+
if spaces != self.joined_spaces.get() {
96+
self.joined_spaces.set(spaces.clone());
97+
}
98+
99+
spaces
90100
}
91101

92102
pub fn space_room_list(&self, space_id: OwnedRoomId) -> SpaceServiceRoomList {
@@ -181,7 +191,7 @@ mod tests {
181191
let server = MatrixMockServer::new().await;
182192
let client = server.client_builder().build().await;
183193
let user_id = client.user_id().unwrap();
184-
let space_service = SpaceService::new(client.clone()).await;
194+
let space_service = SpaceService::new(client.clone());
185195
let factory = EventFactory::new();
186196

187197
server.mock_room_state_encryption().plain().mount().await;
@@ -249,13 +259,23 @@ mod tests {
249259

250260
// Only the parent space is returned
251261
assert_eq!(
252-
space_service.joined_spaces().iter().map(|s| s.room_id.to_owned()).collect::<Vec<_>>(),
262+
space_service
263+
.joined_spaces()
264+
.await
265+
.iter()
266+
.map(|s| s.room_id.to_owned())
267+
.collect::<Vec<_>>(),
253268
vec![parent_space_id]
254269
);
255270

256271
// and it has 2 children
257272
assert_eq!(
258-
space_service.joined_spaces().iter().map(|s| s.children_count).collect::<Vec<_>>(),
273+
space_service
274+
.joined_spaces()
275+
.await
276+
.iter()
277+
.map(|s| s.children_count)
278+
.collect::<Vec<_>>(),
259279
vec![2]
260280
);
261281

@@ -318,14 +338,14 @@ mod tests {
318338
// Build the `SpaceService` and expect the room to show up with no updates
319339
// pending
320340

321-
let space_service = SpaceService::new(client.clone()).await;
341+
let space_service = SpaceService::new(client.clone());
322342

323343
let joined_spaces_subscriber = space_service.subscribe_to_joined_spaces();
324344
pin_mut!(joined_spaces_subscriber);
325345
assert_pending!(joined_spaces_subscriber);
326346

327347
assert_eq!(
328-
space_service.joined_spaces(),
348+
space_service.joined_spaces().await,
329349
vec![SpaceServiceRoom::new_from_known(client.get_room(first_space_id).unwrap(), 0)]
330350
);
331351

@@ -344,7 +364,7 @@ mod tests {
344364

345365
// And expect the list to update
346366
assert_eq!(
347-
space_service.joined_spaces(),
367+
space_service.joined_spaces().await,
348368
vec![
349369
SpaceServiceRoom::new_from_known(client.get_room(first_space_id).unwrap(), 0),
350370
SpaceServiceRoom::new_from_known(client.get_room(second_space_id).unwrap(), 0)
@@ -380,7 +400,7 @@ mod tests {
380400
// and the subscriber doesn't yield any updates
381401
assert_pending!(joined_spaces_subscriber);
382402
assert_eq!(
383-
space_service.joined_spaces(),
403+
space_service.joined_spaces().await,
384404
vec![SpaceServiceRoom::new_from_known(client.get_room(first_space_id).unwrap(), 0)]
385405
);
386406
}

crates/matrix-sdk-ui/src/spaces/room_list.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ mod tests {
206206
async fn test_room_list_pagination() {
207207
let server = MatrixMockServer::new().await;
208208
let client = server.client_builder().build().await;
209-
let space_service = SpaceService::new(client.clone()).await;
209+
let space_service = SpaceService::new(client.clone());
210210

211211
server.mock_room_state_encryption().plain().mount().await;
212212

@@ -285,7 +285,7 @@ mod tests {
285285
async fn test_room_state_updates() {
286286
let server = MatrixMockServer::new().await;
287287
let client = server.client_builder().build().await;
288-
let space_service = SpaceService::new(client.clone()).await;
288+
let space_service = SpaceService::new(client.clone());
289289

290290
let parent_space_id = room_id!("!parent_space:example.org");
291291
let child_room_id_1 = room_id!("!1:example.org");

0 commit comments

Comments
 (0)