Skip to content

Commit 257c48d

Browse files
committed
Introduce a SpaceServiceRoomList that allows pagination and provides reactive interfaces to its rooms and pagination state.
1 parent 9151cc9 commit 257c48d

File tree

5 files changed

+372
-35
lines changed

5 files changed

+372
-35
lines changed

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

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use std::{fmt::Debug, sync::Arc};
16+
17+
use futures_util::{pin_mut, StreamExt};
18+
use matrix_sdk_common::{SendOutsideWasm, SyncOutsideWasm};
1519
use matrix_sdk_ui::spaces::{
20+
room_list::SpaceServiceRoomListPaginationState as UISpaceServiceRoomListPaginationState,
1621
SpaceService as UISpaceService, SpaceServiceRoom as UISpaceServiceRoom,
22+
SpaceServiceRoomList as UISpaceServiceRoomList,
1723
};
1824
use ruma::RoomId;
1925

@@ -22,6 +28,8 @@ use crate::{
2228
error::ClientError,
2329
room::{Membership, RoomHero},
2430
room_preview::RoomType,
31+
runtime::get_runtime_handle,
32+
TaskHandle,
2533
};
2634

2735
#[derive(uniffi::Object)]
@@ -30,28 +38,104 @@ pub struct SpaceService {
3038
}
3139

3240
impl SpaceService {
33-
/// Create a new instance of `SpaceService`.
3441
pub fn new(inner: UISpaceService) -> Self {
3542
Self { inner }
3643
}
3744
}
3845

3946
#[matrix_sdk_ffi_macros::export]
4047
impl SpaceService {
41-
/// Get the list of joined spaces.
4248
pub fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
4349
self.inner.joined_spaces().into_iter().map(Into::into).collect()
4450
}
4551

46-
/// Get the top-level children for a given space.
47-
pub async fn top_level_children_for(
52+
pub fn top_level_children_for(
4853
&self,
4954
space_id: String,
50-
) -> Result<Vec<SpaceServiceRoom>, ClientError> {
55+
) -> Result<SpaceServiceRoomList, ClientError> {
5156
let space_id = RoomId::parse(space_id)?;
52-
let children = self.inner.top_level_children_for(space_id).await?;
53-
Ok(children.into_iter().map(Into::into).collect())
57+
Ok(SpaceServiceRoomList::new(self.inner.space_room_list(space_id)))
58+
}
59+
}
60+
61+
#[derive(uniffi::Object)]
62+
pub struct SpaceServiceRoomList {
63+
inner: UISpaceServiceRoomList,
64+
}
65+
66+
impl SpaceServiceRoomList {
67+
pub fn new(inner: UISpaceServiceRoomList) -> Self {
68+
Self { inner }
69+
}
70+
}
71+
72+
#[matrix_sdk_ffi_macros::export]
73+
impl SpaceServiceRoomList {
74+
pub fn pagination_state(&self) -> SpaceServiceRoomListPaginationState {
75+
self.inner.pagination_state().into()
76+
}
77+
78+
pub fn subscribe_to_pagiation_state_updates(
79+
&self,
80+
listener: Box<dyn SpaceServiceRoomListPaginationStateListener>,
81+
) {
82+
let pagination_state = self.inner.subscribe_to_pagination_state_updates();
83+
84+
Arc::new(TaskHandle::new(get_runtime_handle().spawn(async move {
85+
pin_mut!(pagination_state);
86+
87+
while let Some(state) = pagination_state.next().await {
88+
listener.on_update(state.into());
89+
}
90+
})));
5491
}
92+
93+
pub fn rooms(&self) -> Vec<SpaceServiceRoom> {
94+
self.inner.rooms().into_iter().map(Into::into).collect()
95+
}
96+
97+
pub fn subscribe_to_room_update(&self, listener: Box<dyn SpaceServiceRoomListEntriesListener>) {
98+
let entries_stream = self.inner.subscribe_to_room_updates();
99+
100+
Arc::new(TaskHandle::new(get_runtime_handle().spawn(async move {
101+
pin_mut!(entries_stream);
102+
103+
while let Some(rooms) = entries_stream.next().await {
104+
listener.on_update(rooms.into_iter().map(Into::into).collect());
105+
}
106+
})));
107+
}
108+
}
109+
110+
#[derive(uniffi::Enum)]
111+
pub enum SpaceServiceRoomListPaginationState {
112+
Idle { end_reached: bool },
113+
Loading,
114+
}
115+
116+
impl From<UISpaceServiceRoomListPaginationState> for SpaceServiceRoomListPaginationState {
117+
fn from(state: UISpaceServiceRoomListPaginationState) -> Self {
118+
match state {
119+
UISpaceServiceRoomListPaginationState::Idle { end_reached } => {
120+
SpaceServiceRoomListPaginationState::Idle { end_reached }
121+
}
122+
UISpaceServiceRoomListPaginationState::Loading => {
123+
SpaceServiceRoomListPaginationState::Loading
124+
}
125+
}
126+
}
127+
}
128+
129+
#[matrix_sdk_ffi_macros::export(callback_interface)]
130+
pub trait SpaceServiceRoomListPaginationStateListener:
131+
SendOutsideWasm + SyncOutsideWasm + Debug
132+
{
133+
fn on_update(&self, pagination_state: SpaceServiceRoomListPaginationState);
134+
}
135+
136+
#[matrix_sdk_ffi_macros::export(callback_interface)]
137+
pub trait SpaceServiceRoomListEntriesListener: SendOutsideWasm + SyncOutsideWasm + Debug {
138+
fn on_update(&self, rooms: Vec<SpaceServiceRoom>);
55139
}
56140

