Skip to content

Commit 397a26e

Browse files
committed
ffi: add bindings for the timeline focus mode and associated functions
1 parent a6c4240 commit 397a26e

File tree

2 files changed

+75
-11
lines changed

2 files changed

+75
-11
lines changed

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

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ use std::sync::Arc;
22

33
use anyhow::{Context, Result};
44
use matrix_sdk::{
5+
event_cache::paginator::PaginatorError,
56
room::{power_levels::RoomPowerLevelChanges, Room as SdkRoom, RoomMemberRole},
67
RoomMemberships, RoomState,
78
};
8-
use matrix_sdk_ui::timeline::RoomExt;
9+
use matrix_sdk_ui::timeline::{PaginationError, RoomExt, TimelineFocus};
910
use mime::Mime;
1011
use ruma::{
1112
api::client::room::report_content,
@@ -30,7 +31,7 @@ use crate::{
3031
room_info::RoomInfo,
3132
room_member::RoomMember,
3233
ruma::ImageInfo,
33-
timeline::{EventTimelineItem, ReceiptType, Timeline},
34+
timeline::{EventTimelineItem, FocusEventError, ReceiptType, Timeline},
3435
utils::u64_to_uint,
3536
TaskHandle,
3637
};
@@ -167,6 +168,48 @@ impl Room {
167168
}
168169
}
169170

171+
/// Returns a timeline focused on the given event.
172+
///
173+
/// Note: this timeline is independent from that returned with
174+
/// [`Self::timeline`], and as such it is not cached.
175+
pub async fn timeline_focused_on_event(
176+
&self,
177+
event_id: String,
178+
num_context_events: u16,
179+
internal_id_prefix: Option<String>,
180+
) -> Result<Arc<Timeline>, FocusEventError> {
181+
let parsed_event_id = EventId::parse(&event_id).map_err(|err| {
182+
FocusEventError::InvalidEventId { event_id: event_id.clone(), err: err.to_string() }
183+
})?;
184+
185+
let room = &self.inner;
186+
187+
let mut builder = matrix_sdk_ui::timeline::Timeline::builder(room);
188+
189+
if let Some(internal_id_prefix) = internal_id_prefix {
190+
builder = builder.with_internal_id_prefix(internal_id_prefix);
191+
}
192+
193+
let timeline = match builder
194+
.with_focus(TimelineFocus::Event { target: parsed_event_id, num_context_events })
195+
.build()
196+
.await
197+
{
198+
Ok(t) => t,
199+
Err(err) => {
200+
if let matrix_sdk_ui::timeline::Error::PaginationError(
201+
PaginationError::Paginator(PaginatorError::EventNotFound(..)),
202+
) = err
203+
{
204+
return Err(FocusEventError::EventNotFound { event_id: event_id.to_string() });
205+
}
206+
return Err(FocusEventError::Other { msg: err.to_string() });
207+
}
208+
};
209+
210+
Ok(Timeline::new(timeline))
211+
}
212+
170213
pub fn display_name(&self) -> Result<String, ClientError> {
171214
let r = self.inner.clone();
172215
RUNTIME.block_on(async move { Ok(r.display_name().await?.to_string()) })
@@ -237,7 +280,8 @@ impl Room {
237280
}
238281
}
239282

240-
// Otherwise, fallback to the classical path.
283+
// Otherwise, create a synthetic [`EventTimelineItem`] using the classical
284+
// [`Room`] path.
241285
let latest_event = match self.inner.latest_event() {
242286
Some(latest_event) => matrix_sdk_ui::timeline::EventTimelineItem::from_latest_event(
243287
self.inner.client(),
@@ -249,6 +293,7 @@ impl Room {
249293
.map(Arc::new),
250294
None => None,
251295
};
296+
252297
Ok(RoomInfo::new(&self.inner, avatar_url, latest_event).await?)
253298
}
254299

bindings/matrix-sdk-ffi/src/timeline/mod.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use matrix_sdk::attachment::{
2222
AttachmentConfig, AttachmentInfo, BaseAudioInfo, BaseFileInfo, BaseImageInfo,
2323
BaseThumbnailInfo, BaseVideoInfo, Thumbnail,
2424
};
25-
use matrix_sdk_ui::timeline::{BackPaginationStatus, EventItemOrigin, Profile, TimelineDetails};
25+
use matrix_sdk_ui::timeline::{EventItemOrigin, PaginationStatus, Profile, TimelineDetails};
2626
use mime::Mime;
2727
use ruma::{
2828
events::{
@@ -162,7 +162,7 @@ impl Timeline {
162162

163163
pub fn subscribe_to_back_pagination_status(
164164
&self,
165-
listener: Box<dyn BackPaginationStatusListener>,
165+
listener: Box<dyn PaginationStatusListener>,
166166
) -> Result<Arc<TaskHandle>, ClientError> {
167167
let mut subscriber = self.inner.back_pagination_status();
168168

@@ -176,11 +176,18 @@ impl Timeline {
176176
}))))
177177
}
178178

179-
/// Loads older messages into the timeline.
179+
/// Paginate backwards, whether we are in focused mode or in live mode.
180180
///
181-
/// Raises an exception if there are no timeline listeners.
182-
pub fn paginate_backwards(&self, opts: PaginationOptions) -> Result<(), ClientError> {
183-
RUNTIME.block_on(async { Ok(self.inner.paginate_backwards(opts.into()).await?) })
181+
/// Returns whether we hit the end of the timeline or not.
182+
pub async fn paginate_backwards(&self, num_events: u16) -> Result<bool, ClientError> {
183+
Ok(self.inner.paginate_backwards(num_events).await?)
184+
}
185+
186+
/// Paginate forwards, when in focused mode.
187+
///
188+
/// Returns whether we hit the end of the timeline or not.
189+
pub async fn paginate_forwards(&self, num_events: u16) -> Result<bool, ClientError> {
190+
Ok(self.inner.focused_paginate_forwards(num_events).await?)
184191
}
185192

186193
pub fn send_read_receipt(
@@ -573,6 +580,18 @@ impl Timeline {
573580
}
574581
}
575582

583+
#[derive(Debug, thiserror::Error, uniffi::Error)]
584+
pub enum FocusEventError {
585+
#[error("the event id parameter {event_id} is incorrect: {err}")]
586+
InvalidEventId { event_id: String, err: String },
587+
588+
#[error("the event {event_id} could not be found")]
589+
EventNotFound { event_id: String },
590+
591+
#[error("error when trying to focus on an event: {msg}")]
592+
Other { msg: String },
593+
}
594+
576595
#[derive(uniffi::Record)]
577596
pub struct RoomTimelineListenerResult {
578597
pub items: Vec<Arc<TimelineItem>>,
@@ -585,8 +604,8 @@ pub trait TimelineListener: Sync + Send {
585604
}
586605

587606
#[uniffi::export(callback_interface)]
588-
pub trait BackPaginationStatusListener: Sync + Send {
589-
fn on_update(&self, status: BackPaginationStatus);
607+
pub trait PaginationStatusListener: Sync + Send {
608+
fn on_update(&self, status: PaginationStatus);
590609
}
591610

592611
#[derive(Clone, uniffi::Object)]

0 commit comments

Comments
 (0)