Setup composer actions within threaded timelines.

This commit is contained in:
Stefan Ceriu
2025-06-03 17:53:43 +03:00
committed by Stefan Ceriu
parent c3a9e5deaa
commit 21e07e164c
9 changed files with 66 additions and 37 deletions
@@ -175,7 +175,7 @@ class JoinedRoomProxy: JoinedRoomProxyProtocol {
trackReadReceipts: true,
reportUtds: true))
let timeline = TimelineProxy(timeline: sdkTimeline, kind: .thread)
let timeline = TimelineProxy(timeline: sdkTimeline, kind: .thread(rootEventID: eventID))
await timeline.subscribeForUpdates()
return .success(timeline)
@@ -158,6 +158,7 @@ class TimelineController: TimelineControllerProtocol {
switch await activeTimeline.sendMessage(message,
html: html,
threadRootEventID: timelineKind.threadRootEventID,
inReplyToEventID: inReplyToEventID,
intentionalMentions: intentionalMentions) {
case .success:
@@ -389,8 +389,15 @@ final class TimelineProxy: TimelineProxyProtocol {
return .success(())
}
/// Send a message within a room. If `inReplyToEventID` is specified then it will be sent as a reply
/// to that particular message. If the `threadRootEventID` is also specified then it will be sent
/// as a reply to the given `inReplyToEventID` within the thread rooted in `threadRootEventID`
///
/// Internally `enforceThread` is set to true whenever `threadRootEventID` is specified
/// and `replyWithinThread` when `inReplyToEventID` is.
func sendMessage(_ message: String,
html: String?,
threadRootEventID: String?,
inReplyToEventID: String? = nil,
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
if let inReplyToEventID {
@@ -405,14 +412,18 @@ final class TimelineProxy: TimelineProxyProtocol {
do {
if let inReplyToEventID {
// `enforceThread` will force send the message a thread with `inReplyToEventID` while
// `replyWithinThread` will create an in-reply-to associated field *within* that same thread
try await timeline.sendReply(msg: messageContent, replyParams: .init(eventId: inReplyToEventID,
enforceThread: false,
replyWithinThread: false))
enforceThread: threadRootEventID != nil,
replyWithinThread: threadRootEventID != nil))
MXLog.info("Finished sending reply to eventID: \(inReplyToEventID)")
} else {
_ = try await timeline.send(msg: messageContent)
if let threadRootEventID {
try await timeline.sendReply(msg: messageContent, replyParams: .init(eventId: threadRootEventID,
enforceThread: true,
replyWithinThread: false))
} else {
_ = try await timeline.send(msg: messageContent)
}
MXLog.info("Finished sending message")
}
} catch {
@@ -13,10 +13,23 @@ enum TimelineKind: Equatable {
case live
case detached
case pinned
case thread
case thread(rootEventID: String)
enum MediaPresentation { case roomScreenLive, roomScreenDetached, pinnedEventsScreen, mediaFilesScreen }
case media(MediaPresentation)
var isThread: Bool {
threadRootEventID != nil
}
var threadRootEventID: String? {
switch self {
case .thread(let rootEventID):
rootEventID
default:
nil
}
}
}
enum TimelineFocus {
@@ -105,6 +118,7 @@ protocol TimelineProxyProtocol {
func sendMessage(_ message: String,
html: String?,
threadRootEventID: String?,
inReplyToEventID: String?,
intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError>