Skip to content

Commit d1163b7

Browse files
committed
feat!(timeline): Timeline::send_reply() automatically includes the thread relationship too
1 parent 5ae7d0f commit d1163b7

File tree

5 files changed

+64
-49
lines changed

5 files changed

+64
-49
lines changed

bindings/matrix-sdk-ffi/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ All notable changes to this project will be documented in this file.
88

99
### Features:
1010

11+
- [**breaking**] [`Timeline::send_reply()`] now automatically fills in the thread relationship,
12+
based on the timeline focus. As a result, it only takes an `OwnedEventId` parameter, instead of
13+
the `Reply` type. The proper way to start a thread is now thus to create a threaded-focused
14+
timeline, and then use `Timeline::send()`.
15+
([5427](https://github.com/matrix-org/matrix-rust-sdk/pull/5427))
1116
- Add `HomeserverLoginDetails::supports_sso_login` for legacy SSO support information.
1217
This is primarily for Element X to give a dedicated error message in case
1318
it connects a homeserver with only this method available.

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,10 @@ impl Timeline {
529529
pub async fn send_reply(
530530
&self,
531531
msg: Arc<RoomMessageEventContentWithoutRelation>,
532-
reply_params: ReplyParameters,
532+
event_id: String,
533533
) -> Result<(), ClientError> {
534-
self.inner.send_reply((*msg).clone(), reply_params.try_into()?).await?;
534+
let event_id = EventId::parse(&event_id).map_err(|_| RoomError::InvalidRepliedToEventId)?;
535+
self.inner.send_reply((*msg).clone(), event_id).await?;
535536
Ok(())
536537
}
537538

@@ -585,7 +586,7 @@ impl Timeline {
585586
description: Option<String>,
586587
zoom_level: Option<u8>,
587588
asset_type: Option<AssetType>,
588-
reply_params: Option<ReplyParameters>,
589+
replied_to_event_id: Option<String>,
589590
) -> Result<(), ClientError> {
590591
let mut location_event_message_content =
591592
LocationMessageEventContent::new(body, geo_uri.clone());
@@ -604,8 +605,8 @@ impl Timeline {
604605
MessageType::Location(location_event_message_content),
605606
);
606607

607-
if let Some(reply_params) = reply_params {
608-
self.send_reply(Arc::new(room_message_event_content), reply_params).await
608+
if let Some(replied_to_event_id) = replied_to_event_id {
609+
self.send_reply(Arc::new(room_message_event_content), replied_to_event_id).await
609610
} else {
610611
self.send(Arc::new(room_message_event_content)).await?;
611612
Ok(())

crates/matrix-sdk-ui/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ All notable changes to this project will be documented in this file.
88

99
### Features
1010

11+
- [**breaking**] [`Timeline::send_reply()`] now automatically fills in the thread relationship,
12+
based on the timeline focus. As a result, it only takes an `OwnedEventId` parameter, instead of
13+
the `Reply` type. The proper way to start a thread is now thus to create a threaded-focused
14+
timeline, and then use `Timeline::send()`.
15+
([5427](https://github.com/matrix-org/matrix-rust-sdk/pull/5427))
1116
- `Timeline::send()` will now automatically fill the thread relationship, if the timeline has a
1217
thread focus, and the sent event doesn't have a prefilled `relates_to` field (i.e. a relationship).
1318
([5427](https://github.com/matrix-org/matrix-rust-sdk/pull/5427))

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

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -339,26 +339,38 @@ impl Timeline {
339339
///
340340
/// Currently it only supports events with an event ID and JSON being
341341
/// available (which can be removed by local redactions). This is subject to
342-
/// change. Please check [`EventTimelineItem::can_be_replied_to`] to decide
343-
/// whether to render a reply button.
342+
/// change. Use [`EventTimelineItem::can_be_replied_to`] to decide whether
343+
/// to render a reply button.
344344
///
345345
/// The sender will be added to the mentions of the reply if
346346
/// and only if the event has not been written by the sender.
347347
///
348-
/// # Arguments
348+
/// This will do the right thing in the presence of threads:
349+
/// - if this timeline is not focused on a thread, then it will forward the
350+
/// thread relationship of the replied-to event, if present.
351+
/// - if this is a threaded timeline, it will mark the reply as an in-thread
352+
/// reply.
349353
///
350-
/// * `content` - The content of the reply
354+
/// # Arguments
351355
///
352-
/// * `event_id` - The ID of the event to reply to
356+
/// * `content` - The content of the reply.
353357
///
354-
/// * `enforce_thread` - Whether to enforce a thread relation on the reply
358+
/// * `event_id` - The ID of the event to reply to.
355359
#[instrument(skip(self, content))]
356360
pub async fn send_reply(
357361
&self,
358362
content: RoomMessageEventContentWithoutRelation,
359-
reply: Reply,
363+
replied_to: OwnedEventId,
360364
) -> Result<(), Error> {
361-
let content = self.room().make_reply_event(content, reply).await?;
365+
let enforce_thread = if self.controller.thread_root().is_some() {
366+
EnforceThread::Threaded(ReplyWithinThread::Yes)
367+
} else {
368+
EnforceThread::MaybeThreaded
369+
};
370+
let content = self
371+
.room()
372+
.make_reply_event(content, Reply { event_id: replied_to, enforce_thread })
373+
.await?;
362374
self.send(content.into()).await?;
363375
Ok(())
364376
}

crates/matrix-sdk-ui/tests/integration/timeline/replies.rs

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ use assert_matches::assert_matches;
44
use assert_matches2::assert_let;
55
use eyeball_im::VectorDiff;
66
use futures_util::StreamExt;
7-
use matrix_sdk::{
8-
room::reply::{EnforceThread, Reply},
9-
test_utils::mocks::MatrixMockServer,
10-
};
7+
use matrix_sdk::test_utils::mocks::MatrixMockServer;
118
use matrix_sdk_base::timeout::timeout;
129
use matrix_sdk_test::{
1310
ALICE, BOB, CAROL, JoinedRoomBuilder, async_test, event_factory::EventFactory,
1411
};
1512
use matrix_sdk_ui::timeline::{
1613
Error as TimelineError, EventSendState, MsgLikeContent, MsgLikeKind, RoomExt, TimelineDetails,
17-
TimelineEventItemId, TimelineItemContent,
14+
TimelineEventItemId, TimelineFocus, TimelineItemContent,
1815
};
1916
use ruma::{
2017
MilliSecondsSinceUnixEpoch, UInt, event_id,
@@ -27,7 +24,7 @@ use ruma::{
2724
encrypted::{
2825
EncryptedEventScheme, MegolmV1AesSha2ContentInit, RoomEncryptedEventContent,
2926
},
30-
message::{Relation, ReplyWithinThread, RoomMessageEventContentWithoutRelation},
27+
message::{Relation, RoomMessageEventContent, RoomMessageEventContentWithoutRelation},
3128
},
3229
sticker::{StickerEventContent, StickerMediaSource},
3330
},
@@ -706,10 +703,7 @@ async fn test_send_reply() {
706703
timeline
707704
.send_reply(
708705
RoomMessageEventContentWithoutRelation::text_plain("Replying to Bob"),
709-
Reply {
710-
event_id: event_id_from_bob.into(),
711-
enforce_thread: EnforceThread::MaybeThreaded,
712-
},
706+
event_id_from_bob.into(),
713707
)
714708
.await
715709
.unwrap();
@@ -808,10 +802,7 @@ async fn test_send_reply_to_self() {
808802
timeline
809803
.send_reply(
810804
RoomMessageEventContentWithoutRelation::text_plain("Replying to self"),
811-
Reply {
812-
event_id: event_id_from_self.into(),
813-
enforce_thread: EnforceThread::MaybeThreaded,
814-
},
805+
event_id_from_self.into(),
815806
)
816807
.await
817808
.unwrap();
@@ -876,7 +867,7 @@ async fn test_send_reply_to_threaded() {
876867
timeline
877868
.send_reply(
878869
RoomMessageEventContentWithoutRelation::text_plain("Hello, Bob!"),
879-
Reply { event_id: event_id_1.into(), enforce_thread: EnforceThread::MaybeThreaded },
870+
event_id_1.into(),
880871
)
881872
.await
882873
.unwrap();
@@ -978,10 +969,7 @@ async fn test_send_reply_with_event_id() {
978969
timeline
979970
.send_reply(
980971
RoomMessageEventContentWithoutRelation::text_plain("Replying to Bob"),
981-
Reply {
982-
event_id: event_id_from_bob.into(),
983-
enforce_thread: EnforceThread::MaybeThreaded,
984-
},
972+
event_id_from_bob.into(),
985973
)
986974
.await
987975
.unwrap();
@@ -1063,14 +1051,16 @@ async fn test_send_reply_enforce_thread() {
10631051
.mount()
10641052
.await;
10651053

1066-
timeline
1067-
.send_reply(
1068-
RoomMessageEventContentWithoutRelation::text_plain("Replying to Bob"),
1069-
Reply {
1070-
event_id: event_id_from_bob.into(),
1071-
enforce_thread: EnforceThread::Threaded(ReplyWithinThread::No),
1072-
},
1073-
)
1054+
// Starting a thread.
1055+
let thread_timeline = room
1056+
.timeline_builder()
1057+
.with_focus(TimelineFocus::Thread { root_event_id: event_id_from_bob.to_owned() })
1058+
.build()
1059+
.await
1060+
.unwrap();
1061+
1062+
thread_timeline
1063+
.send(RoomMessageEventContent::text_plain("Replying to Bob").into())
10741064
.await
10751065
.unwrap();
10761066

@@ -1162,13 +1152,18 @@ async fn test_send_reply_enforce_thread_is_reply() {
11621152
.mount()
11631153
.await;
11641154

1165-
timeline
1155+
// Starting a thread, and making an explicit reply inside the thread.
1156+
let thread_timeline = room
1157+
.timeline_builder()
1158+
.with_focus(TimelineFocus::Thread { root_event_id: event_id_from_bob.to_owned() })
1159+
.build()
1160+
.await
1161+
.unwrap();
1162+
1163+
thread_timeline
11661164
.send_reply(
11671165
RoomMessageEventContentWithoutRelation::text_plain("Replying to Bob"),
1168-
Reply {
1169-
event_id: event_id_from_bob.into(),
1170-
enforce_thread: EnforceThread::Threaded(ReplyWithinThread::Yes),
1171-
},
1166+
event_id_from_bob.into(),
11721167
)
11731168
.await
11741169
.unwrap();
@@ -1260,10 +1255,7 @@ async fn test_send_reply_with_event_id_that_is_redacted() {
12601255
timeline
12611256
.send_reply(
12621257
RoomMessageEventContentWithoutRelation::text_plain("Replying to Bob"),
1263-
Reply {
1264-
event_id: redacted_event_id_from_bob.into(),
1265-
enforce_thread: EnforceThread::MaybeThreaded,
1266-
},
1258+
redacted_event_id_from_bob.into(),
12671259
)
12681260
.await
12691261
.unwrap();

0 commit comments

Comments
 (0)