diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index b88ded62c..e58469ce8 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -689,6 +689,7 @@ 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; + 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; 91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */; }; 91D1A46A733EC24C081DD353 /* SessionVerificationRequestDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1265FAF2C0AF1C30605BE7 /* SessionVerificationRequestDetailsView.swift */; }; @@ -1900,6 +1901,7 @@ 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemView.swift; sourceTree = ""; }; 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachmentData.swift; sourceTree = ""; }; 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenCoordinator.swift; sourceTree = ""; }; + 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = ""; }; 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = ""; }; 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = ""; }; @@ -3032,6 +3034,7 @@ 9EB9BA2F30EB8C33226D8FF1 /* UserSessionStoreMock.swift */, B23135B06B044CB811139D2F /* Generated */, E5E545F92D01588360A9BAC5 /* SDK */, + 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */, ); path = Mocks; sourceTree = ""; @@ -7096,6 +7099,7 @@ 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */, D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */, + 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */, FB595EC9C00AB32F39034055 /* SceneDelegate.swift in Sources */, 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */, 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 29b2dfc75..8b26c4c61 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -248,8 +248,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", - "version" : "1.17.5" + "revision" : "42a086182681cf661f5c47c9b7dc3931de18c6d7", + "version" : "1.17.6" } }, { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index c6361567d..db4da917b 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -14449,15 +14449,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - sendAudio - var sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendAudioUrlAudioInfoProgressSubjectRequestHandleCallsCount: Int { + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14465,27 +14465,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendAudioUrlAudioInfoProgressSubjectRequestHandleCalled: Bool { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleCallsCount > 0 + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendAudioUrlAudioInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14493,35 +14493,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendAudioUrlAudioInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure: ((URL, AudioInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure: ((URL, AudioInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendAudio(url: URL, audioInfo: AudioInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendAudioUrlAudioInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure = sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure { - return await sendAudioUrlAudioInfoProgressSubjectRequestHandleClosure(url, audioInfo, progressSubject, requestHandle) + func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure = sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure { + return await sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure(url, audioInfo, caption, progressSubject, requestHandle) } else { - return sendAudioUrlAudioInfoProgressSubjectRequestHandleReturnValue + return sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendFile - var sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendFileUrlFileInfoProgressSubjectRequestHandleCallsCount: Int { + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14529,27 +14529,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendFileUrlFileInfoProgressSubjectRequestHandleCalled: Bool { - return sendFileUrlFileInfoProgressSubjectRequestHandleCallsCount > 0 + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendFileUrlFileInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14557,35 +14557,35 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendFileUrlFileInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendFileUrlFileInfoProgressSubjectRequestHandleClosure: ((URL, FileInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure: ((URL, FileInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendFile(url: URL, fileInfo: FileInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendFileUrlFileInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendFileUrlFileInfoProgressSubjectRequestHandleClosure = sendFileUrlFileInfoProgressSubjectRequestHandleClosure { - return await sendFileUrlFileInfoProgressSubjectRequestHandleClosure(url, fileInfo, progressSubject, requestHandle) + func sendFile(url: URL, fileInfo: FileInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendFileUrlFileInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure = sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure { + return await sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure(url, fileInfo, caption, progressSubject, requestHandle) } else { - return sendFileUrlFileInfoProgressSubjectRequestHandleReturnValue + return sendFileUrlFileInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendImage - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCallsCount: Int { + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14593,27 +14593,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCalled: Bool { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCallsCount > 0 + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14621,22 +14621,22 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure: ((URL, URL, ImageInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure: ((URL, URL, ImageInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure = sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure { - return await sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleClosure(url, thumbnailURL, imageInfo, progressSubject, requestHandle) + func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure = sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure { + return await sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure(url, thumbnailURL, imageInfo, caption, progressSubject, requestHandle) } else { - return sendImageUrlThumbnailURLImageInfoProgressSubjectRequestHandleReturnValue + return sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendLocation @@ -14711,15 +14711,15 @@ class TimelineProxyMock: TimelineProxyProtocol { } //MARK: - sendVideo - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount = 0 - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCallsCount: Int { + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = 0 + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount: Int { get { if Thread.isMainThread { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount + returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount } return returnValue! @@ -14727,27 +14727,27 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingCallsCount = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingCallsCount = newValue } } } } - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCalled: Bool { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCallsCount > 0 + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCalled: Bool { + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount > 0 } - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue: Result! - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleReturnValue: Result! { + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue: Result! + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleReturnValue: Result! { get { if Thread.isMainThread { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } else { var returnValue: Result? = nil DispatchQueue.main.sync { - returnValue = sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue + returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue } return returnValue! @@ -14755,22 +14755,22 @@ class TimelineProxyMock: TimelineProxyProtocol { } set { if Thread.isMainThread { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleUnderlyingReturnValue = newValue + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleUnderlyingReturnValue = newValue } } } } - var sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure: ((URL, URL, VideoInfo, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? + var sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure: ((URL, URL, VideoInfo, String?, CurrentValueSubject?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result)? - func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { - sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleCallsCount += 1 - if let sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure { - return await sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleClosure(url, thumbnailURL, videoInfo, progressSubject, requestHandle) + func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { + sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleCallsCount += 1 + if let sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure { + return await sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure(url, thumbnailURL, videoInfo, caption, progressSubject, requestHandle) } else { - return sendVideoUrlThumbnailURLVideoInfoProgressSubjectRequestHandleReturnValue + return sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleReturnValue } } //MARK: - sendVoiceMessage diff --git a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift index 75a1a5c37..ff385d912 100644 --- a/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/JoinedRoomProxyMock.swift @@ -49,22 +49,8 @@ extension JoinedRoomProxyMock { id = configuration.id isEncrypted = configuration.isEncrypted - let timeline = TimelineProxyMock() - timeline.sendMessageEventContentReturnValue = .success(()) - timeline.paginateBackwardsRequestSizeReturnValue = .success(()) - timeline.paginateForwardsRequestSizeReturnValue = .success(()) - timeline.sendReadReceiptForTypeReturnValue = .success(()) - - if configuration.shouldUseAutoUpdatingTimeline { - timeline.underlyingTimelineProvider = AutoUpdatingRoomTimelineProviderMock() - } else { - let timelineProvider = RoomTimelineProviderMock() - timelineProvider.paginationState = .init(backward: configuration.timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached) - timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher() - timeline.underlyingTimelineProvider = timelineProvider - } - - self.timeline = timeline + timeline = TimelineProxyMock(.init(isAutoUpdating: configuration.shouldUseAutoUpdatingTimeline, + timelineStartReached: configuration.timelineStartReached)) ownUserID = configuration.ownUserID diff --git a/ElementX/Sources/Mocks/TimelineProxyMock.swift b/ElementX/Sources/Mocks/TimelineProxyMock.swift new file mode 100644 index 000000000..13147820e --- /dev/null +++ b/ElementX/Sources/Mocks/TimelineProxyMock.swift @@ -0,0 +1,35 @@ +// +// Copyright 2024 New Vector Ltd. +// +// SPDX-License-Identifier: AGPL-3.0-only +// Please see LICENSE in the repository root for full details. +// + +import Combine +import Foundation + +extension TimelineProxyMock { + struct Configuration { + var isAutoUpdating = false + var timelineStartReached = false + } + + @MainActor + convenience init(_ configuration: Configuration) { + self.init() + + sendMessageEventContentReturnValue = .success(()) + paginateBackwardsRequestSizeReturnValue = .success(()) + paginateForwardsRequestSizeReturnValue = .success(()) + sendReadReceiptForTypeReturnValue = .success(()) + + if configuration.isAutoUpdating { + underlyingTimelineProvider = AutoUpdatingRoomTimelineProviderMock() + } else { + let timelineProvider = RoomTimelineProviderMock() + timelineProvider.paginationState = .init(backward: configuration.timelineStartReached ? .timelineEndReached : .idle, forward: .timelineEndReached) + timelineProvider.underlyingMembershipChangePublisher = PassthroughSubject().eraseToAnyPublisher() + underlyingTimelineProvider = timelineProvider + } + } +} diff --git a/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift b/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift index 2551c02ca..a32482f47 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/BigIcon.swift @@ -50,7 +50,7 @@ struct BigIcon: View { var style: Style = .defaultSolid var body: some View { - CompoundIcon(icon, size: .custom(32), relativeTo: .title) + CompoundIcon(icon, size: .custom(32), relativeTo: .compound.headingLG) .modifier(BigIconModifier(style: style)) } } @@ -62,7 +62,7 @@ extension Image { resizable() .renderingMode(.template) .aspectRatio(contentMode: .fit) - .scaledPadding(insets, relativeTo: .title) + .scaledPadding(insets, relativeTo: .compound.headingLG) .modifier(BigIconModifier(style: style)) } } @@ -72,7 +72,7 @@ private struct BigIconModifier: ViewModifier { func body(content: Content) -> some View { content - .scaledFrame(size: 64, relativeTo: .title) + .scaledFrame(size: 64, relativeTo: .compound.headingLG) .foregroundColor(style.foregroundColor) .background { RoundedRectangle(cornerRadius: 14) diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift index c471ab42a..f9c1eb178 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenModels.swift @@ -15,6 +15,13 @@ struct MediaUploadPreviewScreenViewState: BindableState { let url: URL let title: String? var shouldDisableInteraction = false + + var bindings = MediaUploadPreviewScreenBindings() +} + +struct MediaUploadPreviewScreenBindings: BindableState { + var caption = NSAttributedString() + var presendCallback: (() -> Void)? } enum MediaUploadPreviewScreenViewAction { diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift index cca94f2cc..c7f2164db 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/MediaUploadPreviewScreenViewModel.swift @@ -42,6 +42,9 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, } override func process(viewAction: MediaUploadPreviewScreenViewAction) { + // Get the current caption before all the processing starts. + let caption = state.bindings.caption.nonBlankString + switch viewAction { case .send: Task { @@ -51,7 +54,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, switch await mediaUploadingPreprocessor.processMedia(at: url) { case .success(let mediaInfo): - switch await sendAttachment(mediaInfo: mediaInfo, progressSubject: progressSubject) { + switch await sendAttachment(mediaInfo: mediaInfo, caption: caption, progressSubject: progressSubject) { case .success: actionsSubject.send(.dismiss) case .failure(let error): @@ -75,20 +78,38 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, // MARK: - Private - private func sendAttachment(mediaInfo: MediaInfo, progressSubject: CurrentValueSubject?) async -> Result { + private func sendAttachment(mediaInfo: MediaInfo, caption: String?, progressSubject: CurrentValueSubject?) async -> Result { let requestHandle: ((SendAttachmentJoinHandleProtocol) -> Void) = { [weak self] handle in self?.requestHandle = handle } switch mediaInfo { case let .image(imageURL, thumbnailURL, imageInfo): - return await roomProxy.timeline.sendImage(url: imageURL, thumbnailURL: thumbnailURL, imageInfo: imageInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendImage(url: imageURL, + thumbnailURL: thumbnailURL, + imageInfo: imageInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) case let .video(videoURL, thumbnailURL, videoInfo): - return await roomProxy.timeline.sendVideo(url: videoURL, thumbnailURL: thumbnailURL, videoInfo: videoInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendVideo(url: videoURL, + thumbnailURL: thumbnailURL, + videoInfo: videoInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) case let .audio(audioURL, audioInfo): - return await roomProxy.timeline.sendAudio(url: audioURL, audioInfo: audioInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendAudio(url: audioURL, + audioInfo: audioInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) case let .file(fileURL, fileInfo): - return await roomProxy.timeline.sendFile(url: fileURL, fileInfo: fileInfo, progressSubject: progressSubject, requestHandle: requestHandle) + return await roomProxy.timeline.sendFile(url: fileURL, + fileInfo: fileInfo, + caption: caption, + progressSubject: progressSubject, + requestHandle: requestHandle) } } @@ -118,3 +139,10 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType, userIndicatorController.submitIndicator(UserIndicator(title: label)) } } + +extension NSAttributedString { + var nonBlankString: String? { + guard !string.isBlank else { return nil } + return string + } +} diff --git a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift index 30db52e56..6da34ba5e 100644 --- a/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift +++ b/ElementX/Sources/Screens/MediaUploadPreviewScreen/View/MediaUploadPreviewScreen.swift @@ -5,6 +5,7 @@ // Please see LICENSE in the repository root for full details. // +import Compound import QuickLook import SwiftUI @@ -17,13 +18,20 @@ struct MediaUploadPreviewScreen: View { var body: some View { mainContent - .id(UUID()) + .id(context.viewState.url) + .ignoresSafeArea(edges: [.horizontal]) + .safeAreaInset(edge: .bottom, spacing: 0) { + composer + .padding(.horizontal, 12) + .padding(.vertical, 16) + .background() // Don't use compound so we match the QLPreviewController. + } .navigationTitle(title) .navigationBarTitleDisplayMode(.inline) - .disabled(context.viewState.shouldDisableInteraction) - .ignoresSafeArea(edges: [.horizontal, .bottom]) .toolbar { toolbar } + .disabled(context.viewState.shouldDisableInteraction) .interactiveDismissDisabled() + .preferredColorScheme(.dark) } @ViewBuilder @@ -38,18 +46,31 @@ struct MediaUploadPreviewScreen: View { } } + private var composer: some View { + HStack(spacing: 12) { + MessageComposerTextField(placeholder: L10n.richTextEditorComposerCaptionPlaceholder, + text: $context.caption, + presendCallback: $context.presendCallback, + maxHeight: ComposerConstant.maxHeight, + keyHandler: { _ in }, + pasteHandler: { _ in }) + .messageComposerStyle() + + SendButton { + context.send(viewAction: .send) + } + } + } + @ToolbarContentBuilder private var toolbar: some ToolbarContent { ToolbarItem(placement: .cancellationAction) { Button { context.send(viewAction: .cancel) } label: { Text(L10n.actionCancel) } - } - ToolbarItem(placement: .confirmationAction) { - Button { context.send(viewAction: .send) } label: { - Text(L10n.actionSend) - } - .disabled(context.viewState.shouldDisableInteraction) + // Fix a bug with the preferredColorScheme on iOS 18 where the button doesn't + // follow the dark colour scheme on devices running with dark mode disabled. + .tint(.compound.textActionPrimary) } } } @@ -111,21 +132,6 @@ private class PreviewItem: NSObject, QLPreviewItem { } } -// MARK: - Previews - -struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview { - static let viewModel = MediaUploadPreviewScreenViewModel(userIndicatorController: UserIndicatorControllerMock.default, - roomProxy: JoinedRoomProxyMock(), - mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), - title: "some random file name", - url: URL.picturesDirectory) - static var previews: some View { - NavigationStack { - MediaUploadPreviewScreen(context: viewModel.context) - } - } -} - private class PreviewViewController: QLPreviewController { override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() @@ -137,3 +143,21 @@ private class PreviewViewController: QLPreviewController { toolbarItems?.first?.isHidden = true } } + +// MARK: - Previews + +struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview { + static let snapshotURL = URL.picturesDirectory + static let testURL = Bundle.main.url(forResource: "AppIcon60x60@2x", withExtension: "png") + + static let viewModel = MediaUploadPreviewScreenViewModel(userIndicatorController: UserIndicatorControllerMock.default, + roomProxy: JoinedRoomProxyMock(), + mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), + title: "App Icon.png", + url: snapshotURL) + static var previews: some View { + NavigationStack { + MediaUploadPreviewScreen(context: viewModel.context) + } + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift index 0cb580d0a..aa6c14db2 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/ComposerToolbar.swift @@ -62,7 +62,7 @@ struct ComposerToolbar: View { if !context.composerFormattingEnabled { if context.viewState.isUploading { ProgressView() - .scaledFrame(size: 44, relativeTo: .title) + .scaledFrame(size: 44, relativeTo: .compound.headingLG) .padding(.leading, 3) } else if context.viewState.showSendButton { sendButton @@ -119,27 +119,29 @@ struct ComposerToolbar: View { Image(Asset.Images.closeRte.name) .resizable() .scaledToFit() - .scaledFrame(size: 30, relativeTo: .title) - .scaledPadding(7, relativeTo: .title) + .scaledFrame(size: 30, relativeTo: .compound.headingLG) + .scaledPadding(7, relativeTo: .compound.headingLG) } .accessibilityLabel(L10n.actionClose) .accessibilityIdentifier(A11yIdentifiers.roomScreen.composerToolbar.closeFormattingOptions) } private var sendButton: some View { - Button { - sendMessage() - } label: { - CompoundIcon(context.viewState.composerMode.isEdit ? \.check : \.sendSolid) - .scaledPadding(6, relativeTo: .title) - .accessibilityLabel(context.viewState.composerMode.isEdit ? L10n.actionConfirm : L10n.actionSend) - .foregroundColor(context.viewState.sendButtonDisabled ? .compound.iconDisabled : .white) - .background { - Circle() - .foregroundColor(context.viewState.sendButtonDisabled ? .clear : .compound.iconAccentTertiary) + Group { + if context.viewState.composerMode.isEdit { + Button(action: sendMessage) { + CompoundIcon(\.check, size: .medium, relativeTo: .compound.headingLG) + .foregroundColor(.white) + .scaledPadding(6, relativeTo: .compound.headingLG) + .background(.compound.iconAccentTertiary, in: Circle()) + .accessibilityLabel(L10n.actionConfirm) } - .scaledPadding(4, relativeTo: .title) + } else { + SendButton(action: sendMessage) + .accessibilityLabel(L10n.actionSend) + } } + .scaledPadding(4, relativeTo: .compound.headingLG) .disabled(context.viewState.sendButtonDisabled) .animation(.linear(duration: 0.1).disabledDuringTests(), value: context.viewState.sendButtonDisabled) .keyboardShortcut(.return, modifiers: [.command]) @@ -271,8 +273,8 @@ struct ComposerToolbar: View { } label: { CompoundIcon(\.delete) .scaledToFit() - .scaledFrame(size: 30, relativeTo: .title) - .scaledPadding(7, relativeTo: .title) + .scaledFrame(size: 30, relativeTo: .compound.headingLG) + .scaledPadding(7, relativeTo: .compound.headingLG) } .buttonStyle(.compound(.plain)) .accessibilityLabel(L10n.a11yDelete) @@ -291,6 +293,8 @@ struct ComposerToolbar: View { } } +// MARK: - Previews + struct ComposerToolbar_Previews: PreviewProvider, TestablePreview { static let wysiwygViewModel = WysiwygComposerViewModel() static let composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, @@ -330,8 +334,6 @@ struct ComposerToolbar_Previews: PreviewProvider, TestablePreview { } } -// MARK: - Mock - extension ComposerToolbar { static func mock(focused: Bool = true) -> ComposerToolbar { let wysiwygViewModel = WysiwygComposerViewModel() diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift index 809c80279..89f8903d0 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/MessageComposer.swift @@ -35,17 +35,8 @@ struct MessageComposer: View { resizeGrabber } - mainContent - .padding(.horizontal, 12.0) - .clipShape(composerShape) - .background { - ZStack { - composerShape - .fill(Color.compound.bgSubtleSecondary) - composerShape - .stroke(Color.compound._borderTextFieldFocused, lineWidth: 0.5) - } - } + composerTextField + .messageComposerStyle(header: header) // Explicitly disable all animations to fix weirdness with the header immediately // appearing whilst the text field and keyboard are still animating up to it. .animation(.noAnimation, value: mode) @@ -57,34 +48,27 @@ struct MessageComposer: View { @State private var composerFrame = CGRect.zero - private var mainContent: some View { - VStack(alignment: .leading, spacing: -6) { - header - - if composerFormattingEnabled { - Color.clear - .overlay(alignment: .top) { - composerView - .clipped() - .readFrame($composerFrame) - } - .frame(minHeight: ComposerConstant.minHeight, maxHeight: max(composerHeight, composerFrame.height), - alignment: .top) - .tint(.compound.iconAccentTertiary) - .padding(.vertical, 10) - .onAppear { - onAppearAction() - } - } else { - MessageComposerTextField(placeholder: L10n.richTextEditorComposerPlaceholder, - text: $plainComposerText, - presendCallback: $presendCallback, - maxHeight: ComposerConstant.maxHeight, - keyHandler: { handleKeyPress($0) }, - pasteHandler: pasteAction) - .tint(.compound.iconAccentTertiary) - .padding(.vertical, 10) - } + @ViewBuilder + private var composerTextField: some View { + if composerFormattingEnabled { + Color.clear + .overlay(alignment: .top) { + composerView + .clipped() + .readFrame($composerFrame) + } + .frame(minHeight: ComposerConstant.minHeight, maxHeight: max(composerHeight, composerFrame.height), + alignment: .top) + .onAppear { + onAppearAction() + } + } else { + MessageComposerTextField(placeholder: L10n.richTextEditorComposerPlaceholder, + text: $plainComposerText, + presendCallback: $presendCallback, + maxHeight: ComposerConstant.maxHeight, + keyHandler: { handleKeyPress($0) }, + pasteHandler: pasteAction) } } @@ -200,6 +184,42 @@ private struct MessageComposerHeaderLabelStyle: LabelStyle { } } +// MARK: - Style + +extension View { + func messageComposerStyle(header: some View = EmptyView()) -> some View { + modifier(MessageComposerStyleModifier(header: header)) + } +} + +private struct MessageComposerStyleModifier: ViewModifier { + private let composerShape = RoundedRectangle(cornerRadius: 21, style: .circular) + + let header: Header + + func body(content: Content) -> some View { + VStack(alignment: .leading, spacing: -6) { + header + + content + .tint(.compound.iconAccentTertiary) + .padding(.vertical, 10) + } + .padding(.horizontal, 12.0) + .clipShape(composerShape) + .background { + ZStack { + composerShape + .fill(Color.compound.bgSubtleSecondary) + composerShape + .stroke(Color.compound.borderInteractiveSecondary, lineWidth: 0.5) + } + } + } +} + +// MARK: - Previews + struct MessageComposer_Previews: PreviewProvider, TestablePreview { static let viewModel = TimelineViewModel.mock diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift index 791ee8d54..0732bd15f 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/RoomAttachmentPicker.swift @@ -18,8 +18,8 @@ struct RoomAttachmentPicker: View { Menu { menuContent } label: { - CompoundIcon(asset: Asset.Images.composerAttachment, size: .custom(30), relativeTo: .title) - .scaledPadding(7, relativeTo: .title) + CompoundIcon(asset: Asset.Images.composerAttachment, size: .custom(30), relativeTo: .compound.headingLG) + .scaledPadding(7, relativeTo: .compound.headingLG) } .buttonStyle(RoomAttachmentPickerButtonStyle()) .accessibilityLabel(L10n.actionAddToTimeline) diff --git a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift index 8688f0f6c..c998209e5 100644 --- a/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift +++ b/ElementX/Sources/Screens/RoomScreen/ComposerToolbar/View/VoiceMessageRecordingButton.swift @@ -32,18 +32,15 @@ struct VoiceMessageRecordingButton: View { } label: { switch mode { case .idle: - CompoundIcon(\.micOn, size: .medium, relativeTo: .title) + CompoundIcon(\.micOn, size: .medium, relativeTo: .compound.headingLG) .foregroundColor(.compound.iconSecondary) - .scaledPadding(10, relativeTo: .title) + .scaledPadding(10, relativeTo: .compound.headingLG) case .recording: - CompoundIcon(asset: Asset.Images.stopRecording, size: .medium, relativeTo: .title) + CompoundIcon(asset: Asset.Images.stopRecording, size: .medium, relativeTo: .compound.headingLG) .foregroundColor(.compound.iconOnSolidPrimary) - .scaledPadding(6, relativeTo: .title) - .background( - Circle() - .foregroundColor(.compound.bgActionPrimaryRest) - ) - .scaledPadding(4, relativeTo: .title) + .scaledPadding(6, relativeTo: .compound.headingLG) + .background(.compound.bgActionPrimaryRest, in: Circle()) + .scaledPadding(4, relativeTo: .compound.headingLG) } } .buttonStyle(VoiceMessageRecordingButtonStyle()) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxy.swift b/ElementX/Sources/Services/Timeline/TimelineProxy.swift index 4309d206c..0a7a1b1dc 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxy.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxy.swift @@ -223,13 +223,14 @@ final class TimelineProxy: TimelineProxyProtocol { func sendAudio(url: URL, audioInfo: AudioInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending audio") let handle = timeline.sendAudio(url: url.path(percentEncoded: false), audioInfo: audioInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) @@ -251,13 +252,14 @@ final class TimelineProxy: TimelineProxyProtocol { func sendFile(url: URL, fileInfo: FileInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending file") let handle = timeline.sendFile(url: url.path(percentEncoded: false), fileInfo: fileInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) @@ -277,9 +279,11 @@ final class TimelineProxy: TimelineProxyProtocol { return .success(()) } + // swiftlint:disable:next function_parameter_count func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending image") @@ -287,7 +291,7 @@ final class TimelineProxy: TimelineProxyProtocol { let handle = timeline.sendImage(url: url.path(percentEncoded: false), thumbnailUrl: thumbnailURL.path(percentEncoded: false), imageInfo: imageInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) @@ -325,9 +329,11 @@ final class TimelineProxy: TimelineProxyProtocol { return .success(()) } + // swiftlint:disable:next function_parameter_count func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result { MXLog.info("Sending video") @@ -335,7 +341,7 @@ final class TimelineProxy: TimelineProxyProtocol { let handle = timeline.sendVideo(url: url.path(percentEncoded: false), thumbnailUrl: thumbnailURL.path(percentEncoded: false), videoInfo: videoInfo, - caption: nil, + caption: caption, formattedCaption: nil, progressWatcher: UploadProgressListener { progress in progressSubject?.send(progress) diff --git a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift index e1c8b5f6f..d0d5285fb 100644 --- a/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift +++ b/ElementX/Sources/Services/Timeline/TimelineProxyProtocol.swift @@ -51,17 +51,21 @@ protocol TimelineProxyProtocol { func sendAudio(url: URL, audioInfo: AudioInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result func sendFile(url: URL, fileInfo: FileInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result + // swiftlint:disable:next function_parameter_count func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result @@ -71,9 +75,11 @@ protocol TimelineProxyProtocol { zoomLevel: UInt8?, assetType: AssetType?) async -> Result + // swiftlint:disable:next function_parameter_count func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, + caption: String?, progressSubject: CurrentValueSubject?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png index 0d9570e80..49a9a3287 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ed83944ed745ce8ba0d41ee0ccc0e343b917875cb190fb83f869ca5200df8555 -size 75517 +oid sha256:888932f08b86692e4ed6d35aa438a1fa4839a0247ef4d4e8109f9f4d2902a2a7 +size 75306 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png index 24ca0f3d3..d7f9d22c7 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:474774d07c69a9652245a6f2e31b57fc29325592cd98f9455ddb53fca0d3c047 -size 93517 +oid sha256:3005df9a148c026be35620606d64fd479601439bf2bdda4d3d56113d121464d7 +size 93485 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png index 6d783efa9..51071b686 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:649cf6ecbb5506ff2d3d88932950bb965f5ce21529f97d10c0bf065f51931f23 -size 95810 +oid sha256:a8a8066e41d3d84e7aedc675e7991b0dd57fc1f93f363312353bf43a236e3f6a +size 101416 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png index 2ee57674c..e594e1dd0 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-en-GB.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e4fd5cfb6d8191e632c5a5b0d2a9f89b50b36d1547d903971a9498ce6c6cb32a -size 98356 +oid sha256:1b8ef13343f827c0dc3e9aaf74ce28f8a3e96bb0f4b9aa457e6a9ff40b3ad632 +size 98059 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png index 1651742e0..cc67cd414 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fd2db090826802de3831227fbb81614deea2ecd62c1e3cff9488d0e4c4c113f -size 75899 +oid sha256:d546bdab2d2ff0d1f674bc5f5d7583f7a60c338a8ee6e94041ed4ed07a106a31 +size 75724 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png index fe8714849..deb7d6373 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a716604e488f96f610770f9b550e36ba5caf6cafaf7c1e24155cd3ff498b1a98 -size 94344 +oid sha256:b9c15c54c93c21400eb263cbc0575f86d1c47377d2f73a2fe59ec8d7886914e3 +size 94359 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png index d93d75328..f293f957b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ab78db432612172ab37dae1e1c2972d7ec1e8398034df87f32d97e5ccef19c5d -size 96540 +oid sha256:8fcc46292a1139dab8462e81a1f91bc177e9a05cbcf8ff6ef5ddbe15707cfdf8 +size 102213 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png index 489b79684..0deed32f4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPad-pseudo.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9ed7b4e33493a6206a97101e5f241cb331afd24b39d60e60af8d577a30aa1cc0 -size 98738 +oid sha256:516b16553d506445d965c708a5f56e5b9c53b23488809a2513a56c2368a2d633 +size 98477 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png index 09364f55a..4edb59584 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:29c7624de3004d0a17828fd97c74b516cd420781c2c7a7c96d6383d8befcc9c5 -size 34590 +oid sha256:d4a497fc8cb28e5187c80bf8caec98e69c9faec1ed153b1c2beaa52aa8cd8ae1 +size 34435 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png index 1acfcc6c5..f0b7d423a 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:34126123e98e38598b990f5a0e5c7a4f80d58b336131dcbd0646e2dbe4e8c754 -size 51216 +oid sha256:942b0ff59359bbfe7a1ae88f7acf44b856f763d91688bac8ad173a7eda405972 +size 50565 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png index 827b509aa..029173618 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c18ac30d254a8ab48fd16bdd213b4000944ead4e634a69cc6a808e1408805c65 -size 52052 +oid sha256:6ffa98f5f715b47251f816c0fcab5c4ff62d51d60270f8a41a34ca3835c3e0f6 +size 58631 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png index a4224c5d3..b4ce7760f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-en-GB.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b1c8b56332155977848329ca750ac240b304210abef5587519f8e2e222435a42 -size 53760 +oid sha256:b4bc7dbfbb1c7c58641f7d19bcb648e792220c19919b9001b09bdc8ccda0c86f +size 53599 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png index a50fe3f0e..b93a576a4 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:69c9c7a7368afc683ed8ee311038cea74c1305dc96c2594e3ef1e089a5044353 -size 35006 +oid sha256:67d481416b45627802785280c9dd03bc5f634902b64a4beacd567b42fd0a444c +size 34849 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png index 1f2018dfc..1074662e1 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Reply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:463bece34b226141be90906cc7aeb56f55e217034f25befa0eee5ab7fc9a9cde -size 52029 +oid sha256:9c9ed32588b6de5c4c2c87c14a54a4d436648518cf6b7807a16a39be20332778 +size 51436 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png index efb7b232d..2dfa3ceba 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.Voice-Message.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:938c55d264a5ec64d9f982482b93c0a1f15b3454b19f7ea61b6a91a82f56fccc -size 52835 +oid sha256:b411f75a2ce4d925ee0170cb0956129fd26b1c2d8b64b0741b82699bc058e6b6 +size 59463 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png index f5722c579..0c9096622 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_composerToolbar-iPhone-16-pseudo.With-Suggestions.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88408dc1dd51e53dec8a4d476c4a42b7d2bdea768430be9002e48ce554ed753c -size 54176 +oid sha256:fd4bca95fba0ed2e11a1212c1ac3d1a638815274c370a1bdb4a3dd825c89de6d +size 54013 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png index c36548dd7..a218dc80e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:142460487dd7b40c347faeb4ce229bc900cee12d358288edec544fa7f74f26b8 -size 78954 +oid sha256:885fb08cfe301dd996fa6f1b276afa7a74f6534d692ab313ec7d64bfcb970981 +size 91980 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png index da0b314e6..687ed4884 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:740a28f97bf1d14670f314d0030a013e2aa6349551dbdc7c11e95334c05c4ac6 -size 79591 +oid sha256:ab99e9ac3233f55705f96cc0c8f1480351f0765b7b36d1e90e3262758b2ede9a +size 93223 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png index 2d9b3cd6a..748902c2b 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b48e09d6a5605dd6e21141b176b17f7637c59be6bdee67d3650c1d61fd06493 -size 39052 +oid sha256:3cd02932f70d0c1336b295d94ca31694f569fea56b36b8cc29c448284406e8dd +size 50622 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png index b6ea52d1e..960476010 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_mediaUploadPreviewScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d24d5f89ef4e437525e82bd0aa0ab52f9f6c7463bbec799c8d5de724294d0f9c -size 39482 +oid sha256:26109f9334be8c7452fd98c15158bea787df6b87f560f8ee6b6aea46dc6a1647 +size 51627 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png index 00c09a774..aee9e9b7d 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:620197da87f254260dca5e965abc6e6cbd9f7743c01a236c58b8642437b92047 -size 98722 +oid sha256:1a5e7e651f73e10b1b7c5fad0a3eb631d9f50f5f42286f1faaed852316dd287d +size 98836 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png index 2773e1257..e7368f76c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a034b807916e062e25c5fb59ecd09a47d0e1c7c822534b35e992fd9c839ab07 -size 196481 +oid sha256:71cb80dc579a03031aa4de25bf2af339ddd8670651c0e3a5b4fb5d0423592455 +size 196910 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png index 2773e1257..e7368f76c 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-en-GB.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a034b807916e062e25c5fb59ecd09a47d0e1c7c822534b35e992fd9c839ab07 -size 196481 +oid sha256:71cb80dc579a03031aa4de25bf2af339ddd8670651c0e3a5b4fb5d0423592455 +size 196910 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png index 39f60f5f6..61a955e37 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a632e640aefa28698b33f87eb8a8576db9021ea3e0f6cbbddcf3d7c61f71c35 -size 99789 +oid sha256:4914f7dc335cc0333584c2ad34034ce5a28e6fb3bb52d05f27734ed2dae5e7a6 +size 99876 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png index 26e53c7a3..f76ef1279 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffe1ceda422b0bccc1e587036ea047bebb4ee4643f54bdf25ff2b3b530b6f7e2 -size 199662 +oid sha256:218956837978d0f8f16b8744a064f5ed78be91a8be0a712cae7536f54867319c +size 200002 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png index 26e53c7a3..f76ef1279 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPad-pseudo.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ffe1ceda422b0bccc1e587036ea047bebb4ee4643f54bdf25ff2b3b530b6f7e2 -size 199662 +oid sha256:218956837978d0f8f16b8744a064f5ed78be91a8be0a712cae7536f54867319c +size 200002 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png index b0eb8e49a..a28707e06 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbfd12737413020fd7c0ff01c1b276f57ced10e33be2ea41977d3faf79050857 -size 54984 +oid sha256:9951096cb1ddc3050415353192108a4489908d8355b30189845a7da5fa2b5d83 +size 55103 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png index e58f1c116..69aeadc93 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91bef32e5248f8084995b237b671cea005ce0eb9253a325165dd066a43934bfa -size 135848 +oid sha256:19d120c20ff2a374d05884e6599032a4a3d4982dd9e2d19bc4e28e95f79cb4e0 +size 136286 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png index e58f1c116..69aeadc93 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-en-GB.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:91bef32e5248f8084995b237b671cea005ce0eb9253a325165dd066a43934bfa -size 135848 +oid sha256:19d120c20ff2a374d05884e6599032a4a3d4982dd9e2d19bc4e28e95f79cb4e0 +size 136286 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png index b237a68c6..bda11829e 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:702ac84c437121bd0c7370fc5de6928cf60894554c00dcb721924f349db4c991 -size 57150 +oid sha256:745116e5588711197b37e391b2f2ca6359c9a4cb8b3dd718ec55dd29c33d72a1 +size 57224 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png index 39ebe4462..990235129 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying-in-thread.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5fd3ee0cc6bb3cf124cc66877d87cde800a3da7c10f8e26d6e19d884f4ca40e -size 139138 +oid sha256:da4f3b1174b24ae18c931db745a788e01793f73693fe132cb29836728db76172 +size 139540 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png index 39ebe4462..990235129 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_messageComposer-iPhone-16-pseudo.Replying.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5fd3ee0cc6bb3cf124cc66877d87cde800a3da7c10f8e26d6e19d884f4ca40e -size 139138 +oid sha256:da4f3b1174b24ae18c931db745a788e01793f73693fe132cb29836728db76172 +size 139540 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png index ff3b7d7e6..742befb2f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:033f43d5be47abd91cd5f36b93a8b32b0f9800e7a8a947e0c2cd4debd8b4c694 -size 295633 +oid sha256:906409795a47057b2da67dc7a50221b6a9be839309cf434899d3ee7c19735c83 +size 295656 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png index 65b5872de..76fe17dfe 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc959ac1d5a22da8ca928d891e9f0a649dfa28b1cdfa7a91b0a74d2189cc38a3 -size 297711 +oid sha256:38a6eea96f81ab5acd88b75823745cc7bb71c237ff0ca181e05e0263abc487d9 +size 297761 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png index bd01dd63c..037e6f2ee 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26de643c28b47f7fd0631c0c754d979c43fc51bc274e863fdb6acaf0ed299960 -size 180507 +oid sha256:6b8ab1d9311c44e85d8e145a9290e97aa2b37070a3104402332479ec8c2fd739 +size 180530 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png index 10b37a11f..d1aac8e16 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_roomScreen-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58ae4f390371ef48aca7b5faeb4c75ba7bdfad4294797fd422c0d102036ee4a8 -size 178571 +oid sha256:f5843af5ad8774b2d73bc57b18caacb79cfa46abc54c797b5c17948f961ded06 +size 178598 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png index ff3b7d7e6..742befb2f 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:033f43d5be47abd91cd5f36b93a8b32b0f9800e7a8a947e0c2cd4debd8b4c694 -size 295633 +oid sha256:906409795a47057b2da67dc7a50221b6a9be839309cf434899d3ee7c19735c83 +size 295656 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png index 65b5872de..76fe17dfe 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPad-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc959ac1d5a22da8ca928d891e9f0a649dfa28b1cdfa7a91b0a74d2189cc38a3 -size 297711 +oid sha256:38a6eea96f81ab5acd88b75823745cc7bb71c237ff0ca181e05e0263abc487d9 +size 297761 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png index bd01dd63c..037e6f2ee 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-en-GB.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:26de643c28b47f7fd0631c0c754d979c43fc51bc274e863fdb6acaf0ed299960 -size 180507 +oid sha256:6b8ab1d9311c44e85d8e145a9290e97aa2b37070a3104402332479ec8c2fd739 +size 180530 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png index 10b37a11f..d1aac8e16 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/test_timelineView-iPhone-16-pseudo.1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58ae4f390371ef48aca7b5faeb4c75ba7bdfad4294797fd422c0d102036ee4a8 -size 178571 +oid sha256:f5843af5ad8774b2d73bc57b18caacb79cfa46abc54c797b5c17948f961ded06 +size 178598 diff --git a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift index 880f27acb..c74ec0318 100644 --- a/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift +++ b/UnitTests/Sources/MediaUploadPreviewScreenViewModelTests.swift @@ -10,4 +10,135 @@ import XCTest @testable import ElementX @MainActor -class MediaUploadPreviewScreenViewModelTests: XCTestCase { } +class MediaUploadPreviewScreenViewModelTests: XCTestCase { + var timelineProxy: TimelineProxyMock! + var viewModel: MediaUploadPreviewScreenViewModel! + var context: MediaUploadPreviewScreenViewModel.Context { viewModel.context } + + enum TestError: Swift.Error { + case unexpectedParameter + case unknown + } + + override func setUp() { + AppSettings.resetAllSettings() + let appSettings = AppSettings() + appSettings.optimizeMediaUploads = false + ServiceLocator.shared.register(appSettings: appSettings) + } + + deinit { + AppSettings.resetAllSettings() + } + + func testImageUploadWithoutCaption() async throws { + setUpViewModel(url: imageURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testImageUploadWithBlankCaption() async throws { + setUpViewModel(url: imageURL, expectedCaption: nil) + context.caption = .init(" ") + try await send() + } + + func testImageUploadWithCaption() async throws { + let caption = "This is a really great image!" + setUpViewModel(url: imageURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + func testVideoUploadWithoutCaption() async throws { + setUpViewModel(url: videoURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testVideoUploadWithCaption() async throws { + let caption = "Check out this video!" + setUpViewModel(url: videoURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + func testAudioUploadWithoutCaption() async throws { + setUpViewModel(url: audioURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testAudioUploadWithCaption() async throws { + let caption = "Listen to this!" + setUpViewModel(url: audioURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + func testFileUploadWithoutCaption() async throws { + setUpViewModel(url: fileURL, expectedCaption: nil) + context.caption = .init("") + try await send() + } + + func testFileUploadWithCaption() async throws { + let caption = "Please will you check my article." + setUpViewModel(url: fileURL, expectedCaption: caption) + context.caption = .init(string: caption) + try await send() + } + + // MARK: - Helpers + + private var audioURL: URL { assertResourceURL(filename: "test_audio.mp3") } + private var fileURL: URL { assertResourceURL(filename: "test_pdf.pdf") } + private var imageURL: URL { assertResourceURL(filename: "test_animated_image.gif") } + private var videoURL: URL { assertResourceURL(filename: "landscape_test_video.mov") } + + private func assertResourceURL(filename: String) -> URL { + guard let url = Bundle(for: Self.self).url(forResource: filename, withExtension: nil) else { + XCTFail("Failed retrieving test asset") + return .picturesDirectory + } + return url + } + + private func setUpViewModel(url: URL, expectedCaption: String?) { + timelineProxy = TimelineProxyMock(.init()) + timelineProxy.sendAudioUrlAudioInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + timelineProxy.sendFileUrlFileInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + timelineProxy.sendImageUrlThumbnailURLImageInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + timelineProxy.sendVideoUrlThumbnailURLVideoInfoCaptionProgressSubjectRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in + self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown)) + } + + let roomProxy = JoinedRoomProxyMock(.init()) + roomProxy.timeline = timelineProxy + viewModel = MediaUploadPreviewScreenViewModel(userIndicatorController: UserIndicatorControllerMock(), + roomProxy: roomProxy, + mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings), + title: "Some File", + url: url) + } + + private func verifyCaption(_ caption: String?, expectedCaption: String?) -> Result { + guard caption == expectedCaption else { + XCTFail("The sent caption '\(caption ?? "nil")' does not match the expected value '\(expectedCaption ?? "nil")'").self + return .failure(.sdkError(TestError.unexpectedParameter)) + } + return .success(()) + } + + private func send() async throws { + let deferred = deferFulfillment(viewModel.actions) { $0 == .dismiss } + context.send(viewAction: .send) + try await deferred.fulfill() + } +}