Skip to content

Commit 9ae579c

Browse files
committed
chore(spaces): introduce a SpaceServiceRoom
1 parent c2976e6 commit 9ae579c

File tree

4 files changed

+147
-20
lines changed

4 files changed

+147
-20
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ impl RoomPreview {
3131
avatar_url: info.avatar_url.as_ref().map(|url| url.to_string()),
3232
num_joined_members: info.num_joined_members,
3333
num_active_members: info.num_active_members,
34-
room_type: info.room_type.as_ref().into(),
34+
room_type: info.room_type.clone().into(),
3535
is_history_world_readable: info.is_world_readable,
3636
membership: info.state.map(|state| state.into()),
37-
join_rule: info.join_rule.as_ref().map(Into::into),
37+
join_rule: info.join_rule.clone().map(Into::into),
3838
is_direct: info.is_direct,
3939
heroes: info
4040
.heroes
@@ -116,8 +116,8 @@ pub struct RoomPreviewInfo {
116116
pub heroes: Option<Vec<RoomHero>>,
117117
}
118118

119-
impl From<&JoinRuleSummary> for JoinRule {
120-
fn from(join_rule: &JoinRuleSummary) -> Self {
119+
impl From<JoinRuleSummary> for JoinRule {
120+
fn from(join_rule: JoinRuleSummary) -> Self {
121121
match join_rule {
122122
JoinRuleSummary::Invite => JoinRule::Invite,
123123
JoinRuleSummary::Knock => JoinRule::Knock,
@@ -153,8 +153,8 @@ pub enum RoomType {
153153
Custom { value: String },
154154
}
155155

156-
impl From<Option<&RumaRoomType>> for RoomType {
157-
fn from(value: Option<&RumaRoomType>) -> Self {
156+
impl From<Option<RumaRoomType>> for RoomType {
157+
fn from(value: Option<RumaRoomType>) -> Self {
158158
match value {
159159
Some(RumaRoomType::Space) => RoomType::Space,
160160
Some(RumaRoomType::_Custom(_)) => RoomType::Custom {

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

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

15-
use matrix_sdk_ui::spaces::SpaceService as UISpaceService;
15+
use matrix_sdk_ui::spaces::{
16+
SpaceService as UISpaceService, SpaceServiceRoom as UISpaceServiceRoom,
17+
};
1618
use ruma::RoomId;
1719

18-
use crate::error::ClientError;
20+
use crate::{
21+
client::JoinRule,
22+
error::ClientError,
23+
room::{Membership, RoomHero},
24+
room_preview::RoomType,
25+
};
1926

2027
#[derive(uniffi::Object)]
2128
pub struct SpaceService {
@@ -32,17 +39,53 @@ impl SpaceService {
3239
#[matrix_sdk_ffi_macros::export]
3340
impl SpaceService {
3441
/// Get the list of joined spaces.
35-
pub fn joined_spaces(&self) -> Vec<String> {
36-
self.inner.joined_spaces().into_iter().map(|id| id.to_string()).collect()
42+
pub fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
43+
self.inner.joined_spaces().into_iter().map(Into::into).collect()
3744
}
3845

3946
/// Get the top-level children for a given space.
4047
pub async fn top_level_children_for(
4148
&self,
4249
space_id: String,
43-
) -> Result<Vec<String>, ClientError> {
50+
) -> Result<Vec<SpaceServiceRoom>, ClientError> {
4451
let space_id = RoomId::parse(space_id)?;
4552
let children = self.inner.top_level_children_for(space_id).await?;
46-
Ok(children.into_iter().map(|id| id.to_string()).collect())
53+
Ok(children.into_iter().map(Into::into).collect())
54+
}
55+
}
56+
57+
#[derive(uniffi::Record)]
58+
pub struct SpaceServiceRoom {
59+
pub room_id: String,
60+
pub canonical_alias: Option<String>,
61+
pub name: Option<String>,
62+
pub topic: Option<String>,
63+
pub avatar_url: Option<String>,
64+
pub room_type: RoomType,
65+
pub num_joined_members: u64,
66+
pub join_rule: Option<JoinRule>,
67+
pub world_readable: Option<bool>,
68+
pub guest_can_join: bool,
69+
70+
pub state: Option<Membership>,
71+
pub heroes: Option<Vec<RoomHero>>,
72+
}
73+
74+
impl From<UISpaceServiceRoom> for SpaceServiceRoom {
75+
fn from(room: UISpaceServiceRoom) -> Self {
76+
Self {
77+
room_id: room.room_id.into(),
78+
canonical_alias: room.canonical_alias.map(|alias| alias.into()),
79+
name: room.name,
80+
topic: room.topic,
81+
avatar_url: room.avatar_url.map(|url| url.into()),
82+
room_type: room.room_type.into(),
83+
num_joined_members: room.num_joined_members,
84+
join_rule: room.join_rule.map(Into::into),
85+
world_readable: room.world_readable,
86+
guest_can_join: room.guest_can_join,
87+
state: room.state.map(Into::into),
88+
heroes: room.heroes.map(|heroes| heroes.into_iter().map(Into::into).collect()),
89+
}
4790
}
4891
}

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ use matrix_sdk::{Client, Error};
2020
use ruma::OwnedRoomId;
2121
use ruma::api::client::space::get_hierarchy;
2222

23+
pub use crate::spaces::room::SpaceServiceRoom;
24+
25+
pub mod room;
26+
2327
pub struct SpaceService {
2428
client: Client,
2529
}
@@ -29,25 +33,29 @@ impl SpaceService {
2933
Self { client }
3034
}
3135

32-
pub fn joined_spaces(&self) -> Vec<OwnedRoomId> {
36+
pub fn joined_spaces(&self) -> Vec<SpaceServiceRoom> {
3337
self.client
3438
.joined_rooms()
3539
.into_iter()
36-
.filter_map(|room| if room.is_space() { Some(room.room_id().to_owned()) } else { None })
37-
.collect()
40+
.filter_map(|room| if room.is_space() { Some(room) } else { None })
41+
.map(|room| SpaceServiceRoom::new_from_known(room))
42+
.collect::<Vec<_>>()
3843
}
3944

4045
pub async fn top_level_children_for(
4146
&self,
4247
space_id: OwnedRoomId,
43-
) -> Result<Vec<OwnedRoomId>, Error> {
48+
) -> Result<Vec<SpaceServiceRoom>, Error> {
4449
let request = get_hierarchy::v1::Request::new(space_id.clone());
4550

4651
let result = self.client.send(request).await?;
4752

48-
println!("Top level children for space {}: {:?}", space_id, result.rooms);
49-
50-
Ok(vec![])
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<_>>())
5159
}
5260
}
5361

@@ -133,7 +141,7 @@ mod tests {
133141

134142
// All joined
135143
assert_eq!(
136-
space_service.joined_spaces(),
144+
space_service.joined_spaces().iter().map(|s| s.room_id.to_owned()).collect::<Vec<_>>(),
137145
vec![child_space_id_1, child_space_id_2, parent_space_id]
138146
);
139147

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2025 The Matrix.org Foundation C.I.C.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for that specific language governing permissions and
13+
// limitations under the License.
14+
15+
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};
20+
21+
#[derive(Debug)]
22+
pub struct SpaceServiceRoom {
23+
pub room_id: OwnedRoomId,
24+
pub canonical_alias: Option<OwnedRoomAliasId>,
25+
pub name: Option<String>,
26+
pub topic: Option<String>,
27+
pub avatar_url: Option<OwnedMxcUri>,
28+
pub room_type: Option<RoomType>,
29+
pub num_joined_members: u64,
30+
pub join_rule: Option<JoinRuleSummary>,
31+
pub world_readable: Option<bool>,
32+
pub guest_can_join: bool,
33+
34+
pub state: Option<RoomState>,
35+
pub heroes: Option<Vec<RoomHero>>,
36+
}
37+
38+
impl SpaceServiceRoom {
39+
pub fn new_from_summary(summary: &RoomSummary, known_room: Option<Room>) -> Self {
40+
Self {
41+
room_id: summary.room_id.clone(),
42+
canonical_alias: summary.canonical_alias.clone(),
43+
name: summary.name.clone(),
44+
topic: summary.topic.clone(),
45+
avatar_url: summary.avatar_url.clone(),
46+
room_type: summary.room_type.clone(),
47+
num_joined_members: summary.num_joined_members.into(),
48+
join_rule: Some(summary.join_rule.clone()),
49+
world_readable: Some(summary.world_readable),
50+
guest_can_join: summary.guest_can_join,
51+
state: known_room.as_ref().map(|r| r.state()),
52+
heroes: known_room.map(|r| r.heroes()),
53+
}
54+
}
55+
56+
pub fn new_from_known(known_room: Room) -> Self {
57+
let room_info = known_room.clone_info();
58+
59+
Self {
60+
room_id: room_info.room_id().to_owned(),
61+
canonical_alias: room_info.canonical_alias().map(ToOwned::to_owned),
62+
name: room_info.name().map(ToOwned::to_owned),
63+
topic: room_info.topic().map(ToOwned::to_owned),
64+
avatar_url: room_info.avatar_url().map(ToOwned::to_owned),
65+
room_type: room_info.room_type().cloned(),
66+
num_joined_members: known_room.joined_members_count(),
67+
join_rule: room_info.join_rule().cloned().map(Into::into),
68+
world_readable: room_info
69+
.history_visibility()
70+
.map(|vis| *vis == HistoryVisibility::WorldReadable),
71+
guest_can_join: known_room.guest_access() == GuestAccess::CanJoin,
72+
state: Some(known_room.state()),
73+
heroes: Some(room_info.heroes().to_vec()),
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)