feat(ffi): Implement RoomList::rooms.

This patch implements `RoomList::rooms` to fetch one room. The type
name is `RoomListRoom` to avoid any collision with an existing `Room`
type already.

`RoomListRoom` implements `name`, `timeline` and `latest_event`.
This commit is contained in:
Ivan Enderlin
2023-06-07 20:51:30 +02:00
parent e2480be47f
commit 070965fc87

View File

@@ -2,8 +2,12 @@ use std::{fmt::Debug, sync::Arc};
use eyeball_im::VectorDiff;
use futures_util::{pin_mut, StreamExt};
use ruma::RoomId;
use crate::{Client, RoomListEntry, TaskHandle, RUNTIME};
use crate::{
Client, EventTimelineItem, RoomListEntry, TaskHandle, TimelineDiff, TimelineItem,
TimelineListener, RUNTIME,
};
#[uniffi::export]
impl Client {
@@ -25,6 +29,7 @@ pub enum RoomListError {
UnknownList { list_name: String },
InputHasNotBeenApplied,
RoomNotFound { room_name: String },
InvalidRoomId { error: String },
}
impl From<matrix_sdk_ui::room_list::Error> for RoomListError {
@@ -40,6 +45,12 @@ impl From<matrix_sdk_ui::room_list::Error> for RoomListError {
}
}
impl From<ruma::IdParseError> for RoomListError {
fn from(value: ruma::IdParseError) -> Self {
Self::InvalidRoomId { error: value.to_string() }
}
}
#[derive(uniffi::Object)]
pub struct RoomList {
inner: Arc<matrix_sdk_ui::RoomList>,
@@ -79,7 +90,7 @@ impl RoomList {
let (entries, entries_stream) = self.inner.entries().await.map_err(RoomListError::from)?;
Ok(RoomListEntriesResult {
entries: entries.iter().map(Into::into).collect(),
entries: entries.into_iter().map(Into::into).collect(),
entries_stream: Arc::new(TaskHandle::new(RUNTIME.spawn(async move {
pin_mut!(entries_stream);
@@ -89,6 +100,12 @@ impl RoomList {
}))),
})
}
async fn room(&self, room_id: String) -> Result<Arc<RoomListRoom>, RoomListError> {
let room_id = <&RoomId>::try_from(room_id.as_str()).map_err(RoomListError::from)?;
Ok(Arc::new(RoomListRoom { inner: Arc::new(self.inner.room(room_id).await?) }))
}
}
#[derive(uniffi::Record)]
@@ -167,3 +184,41 @@ impl From<VectorDiff<matrix_sdk::RoomListEntry>> for RoomListEntriesUpdate {
pub trait RoomListEntriesListener: Send + Sync + Debug {
fn on_update(&self, room_entries_update: RoomListEntriesUpdate);
}
#[derive(uniffi::Object)]
pub struct RoomListRoom {
inner: Arc<matrix_sdk_ui::room_list::Room>,
}
#[uniffi::export]
impl RoomListRoom {
async fn name(&self) -> Option<String> {
self.inner.name().await
}
async fn timeline(&self, listener: Box<dyn TimelineListener>) -> RoomListRoomTimelineResult {
let timeline = self.inner.timeline().await;
let (items, items_stream) = timeline.subscribe().await;
RoomListRoomTimelineResult {
items: items.into_iter().map(TimelineItem::from_arc).collect(),
items_stream: Arc::new(TaskHandle::new(RUNTIME.spawn(async move {
pin_mut!(items_stream);
while let Some(diff) = items_stream.next().await {
listener.on_update(Arc::new(TimelineDiff::new(diff)))
}
}))),
}
}
async fn latest_event(&self) -> Option<Arc<EventTimelineItem>> {
self.inner.latest_event().await.map(EventTimelineItem).map(Arc::new)
}
}
#[derive(uniffi::Record)]
pub struct RoomListRoomTimelineResult {
pub items: Vec<Arc<TimelineItem>>,
pub items_stream: Arc<TaskHandle>,
}