Skip to content

Commit f49c588

Browse files
pixlwavestefanceriu
authored andcommitted
spaces: Add a method to get the joined parents of a given child.
1 parent 8e0dba6 commit f49c588

File tree

3 files changed

+118
-2
lines changed

3 files changed

+118
-2
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ impl SpaceService {
8787
Ok(Arc::new(SpaceRoomList::new(self.inner.space_room_list(space_id).await)))
8888
}
8989

90+
/// Returns all known direct-parents of a given space room ID.
91+
pub async fn joined_parents_of_child(
92+
&self,
93+
child_id: String,
94+
) -> Result<Vec<SpaceRoom>, ClientError> {
95+
let child_id = RoomId::parse(child_id)?;
96+
97+
let parents = self.inner.joined_parents_of_child(&child_id).await;
98+
99+
Ok(parents.into_iter().map(Into::into).collect())
100+
}
101+
90102
pub async fn add_child_to_space(
91103
&self,
92104
child_id: String,

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ impl SpaceGraph {
6767
.map_or(vec![], |node| node.children.iter().map(|id| id.as_ref()).collect())
6868
}
6969

70+
/// Returns the parents of a given node. If the node does not exist, it
71+
/// returns an empty vector.
72+
pub(super) fn parents_of(&self, node_id: &RoomId) -> Vec<&RoomId> {
73+
self.nodes
74+
.get(node_id)
75+
.map_or(vec![], |node| node.parents.iter().map(|id| id.as_ref()).collect())
76+
}
77+
7078
/// Adds a node to the graph. If the node already exists, it does nothing.
7179
pub(super) fn add_node(&mut self, node_id: OwnedRoomId) {
7280
self.nodes.entry(node_id.clone()).or_insert(SpaceGraphNode::new(node_id));
@@ -184,8 +192,8 @@ mod tests {
184192

185193
assert_eq!(graph.root_nodes(), vec![&a]);
186194

187-
assert!(graph.nodes[&b].parents.contains(&a));
188-
assert!(graph.nodes[&c].parents.contains(&a));
195+
assert_eq!(graph.parents_of(&b), vec![&a]);
196+
assert_eq!(graph.parents_of(&c), vec![&a]);
189197

190198
assert_eq!(graph.children_of(&a), vec![&b, &c]);
191199
}

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

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,20 @@ impl SpaceService {
216216
SpaceRoomList::new(self.client.clone(), space_id).await
217217
}
218218

219+
/// Returns all known direct-parents of a given space room ID.
220+
pub async fn joined_parents_of_child(&self, child_id: &RoomId) -> Vec<SpaceRoom> {
221+
let graph = &self.space_state.lock().await.graph;
222+
223+
graph
224+
.parents_of(child_id)
225+
.into_iter()
226+
.filter_map(|parent_id| self.client.get_room(parent_id))
227+
.map(|room| {
228+
SpaceRoom::new_from_known(&room, graph.children_of(room.room_id()).len() as u64)
229+
})
230+
.collect()
231+
}
232+
219233
pub async fn add_child_to_space(
220234
&self,
221235
child_id: OwnedRoomId,
@@ -716,6 +730,88 @@ mod tests {
716730
);
717731
}
718732

733+
#[async_test]
734+
async fn test_joined_parents_of_child() {
735+
// Given a space with three parent spaces, two of which are joined.
736+
let server = MatrixMockServer::new().await;
737+
let client = server.client_builder().build().await;
738+
let user_id = client.user_id().unwrap();
739+
let factory = EventFactory::new();
740+
741+
server.mock_room_state_encryption().plain().mount().await;
742+
743+
let parent_space_id_1 = room_id!("!parent_space_1:example.org");
744+
let parent_space_id_2 = room_id!("!parent_space_2:example.org");
745+
let unknown_parent_space_id = room_id!("!unknown_parent_space:example.org");
746+
let child_space_id = room_id!("!child_space:example.org");
747+
748+
server
749+
.sync_room(
750+
&client,
751+
JoinedRoomBuilder::new(child_space_id)
752+
.add_state_event(factory.create(user_id, RoomVersionId::V1).with_space_type())
753+
.add_state_event(
754+
factory
755+
.space_parent(parent_space_id_1.to_owned(), child_space_id.to_owned())
756+
.sender(user_id),
757+
)
758+
.add_state_event(
759+
factory
760+
.space_parent(parent_space_id_2.to_owned(), child_space_id.to_owned())
761+
.sender(user_id),
762+
)
763+
.add_state_event(
764+
factory
765+
.space_parent(
766+
unknown_parent_space_id.to_owned(),
767+
child_space_id.to_owned(),
768+
)
769+
.sender(user_id),
770+
),
771+
)
772+
.await;
773+
774+
server
775+
.sync_room(
776+
&client,
777+
JoinedRoomBuilder::new(parent_space_id_1)
778+
.add_state_event(factory.create(user_id, RoomVersionId::V1).with_space_type())
779+
.add_state_event(
780+
factory
781+
.space_child(parent_space_id_1.to_owned(), child_space_id.to_owned())
782+
.sender(user_id),
783+
),
784+
)
785+
.await;
786+
787+
server
788+
.sync_room(
789+
&client,
790+
JoinedRoomBuilder::new(parent_space_id_2)
791+
.add_state_event(factory.create(user_id, RoomVersionId::V1).with_space_type())
792+
.add_state_event(
793+
factory
794+
.space_child(parent_space_id_2.to_owned(), child_space_id.to_owned())
795+
.sender(user_id),
796+
),
797+
)
798+
.await;
799+
800+
let space_service = SpaceService::new(client.clone());
801+
802+
// Wait for the space hierarchy to register.
803+
_ = space_service.joined_spaces().await;
804+
805+
// When retrieving the joined parents of the child space
806+
let parents = space_service.joined_parents_of_child(child_space_id).await;
807+
808+
// Then both parent spaces are returned
809+
assert_eq!(
810+
parents.iter().map(|space| space.room_id.to_owned()).collect::<Vec<_>>(),
811+
vec![parent_space_id_1, parent_space_id_2]
812+
);
813+
}
814+
719815
#[async_test]
720816
async fn test_add_child_to_space() {
721817
// Given a space and child room where the user is admin of both.

0 commit comments

Comments
 (0)