From a8cff4ded221445046e7f510343bf93e5231a1c6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 22 May 2026 09:19:31 +0300 Subject: [PATCH] Improve how the composer is cleared after sending a message. --- .../RoomPollsHistoryScreenViewModel.swift | 2 +- .../Screens/Timeline/TimelineViewModel.swift | 4 +- .../TimelineController.swift | 89 ++++++++++++++----- .../TimelineControllerProtocol.swift | 1 + 4 files changed, 70 insertions(+), 26 deletions(-) diff --git a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift index 3e6a1209d..36756e2c7 100644 --- a/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomPollsHistoryScreen/RoomPollsHistoryScreenViewModel.swift @@ -79,7 +79,7 @@ class RoomPollsHistoryScreenViewModel: RoomPollsHistoryScreenViewModelType, Room if self.state.canBackPaginate != canBackPaginate { self.state.canBackPaginate = canBackPaginate } - case .isLive: + case .isLive, .sentMessage: break } } diff --git a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift index d6015c07a..999e815c4 100644 --- a/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift +++ b/ElementX/Sources/Screens/Timeline/TimelineViewModel.swift @@ -472,6 +472,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { state.timelineState.focussedEvent = nil } } + case .sentMessage: + actionsSubject.send(.composer(action: .clear)) } } .store(in: &cancellables) @@ -763,8 +765,6 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol { guard !message.isEmpty else { fatalError("This message should never be empty") } - - actionsSubject.send(.composer(action: .clear)) switch mode { case .reply(let eventID, _, _): diff --git a/ElementX/Sources/Services/Timeline/TimelineController/TimelineController.swift b/ElementX/Sources/Services/Timeline/TimelineController/TimelineController.swift index cd055c56b..5d4515920 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/TimelineController.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/TimelineController.swift @@ -296,6 +296,7 @@ class TimelineController: TimelineControllerProtocol { intentionalMentions: intentionalMentions) { case .success: MXLog.info("Finished sending message") + callbacks.send(.sentMessage) await donateSendMessageIntent() case .failure(let error): MXLog.error("Failed sending message with error: \(error)") @@ -306,20 +307,32 @@ class TimelineController: TimelineControllerProtocol { audioInfo: MatrixRustSDK.AudioInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - await activeTimeline.sendAudio(url: url, - audioInfo: audioInfo, - caption: caption, - requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.sendAudio(url: url, + audioInfo: audioInfo, + caption: caption, + requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } func sendFile(url: URL, fileInfo: MatrixRustSDK.FileInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - await activeTimeline.sendFile(url: url, - fileInfo: fileInfo, - caption: caption, - requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.sendFile(url: url, + fileInfo: fileInfo, + caption: caption, + requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } func sendImage(url: URL, @@ -327,11 +340,17 @@ class TimelineController: TimelineControllerProtocol { imageInfo: MatrixRustSDK.ImageInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - await activeTimeline.sendImage(url: url, - thumbnailURL: thumbnailURL, - imageInfo: imageInfo, - caption: caption, - requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.sendImage(url: url, + thumbnailURL: thumbnailURL, + imageInfo: imageInfo, + caption: caption, + requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } func sendVideo(url: URL, @@ -339,11 +358,17 @@ class TimelineController: TimelineControllerProtocol { videoInfo: MatrixRustSDK.VideoInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - await activeTimeline.sendVideo(url: url, - thumbnailURL: thumbnailURL, - videoInfo: videoInfo, - caption: caption, - requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.sendVideo(url: url, + thumbnailURL: thumbnailURL, + videoInfo: videoInfo, + caption: caption, + requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } func sendLocation(body: String, @@ -351,22 +376,40 @@ class TimelineController: TimelineControllerProtocol { description: String?, zoomLevel: UInt8?, assetType: AssetType?) async -> Result { - await activeTimeline.sendLocation(body: body, geoURI: geoURI, description: description, zoomLevel: zoomLevel, assetType: assetType).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.sendLocation(body: body, geoURI: geoURI, description: description, zoomLevel: zoomLevel, assetType: assetType).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } func sendVoiceMessage(url: URL, audioInfo: MatrixRustSDK.AudioInfo, waveform: [Float], requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - await activeTimeline.sendVoiceMessage(url: url, - audioInfo: audioInfo, - waveform: waveform, requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.sendVoiceMessage(url: url, + audioInfo: audioInfo, + waveform: waveform, requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } // MARK: - Polls func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result { - await activeTimeline.createPoll(question: question, answers: answers, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError) + switch await activeTimeline.createPoll(question: question, answers: answers, pollKind: pollKind).mapError(TimelineControllerError.timelineProxyError) { + case .success: + callbacks.send(.sentMessage) + return .success(()) + case .failure(let error): + return .failure(error) + } } func editPoll(original eventID: String, question: String, answers: [String], pollKind: Poll.Kind) async -> Result { diff --git a/ElementX/Sources/Services/Timeline/TimelineController/TimelineControllerProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineController/TimelineControllerProtocol.swift index f6818256e..ec9cbd93a 100644 --- a/ElementX/Sources/Services/Timeline/TimelineController/TimelineControllerProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineController/TimelineControllerProtocol.swift @@ -14,6 +14,7 @@ enum TimelineControllerCallback { case updatedTimelineItems(timelineItems: [RoomTimelineItemProtocol], isSwitchingTimelines: Bool) case paginationState(TimelinePaginationState) case isLive(Bool) + case sentMessage } enum TimelineControllerAction {