Skip to content

Commit 8eafaa5

Browse files
authored
Merge pull request #3169 from matrix-org/mauroromito/directory_search
Room Directory Search
2 parents 44443d3 + 96c7b3f commit 8eafaa5

File tree

9 files changed

+767
-2
lines changed

9 files changed

+767
-2
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ use crate::{
5858
encryption::Encryption,
5959
notification::NotificationClientBuilder,
6060
notification_settings::NotificationSettings,
61+
room_directory_search::RoomDirectorySearch,
6162
sync_service::{SyncService, SyncServiceBuilder},
6263
task_handle::TaskHandle,
6364
ClientError,
@@ -740,6 +741,12 @@ impl Client {
740741
}
741742
})))
742743
}
744+
745+
pub fn room_directory_search(&self) -> Arc<RoomDirectorySearch> {
746+
Arc::new(RoomDirectorySearch::new(
747+
matrix_sdk::room_directory_search::RoomDirectorySearch::new((*self.inner).clone()),
748+
))
749+
}
743750
}
744751

745752
#[uniffi::export(callback_interface)]

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod notification;
3232
mod notification_settings;
3333
mod platform;
3434
mod room;
35+
mod room_directory_search;
3536
mod room_info;
3637
mod room_list;
3738
mod room_member;
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2024 Mauro Romito
2+
// Copyright 2024 The Matrix.org Foundation C.I.C.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
use std::{fmt::Debug, sync::Arc};
17+
18+
use eyeball_im::VectorDiff;
19+
use futures_util::StreamExt;
20+
use matrix_sdk::room_directory_search::RoomDirectorySearch as SdkRoomDirectorySearch;
21+
use tokio::sync::RwLock;
22+
23+
use super::RUNTIME;
24+
use crate::{error::ClientError, task_handle::TaskHandle};
25+
26+
#[derive(uniffi::Enum)]
27+
pub enum PublicRoomJoinRule {
28+
Public,
29+
Knock,
30+
}
31+
32+
impl TryFrom<ruma::directory::PublicRoomJoinRule> for PublicRoomJoinRule {
33+
type Error = String;
34+
35+
fn try_from(value: ruma::directory::PublicRoomJoinRule) -> Result<Self, Self::Error> {
36+
match value {
37+
ruma::directory::PublicRoomJoinRule::Public => Ok(Self::Public),
38+
ruma::directory::PublicRoomJoinRule::Knock => Ok(Self::Knock),
39+
rule => Err(format!("unsupported join rule: {rule:?}")),
40+
}
41+
}
42+
}
43+
44+
#[derive(uniffi::Record)]
45+
pub struct RoomDescription {
46+
pub room_id: String,
47+
pub name: Option<String>,
48+
pub topic: Option<String>,
49+
pub alias: Option<String>,
50+
pub avatar_url: Option<String>,
51+
pub join_rule: Option<PublicRoomJoinRule>,
52+
pub is_world_readable: bool,
53+
pub joined_members: u64,
54+
}
55+
56+
impl From<matrix_sdk::room_directory_search::RoomDescription> for RoomDescription {
57+
fn from(value: matrix_sdk::room_directory_search::RoomDescription) -> Self {
58+
Self {
59+
room_id: value.room_id.to_string(),
60+
name: value.name,
61+
topic: value.topic,
62+
alias: value.alias.map(|alias| alias.to_string()),
63+
avatar_url: value.avatar_url.map(|url| url.to_string()),
64+
join_rule: value.join_rule.try_into().ok(),
65+
is_world_readable: value.is_world_readable,
66+
joined_members: value.joined_members,
67+
}
68+
}
69+
}
70+
71+
#[derive(uniffi::Object)]
72+
pub struct RoomDirectorySearch {
73+
pub(crate) inner: RwLock<SdkRoomDirectorySearch>,
74+
}
75+
76+
impl RoomDirectorySearch {
77+
pub fn new(inner: SdkRoomDirectorySearch) -> Self {
78+
Self { inner: RwLock::new(inner) }
79+
}
80+
}
81+
82+
#[uniffi::export(async_runtime = "tokio")]
83+
impl RoomDirectorySearch {
84+
pub async fn next_page(&self) -> Result<(), ClientError> {
85+
let mut inner = self.inner.write().await;
86+
inner.next_page().await?;
87+
Ok(())
88+
}
89+
90+
pub async fn search(&self, filter: Option<String>, batch_size: u32) -> Result<(), ClientError> {
91+
let mut inner = self.inner.write().await;
92+
inner.search(filter, batch_size).await?;
93+
Ok(())
94+
}
95+
96+
pub async fn loaded_pages(&self) -> Result<u32, ClientError> {
97+
let inner = self.inner.read().await;
98+
Ok(inner.loaded_pages() as u32)
99+
}
100+
101+
pub async fn is_at_last_page(&self) -> Result<bool, ClientError> {
102+
let inner = self.inner.read().await;
103+
Ok(inner.is_at_last_page())
104+
}
105+
106+
pub async fn results(
107+
&self,
108+
listener: Box<dyn RoomDirectorySearchEntriesListener>,
109+
) -> TaskHandle {
110+
let (initial_values, mut stream) = self.inner.read().await.results();
111+
112+
TaskHandle::new(RUNTIME.spawn(async move {
113+
listener.on_update(vec![RoomDirectorySearchEntryUpdate::Reset {
114+
values: initial_values.into_iter().map(Into::into).collect(),
115+
}]);
116+
117+
while let Some(diffs) = stream.next().await {
118+
listener.on_update(diffs.into_iter().map(|diff| diff.into()).collect());
119+
}
120+
}))
121+
}
122+
}
123+
124+
#[derive(uniffi::Record)]
125+
pub struct RoomDirectorySearchEntriesResult {
126+
pub entries_stream: Arc<TaskHandle>,
127+
}
128+
129+
#[derive(uniffi::Enum)]
130+
pub enum RoomDirectorySearchEntryUpdate {
131+
Append { values: Vec<RoomDescription> },
132+
Clear,
133+
PushFront { value: RoomDescription },
134+
PushBack { value: RoomDescription },
135+
PopFront,
136+
PopBack,
137+
Insert { index: u32, value: RoomDescription },
138+
Set { index: u32, value: RoomDescription },
139+
Remove { index: u32 },
140+
Truncate { length: u32 },
141+
Reset { values: Vec<RoomDescription> },
142+
}
143+
144+
impl From<VectorDiff<matrix_sdk::room_directory_search::RoomDescription>>
145+
for RoomDirectorySearchEntryUpdate
146+
{
147+
fn from(diff: VectorDiff<matrix_sdk::room_directory_search::RoomDescription>) -> Self {
148+
match diff {
149+
VectorDiff::Append { values } => {
150+
Self::Append { values: values.into_iter().map(|v| v.into()).collect() }
151+
}
152+
VectorDiff::Clear => Self::Clear,
153+
VectorDiff::PushFront { value } => Self::PushFront { value: value.into() },
154+
VectorDiff::PushBack { value } => Self::PushBack { value: value.into() },
155+
VectorDiff::PopFront => Self::PopFront,
156+
VectorDiff::PopBack => Self::PopBack,
157+
VectorDiff::Insert { index, value } => {
158+
Self::Insert { index: index as u32, value: value.into() }
159+
}
160+
VectorDiff::Set { index, value } => {
161+
Self::Set { index: index as u32, value: value.into() }
162+
}
163+
VectorDiff::Remove { index } => Self::Remove { index: index as u32 },
164+
VectorDiff::Truncate { length } => Self::Truncate { length: length as u32 },
165+
VectorDiff::Reset { values } => {
166+
Self::Reset { values: values.into_iter().map(|v| v.into()).collect() }
167+
}
168+
}
169+
}
170+
}
171+
172+
#[uniffi::export(callback_interface)]
173+
pub trait RoomDirectorySearchEntriesListener: Send + Sync + Debug {
174+
fn on_update(&self, room_entries_update: Vec<RoomDirectorySearchEntryUpdate>);
175+
}

crates/matrix-sdk/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub mod notification_settings;
4848
#[cfg(feature = "experimental-oidc")]
4949
pub mod oidc;
5050
pub mod room;
51+
pub mod room_directory_search;
5152
pub mod utils;
5253
pub mod futures {
5354
//! Named futures returned from methods on types in [the crate root][crate].

0 commit comments

Comments
 (0)