diff --git a/bindings/matrix-sdk-ffi/src/room_list.rs b/bindings/matrix-sdk-ffi/src/room_list.rs index bf2668c21..2c1efc297 100644 --- a/bindings/matrix-sdk-ffi/src/room_list.rs +++ b/bindings/matrix-sdk-ffi/src/room_list.rs @@ -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 for RoomListError { @@ -40,6 +45,12 @@ impl From for RoomListError { } } +impl From for RoomListError { + fn from(value: ruma::IdParseError) -> Self { + Self::InvalidRoomId { error: value.to_string() } + } +} + #[derive(uniffi::Object)] pub struct RoomList { inner: Arc, @@ -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, 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> for RoomListEntriesUpdate { pub trait RoomListEntriesListener: Send + Sync + Debug { fn on_update(&self, room_entries_update: RoomListEntriesUpdate); } + +#[derive(uniffi::Object)] +pub struct RoomListRoom { + inner: Arc, +} + +#[uniffi::export] +impl RoomListRoom { + async fn name(&self) -> Option { + self.inner.name().await + } + + async fn timeline(&self, listener: Box) -> 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> { + self.inner.latest_event().await.map(EventTimelineItem).map(Arc::new) + } +} + +#[derive(uniffi::Record)] +pub struct RoomListRoomTimelineResult { + pub items: Vec>, + pub items_stream: Arc, +}