57141
#[derive(uniffi::Record)]

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

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414

1515
//! High level interfaces for working with Spaces
1616
//!
17-
//! See [`SpaceDiscoveryService`] for details.
17+
//! See [`SpaceService`] for details.
1818
19-
use matrix_sdk::{Client, Error};
19+
use matrix_sdk::Client;
2020
use ruma::OwnedRoomId;
21-
use ruma::api::client::space::get_hierarchy;
2221

23-
pub use crate::spaces::room::SpaceServiceRoom;
22+
pub use crate::spaces::{room::SpaceServiceRoom, room_list::SpaceServiceRoomList};
2423

2524
pub mod room;
25+
pub mod room_list;
2626

2727
pub struct SpaceService {
2828
client: Client,
@@ -38,36 +38,25 @@ impl SpaceService {
3838
.joined_rooms()
3939
.into_iter()
4040
.filter_map(|room| if room.is_space() { Some(room) } else { None })
41-
.map(|room| SpaceServiceRoom::new_from_known(room))
41+
.map(SpaceServiceRoom::new_from_known)
4242
.collect::<Vec<_>>()
4343
}
4444

45-
pub async fn top_level_children_for(
46-
&self,
47-
space_id: OwnedRoomId,
48-
) -> Result<Vec<SpaceServiceRoom>, Error> {
49-
let request = get_hierarchy::v1::Request::new(space_id.clone());
50-
51-
let result = self.client.send(request).await?;
52-
53-
Ok(result
54-
.rooms
55-
.iter()
56-
.map(|room| (&room.summary, self.client.get_room(&room.summary.room_id)))
57-
.map(|(summary, room)| SpaceServiceRoom::new_from_summary(summary, room))
58-
.collect::<Vec<_>>())
45+
pub fn space_room_list(&self, space_id: OwnedRoomId) -> SpaceServiceRoomList {
46+
SpaceServiceRoomList::new(self.client.clone(), space_id)
5947
}
6048
}
6149

6250
#[cfg(test)]
6351
mod tests {
64-
use super::*;
6552
use assert_matches2::assert_let;
6653
use matrix_sdk::{room::ParentSpace, test_utils::mocks::MatrixMockServer};
6754
use matrix_sdk_test::{JoinedRoomBuilder, async_test, event_factory::EventFactory};
6855
use ruma::{RoomVersionId, room::RoomType, room_id};
6956
use tokio_stream::StreamExt;
7057

58+
use super::*;
59+
7160
#[async_test]
7261
async fn test_spaces_hierarchy() {
7362
let server = MatrixMockServer::new().await;
@@ -80,9 +69,9 @@ mod tests {
8069

8170
// Given one parent space with 2 children spaces
8271

83-
let parent_space_id = room_id!("!3:example.org");
84-
let child_space_id_1 = room_id!("!1:example.org");
85-
let child_space_id_2 = room_id!("!2:example.org");
72+
let parent_space_id = room_id!("!parent_space:example.org");
73+
let child_space_id_1 = room_id!("!child_space_1:example.org");
74+
let child_space_id_2 = room_id!("!child_space_2:example.org");
8675

8776
server
8877
.sync_room(

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
// limitations under the License.
1414

1515
use matrix_sdk::{Room, RoomHero, RoomState};
16-
use ruma::events::room::guest_access::GuestAccess;
17-
use ruma::events::room::history_visibility::HistoryVisibility;
18-
use ruma::room::{JoinRuleSummary, RoomSummary, RoomType};
19-
use ruma::{OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId};
16+
use ruma::{
17+
OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId,
18+
events::room::{guest_access::GuestAccess, history_visibility::HistoryVisibility},
19+
room::{JoinRuleSummary, RoomSummary, RoomType},
20+
};
2021

21-
#[derive(Debug)]
22+
#[derive(Debug, Clone, PartialEq)]
2223
pub struct SpaceServiceRoom {
2324
pub room_id: OwnedRoomId,
2425
pub canonical_alias: Option<OwnedRoomAliasId>,

0 commit comments

Comments
 (0)