mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Add support for sending media within threads.
This patch add the `threadRootEventID` as a parameter to media sending functions and forwards the timeline thread root between various application states to the place where its needed. The 2 missing items are Locations and Polls which currently don't have any support on the Rust side for being sent within threads. That will come in a separate PR.
This commit is contained in:
committed by
Stefan Ceriu
parent
6481093107
commit
558cdf5be3
@@ -301,8 +301,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (_, .presentReportContent, .reportContent(let itemID, let senderID, _)):
|
case (_, .presentReportContent, .reportContent(let itemID, let senderID, _)):
|
||||||
presentReportContent(for: itemID, from: senderID)
|
presentReportContent(for: itemID, from: senderID)
|
||||||
|
|
||||||
case (_, .presentMediaUploadPicker, .mediaUploadPicker(let source, _)):
|
case (_, .presentMediaUploadPicker, .mediaUploadPicker(let source, let threadRootEventID, _)):
|
||||||
presentMediaUploadPickerWithSource(source)
|
presentMediaUploadPickerWithSource(source, threadRootEventID: threadRootEventID)
|
||||||
|
|
||||||
case (_, .presentEmojiPicker, .emojiPicker(let itemID, let selectedEmoji, _)):
|
case (_, .presentEmojiPicker, .emojiPicker(let itemID, let selectedEmoji, _)):
|
||||||
presentEmojiPicker(for: itemID, selectedEmoji: selectedEmoji)
|
presentEmojiPicker(for: itemID, selectedEmoji: selectedEmoji)
|
||||||
@@ -387,8 +387,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case (.pollsHistory, .presentPollForm(let mode), .pollsHistoryForm):
|
case (.pollsHistory, .presentPollForm(let mode), .pollsHistoryForm):
|
||||||
presentPollForm(mode: mode)
|
presentPollForm(mode: mode)
|
||||||
|
|
||||||
case (_, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL, _)):
|
case (_, .presentMediaUploadPreview, .mediaUploadPreview(let fileURL, let threadRootEventID, _)):
|
||||||
presentMediaUploadPreviewScreen(for: fileURL, animated: animated)
|
presentMediaUploadPreviewScreen(for: fileURL, threadRootEventID: threadRootEventID, animated: animated)
|
||||||
|
|
||||||
case (_, .presentInviteUsersScreen, .inviteUsersScreen):
|
case (_, .presentInviteUsersScreen, .inviteUsersScreen):
|
||||||
presentInviteUsersScreen()
|
presentInviteUsersScreen()
|
||||||
@@ -441,7 +441,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case .eventFocus(let focusedEvent):
|
case .eventFocus(let focusedEvent):
|
||||||
roomScreenCoordinator?.focusOnEvent(focusedEvent)
|
roomScreenCoordinator?.focusOnEvent(focusedEvent)
|
||||||
case .share(.mediaFile(_, let mediaFile)):
|
case .share(.mediaFile(_, let mediaFile)):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url), userInfo: EventUserInfo(animated: animated))
|
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url, threadRootEventID: nil),
|
||||||
|
userInfo: EventUserInfo(animated: animated))
|
||||||
case .share(.text(_, let text)):
|
case .share(.text(_, let text)):
|
||||||
roomScreenCoordinator?.shareText(text)
|
roomScreenCoordinator?.shareText(text)
|
||||||
case .none:
|
case .none:
|
||||||
@@ -477,7 +478,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
|
|
||||||
switch presentationAction {
|
switch presentationAction {
|
||||||
case .share(.mediaFile(_, let mediaFile)):
|
case .share(.mediaFile(_, let mediaFile)):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url), userInfo: EventUserInfo(animated: animated))
|
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: mediaFile.url, threadRootEventID: nil),
|
||||||
|
userInfo: EventUserInfo(animated: animated))
|
||||||
case .share(.text), .eventFocus:
|
case .share(.text), .eventFocus:
|
||||||
break // These are both handled in the coordinator's init.
|
break // These are both handled in the coordinator's init.
|
||||||
case .none:
|
case .none:
|
||||||
@@ -528,9 +530,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case .presentReportContent(let itemID, let senderID):
|
case .presentReportContent(let itemID, let senderID):
|
||||||
stateMachine.tryEvent(.presentReportContent(itemID: itemID, senderID: senderID))
|
stateMachine.tryEvent(.presentReportContent(itemID: itemID, senderID: senderID))
|
||||||
case .presentMediaUploadPicker(let source):
|
case .presentMediaUploadPicker(let source):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPicker(source: source))
|
stateMachine.tryEvent(.presentMediaUploadPicker(source: source, threadRootEventID: nil))
|
||||||
case .presentMediaUploadPreviewScreen(let url):
|
case .presentMediaUploadPreviewScreen(let url):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url))
|
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url, threadRootEventID: nil))
|
||||||
case .presentEmojiPicker(let itemID, let selectedEmojis):
|
case .presentEmojiPicker(let itemID, let selectedEmojis):
|
||||||
stateMachine.tryEvent(.presentEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
|
stateMachine.tryEvent(.presentEmojiPicker(itemID: itemID, selectedEmojis: selectedEmojis))
|
||||||
case .presentLocationPicker:
|
case .presentLocationPicker:
|
||||||
@@ -605,10 +607,12 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
switch action {
|
switch action {
|
||||||
case .presentReportContent(let itemID, let senderID):
|
case .presentReportContent(let itemID, let senderID):
|
||||||
stateMachine.tryEvent(.presentReportContent(itemID: itemID, senderID: senderID))
|
stateMachine.tryEvent(.presentReportContent(itemID: itemID, senderID: senderID))
|
||||||
case .presentMediaUploadPicker(let source):
|
case .presentMediaUploadPicker(let source, let threadRootEventID):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPicker(source: source))
|
stateMachine.tryEvent(.presentMediaUploadPicker(source: source,
|
||||||
case .presentMediaUploadPreviewScreen(let url):
|
threadRootEventID: threadRootEventID))
|
||||||
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url))
|
case .presentMediaUploadPreviewScreen(let url, let threadRootEventID):
|
||||||
|
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url,
|
||||||
|
threadRootEventID: threadRootEventID))
|
||||||
case .presentLocationPicker:
|
case .presentLocationPicker:
|
||||||
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker))
|
stateMachine.tryEvent(.presentMapNavigator(interactionMode: .picker))
|
||||||
case .presentPollForm(let mode):
|
case .presentPollForm(let mode):
|
||||||
@@ -867,7 +871,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentMediaUploadPickerWithSource(_ source: MediaPickerScreenSource) {
|
private func presentMediaUploadPickerWithSource(_ source: MediaPickerScreenSource,
|
||||||
|
threadRootEventID: String?) {
|
||||||
let stackCoordinator = NavigationStackCoordinator()
|
let stackCoordinator = NavigationStackCoordinator()
|
||||||
|
|
||||||
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: userIndicatorController,
|
let mediaPickerCoordinator = MediaPickerScreenCoordinator(userIndicatorController: userIndicatorController,
|
||||||
@@ -880,7 +885,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case .cancel:
|
case .cancel:
|
||||||
navigationStackCoordinator.setSheetCoordinator(nil)
|
navigationStackCoordinator.setSheetCoordinator(nil)
|
||||||
case .selectMediaAtURL(let url):
|
case .selectMediaAtURL(let url):
|
||||||
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url))
|
stateMachine.tryEvent(.presentMediaUploadPreview(fileURL: url, threadRootEventID: threadRootEventID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,7 +898,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentMediaUploadPreviewScreen(for url: URL, animated: Bool) {
|
private func presentMediaUploadPreviewScreen(for url: URL,
|
||||||
|
threadRootEventID: String?,
|
||||||
|
animated: Bool) {
|
||||||
let stackCoordinator = NavigationStackCoordinator()
|
let stackCoordinator = NavigationStackCoordinator()
|
||||||
|
|
||||||
let parameters = MediaUploadPreviewScreenCoordinatorParameters(userIndicatorController: userIndicatorController,
|
let parameters = MediaUploadPreviewScreenCoordinatorParameters(userIndicatorController: userIndicatorController,
|
||||||
@@ -901,6 +908,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: appSettings),
|
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: appSettings),
|
||||||
title: url.lastPathComponent,
|
title: url.lastPathComponent,
|
||||||
url: url,
|
url: url,
|
||||||
|
threadRootEventID: threadRootEventID,
|
||||||
shouldShowCaptionWarning: appSettings.shouldShowMediaCaptionWarning)
|
shouldShowCaptionWarning: appSettings.shouldShowMediaCaptionWarning)
|
||||||
|
|
||||||
let mediaUploadPreviewScreenCoordinator = MediaUploadPreviewScreenCoordinator(parameters: parameters)
|
let mediaUploadPreviewScreenCoordinator = MediaUploadPreviewScreenCoordinator(parameters: parameters)
|
||||||
@@ -966,11 +974,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
switch action {
|
switch action {
|
||||||
case .selectedLocation(let geoURI, let isUserLocation):
|
case .selectedLocation(let geoURI, let isUserLocation):
|
||||||
Task {
|
Task {
|
||||||
|
#warning("Allow sending locations within threads when the SDK allows it")
|
||||||
_ = await self.roomProxy.timeline.sendLocation(body: geoURI.bodyMessage,
|
_ = await self.roomProxy.timeline.sendLocation(body: geoURI.bodyMessage,
|
||||||
geoURI: geoURI,
|
geoURI: geoURI,
|
||||||
description: nil,
|
description: nil,
|
||||||
zoomLevel: 15,
|
zoomLevel: 15,
|
||||||
assetType: isUserLocation ? .sender : .pin)
|
assetType: isUserLocation ? .sender : .pin,
|
||||||
|
threadRootEventID: nil)
|
||||||
self.navigationStackCoordinator.setSheetCoordinator(nil)
|
self.navigationStackCoordinator.setSheetCoordinator(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,7 +1038,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
|
|
||||||
private func createPoll(question: String, options: [String], pollKind: Poll.Kind) {
|
private func createPoll(question: String, options: [String], pollKind: Poll.Kind) {
|
||||||
Task {
|
Task {
|
||||||
let result = await roomProxy.timeline.createPoll(question: question, answers: options, pollKind: pollKind)
|
#warning("Allow sending polls within threads when the SDK allows it")
|
||||||
|
let result = await roomProxy.timeline.createPoll(question: question, answers: options, pollKind: pollKind, threadRootEventID: nil)
|
||||||
|
|
||||||
self.analytics.trackComposer(inThread: false,
|
self.analytics.trackComposer(inThread: false,
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ extension RoomFlowCoordinator {
|
|||||||
case roomMemberDetails(userID: String, previousState: State)
|
case roomMemberDetails(userID: String, previousState: State)
|
||||||
case userProfile(userID: String, previousState: State)
|
case userProfile(userID: String, previousState: State)
|
||||||
case inviteUsersScreen(previousState: State)
|
case inviteUsersScreen(previousState: State)
|
||||||
case mediaUploadPicker(source: MediaPickerScreenSource, previousState: State)
|
case mediaUploadPicker(source: MediaPickerScreenSource, threadRootEventID: String?, previousState: State)
|
||||||
case mediaUploadPreview(fileURL: URL, previousState: State)
|
case mediaUploadPreview(fileURL: URL, threadRootEventID: String?, previousState: State)
|
||||||
case emojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>, previousState: State)
|
case emojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>, previousState: State)
|
||||||
case mapNavigator(previousState: State)
|
case mapNavigator(previousState: State)
|
||||||
case messageForwarding(forwardingItem: MessageForwardingItem, previousState: State)
|
case messageForwarding(forwardingItem: MessageForwardingItem, previousState: State)
|
||||||
@@ -122,10 +122,10 @@ extension RoomFlowCoordinator {
|
|||||||
case presentInviteUsersScreen
|
case presentInviteUsersScreen
|
||||||
case dismissInviteUsersScreen
|
case dismissInviteUsersScreen
|
||||||
|
|
||||||
case presentMediaUploadPicker(source: MediaPickerScreenSource)
|
case presentMediaUploadPicker(source: MediaPickerScreenSource, threadRootEventID: String?)
|
||||||
case dismissMediaUploadPicker
|
case dismissMediaUploadPicker
|
||||||
|
|
||||||
case presentMediaUploadPreview(fileURL: URL)
|
case presentMediaUploadPreview(fileURL: URL, threadRootEventID: String?)
|
||||||
case dismissMediaUploadPreview
|
case dismissMediaUploadPreview
|
||||||
|
|
||||||
case presentEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
|
case presentEmojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>)
|
||||||
@@ -184,11 +184,11 @@ extension RoomFlowCoordinator {
|
|||||||
case (.room, .presentReportContent(let itemID, let senderID)):
|
case (.room, .presentReportContent(let itemID, let senderID)):
|
||||||
return .reportContent(itemID: itemID, senderID: senderID, previousState: fromState)
|
return .reportContent(itemID: itemID, senderID: senderID, previousState: fromState)
|
||||||
|
|
||||||
case (.room, .presentMediaUploadPicker(let source)):
|
case (.room, .presentMediaUploadPicker(let source, let threadRootEventID)):
|
||||||
return .mediaUploadPicker(source: source, previousState: fromState)
|
return .mediaUploadPicker(source: source, threadRootEventID: threadRootEventID, previousState: fromState)
|
||||||
|
|
||||||
case (.room, .presentMediaUploadPreview(let fileURL)):
|
case (.room, .presentMediaUploadPreview(let fileURL, let threadRootEventID)):
|
||||||
return .mediaUploadPreview(fileURL: fileURL, previousState: fromState)
|
return .mediaUploadPreview(fileURL: fileURL, threadRootEventID: threadRootEventID, previousState: fromState)
|
||||||
|
|
||||||
case (.room, .presentEmojiPicker(let itemID, let selectedEmoji)):
|
case (.room, .presentEmojiPicker(let itemID, let selectedEmoji)):
|
||||||
return .emojiPicker(itemID: itemID, selectedEmojis: selectedEmoji, previousState: fromState)
|
return .emojiPicker(itemID: itemID, selectedEmojis: selectedEmoji, previousState: fromState)
|
||||||
@@ -221,11 +221,11 @@ extension RoomFlowCoordinator {
|
|||||||
case (.thread, .presentReportContent(let itemID, let senderID)):
|
case (.thread, .presentReportContent(let itemID, let senderID)):
|
||||||
return .reportContent(itemID: itemID, senderID: senderID, previousState: fromState)
|
return .reportContent(itemID: itemID, senderID: senderID, previousState: fromState)
|
||||||
|
|
||||||
case (.thread, .presentMediaUploadPicker(let source)):
|
case (.thread, .presentMediaUploadPicker(let source, let threadRootEventID)):
|
||||||
return .mediaUploadPicker(source: source, previousState: fromState)
|
return .mediaUploadPicker(source: source, threadRootEventID: threadRootEventID, previousState: fromState)
|
||||||
|
|
||||||
case (.thread, .presentMediaUploadPreview(let fileURL)):
|
case (.thread, .presentMediaUploadPreview(let fileURL, let threadRootEventID)):
|
||||||
return .mediaUploadPreview(fileURL: fileURL, previousState: fromState)
|
return .mediaUploadPreview(fileURL: fileURL, threadRootEventID: threadRootEventID, previousState: fromState)
|
||||||
|
|
||||||
case (.thread, .presentEmojiPicker(let itemID, let selectedEmoji)):
|
case (.thread, .presentEmojiPicker(let itemID, let selectedEmoji)):
|
||||||
return .emojiPicker(itemID: itemID, selectedEmojis: selectedEmoji, previousState: fromState)
|
return .emojiPicker(itemID: itemID, selectedEmojis: selectedEmoji, previousState: fromState)
|
||||||
@@ -244,7 +244,7 @@ extension RoomFlowCoordinator {
|
|||||||
|
|
||||||
// Room + Thread
|
// Room + Thread
|
||||||
|
|
||||||
case (.mediaUploadPicker(_, let previousState), .dismissMediaUploadPicker):
|
case (.mediaUploadPicker(_, _, let previousState), .dismissMediaUploadPicker):
|
||||||
return previousState
|
return previousState
|
||||||
|
|
||||||
case (.emojiPicker(_, _, let previouState), .dismissEmojiPicker):
|
case (.emojiPicker(_, _, let previouState), .dismissEmojiPicker):
|
||||||
@@ -343,7 +343,7 @@ extension RoomFlowCoordinator {
|
|||||||
case (.knockRequestsList(let previousState), .dismissKnockRequestsListScreen):
|
case (.knockRequestsList(let previousState), .dismissKnockRequestsListScreen):
|
||||||
return previousState
|
return previousState
|
||||||
|
|
||||||
case (.mediaUploadPreview(_, let previousState), .dismissMediaUploadPreview):
|
case (.mediaUploadPreview(_, _, let previousState), .dismissMediaUploadPreview):
|
||||||
return previousState
|
return previousState
|
||||||
|
|
||||||
case (.notificationSettings, .presentGlobalNotificationSettingsScreen):
|
case (.notificationSettings, .presentGlobalNotificationSettingsScreen):
|
||||||
@@ -361,8 +361,8 @@ extension RoomFlowCoordinator {
|
|||||||
case (.pollsHistoryForm, .dismissPollForm):
|
case (.pollsHistoryForm, .dismissPollForm):
|
||||||
return .pollsHistory
|
return .pollsHistory
|
||||||
|
|
||||||
case (.mediaUploadPicker(_, let previousMediaUploadPickerState), .presentMediaUploadPreview(let fileURL)):
|
case (.mediaUploadPicker(_, _, let previousMediaUploadPickerState), .presentMediaUploadPreview(let fileURL, let threadRootEventID)):
|
||||||
return .mediaUploadPreview(fileURL: fileURL, previousState: previousMediaUploadPickerState)
|
return .mediaUploadPreview(fileURL: fileURL, threadRootEventID: threadRootEventID, previousState: previousMediaUploadPickerState)
|
||||||
|
|
||||||
case (_, .presentInviteUsersScreen):
|
case (_, .presentInviteUsersScreen):
|
||||||
return .inviteUsersScreen(previousState: fromState)
|
return .inviteUsersScreen(previousState: fromState)
|
||||||
|
|||||||
@@ -16153,15 +16153,15 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
//MARK: - sendAudio
|
//MARK: - sendAudio
|
||||||
|
|
||||||
var sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount = 0
|
var sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = 0
|
||||||
var sendAudioUrlAudioInfoCaptionRequestHandleCallsCount: Int {
|
var sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount
|
return sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount
|
returnValue = sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16169,27 +16169,27 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendAudioUrlAudioInfoCaptionRequestHandleCalled: Bool {
|
var sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleCalled: Bool {
|
||||||
return sendAudioUrlAudioInfoCaptionRequestHandleCallsCount > 0
|
return sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleCallsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendAudioUrlAudioInfoCaptionRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
var sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue
|
return sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue
|
returnValue = sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16197,35 +16197,35 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendAudioUrlAudioInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendAudioUrlAudioInfoCaptionRequestHandleClosure: ((URL, AudioInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
var sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleClosure: ((URL, AudioInfo, String?, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
func sendAudio(url: URL, audioInfo: AudioInfo, caption: String?, threadRootEventID: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
sendAudioUrlAudioInfoCaptionRequestHandleCallsCount += 1
|
sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleCallsCount += 1
|
||||||
if let sendAudioUrlAudioInfoCaptionRequestHandleClosure = sendAudioUrlAudioInfoCaptionRequestHandleClosure {
|
if let sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleClosure = sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleClosure {
|
||||||
return await sendAudioUrlAudioInfoCaptionRequestHandleClosure(url, audioInfo, caption, requestHandle)
|
return await sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleClosure(url, audioInfo, caption, threadRootEventID, requestHandle)
|
||||||
} else {
|
} else {
|
||||||
return sendAudioUrlAudioInfoCaptionRequestHandleReturnValue
|
return sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendFile
|
//MARK: - sendFile
|
||||||
|
|
||||||
var sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount = 0
|
var sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = 0
|
||||||
var sendFileUrlFileInfoCaptionRequestHandleCallsCount: Int {
|
var sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount
|
return sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount
|
returnValue = sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16233,27 +16233,27 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendFileUrlFileInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendFileUrlFileInfoCaptionRequestHandleCalled: Bool {
|
var sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleCalled: Bool {
|
||||||
return sendFileUrlFileInfoCaptionRequestHandleCallsCount > 0
|
return sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleCallsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendFileUrlFileInfoCaptionRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
var sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue
|
return sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue
|
returnValue = sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16261,35 +16261,35 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendFileUrlFileInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendFileUrlFileInfoCaptionRequestHandleClosure: ((URL, FileInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
var sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleClosure: ((URL, FileInfo, String?, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendFile(url: URL, fileInfo: FileInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
func sendFile(url: URL, fileInfo: FileInfo, caption: String?, threadRootEventID: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
sendFileUrlFileInfoCaptionRequestHandleCallsCount += 1
|
sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleCallsCount += 1
|
||||||
if let sendFileUrlFileInfoCaptionRequestHandleClosure = sendFileUrlFileInfoCaptionRequestHandleClosure {
|
if let sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleClosure = sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleClosure {
|
||||||
return await sendFileUrlFileInfoCaptionRequestHandleClosure(url, fileInfo, caption, requestHandle)
|
return await sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleClosure(url, fileInfo, caption, threadRootEventID, requestHandle)
|
||||||
} else {
|
} else {
|
||||||
return sendFileUrlFileInfoCaptionRequestHandleReturnValue
|
return sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendImage
|
//MARK: - sendImage
|
||||||
|
|
||||||
var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount = 0
|
var sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = 0
|
||||||
var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCallsCount: Int {
|
var sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount
|
return sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount
|
returnValue = sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16297,27 +16297,27 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCalled: Bool {
|
var sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleCalled: Bool {
|
||||||
return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCallsCount > 0
|
return sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleCallsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
var sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue
|
return sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue
|
returnValue = sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16325,35 +16325,35 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendImageUrlThumbnailURLImageInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure: ((URL, URL, ImageInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
var sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleClosure: ((URL, URL, ImageInfo, String?, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
func sendImage(url: URL, thumbnailURL: URL, imageInfo: ImageInfo, caption: String?, threadRootEventID: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
sendImageUrlThumbnailURLImageInfoCaptionRequestHandleCallsCount += 1
|
sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleCallsCount += 1
|
||||||
if let sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure = sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure {
|
if let sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleClosure = sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleClosure {
|
||||||
return await sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure(url, thumbnailURL, imageInfo, caption, requestHandle)
|
return await sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleClosure(url, thumbnailURL, imageInfo, caption, threadRootEventID, requestHandle)
|
||||||
} else {
|
} else {
|
||||||
return sendImageUrlThumbnailURLImageInfoCaptionRequestHandleReturnValue
|
return sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendLocation
|
//MARK: - sendLocation
|
||||||
|
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingCallsCount = 0
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingCallsCount = 0
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeCallsCount: Int {
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingCallsCount
|
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingCallsCount
|
returnValue = sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16361,29 +16361,29 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingCallsCount = newValue
|
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingCallsCount = newValue
|
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeCalled: Bool {
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDCalled: Bool {
|
||||||
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeCallsCount > 0
|
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDCallsCount > 0
|
||||||
}
|
}
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeReceivedArguments: (body: String, geoURI: GeoURI, description: String?, zoomLevel: UInt8?, assetType: AssetType?)?
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDReceivedArguments: (body: String, geoURI: GeoURI, description: String?, zoomLevel: UInt8?, assetType: AssetType?, threadRootEventID: String?)?
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeReceivedInvocations: [(body: String, geoURI: GeoURI, description: String?, zoomLevel: UInt8?, assetType: AssetType?)] = []
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDReceivedInvocations: [(body: String, geoURI: GeoURI, description: String?, zoomLevel: UInt8?, assetType: AssetType?, threadRootEventID: String?)] = []
|
||||||
|
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeReturnValue: Result<Void, TimelineProxyError>! {
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingReturnValue
|
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingReturnValue
|
returnValue = sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16391,39 +16391,39 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingReturnValue = newValue
|
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeUnderlyingReturnValue = newValue
|
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure: ((String, GeoURI, String?, UInt8?, AssetType?) async -> Result<Void, TimelineProxyError>)?
|
var sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDClosure: ((String, GeoURI, String?, UInt8?, AssetType?, String?) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendLocation(body: String, geoURI: GeoURI, description: String?, zoomLevel: UInt8?, assetType: AssetType?) async -> Result<Void, TimelineProxyError> {
|
func sendLocation(body: String, geoURI: GeoURI, description: String?, zoomLevel: UInt8?, assetType: AssetType?, threadRootEventID: String?) async -> Result<Void, TimelineProxyError> {
|
||||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeCallsCount += 1
|
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDCallsCount += 1
|
||||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeReceivedArguments = (body: body, geoURI: geoURI, description: description, zoomLevel: zoomLevel, assetType: assetType)
|
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDReceivedArguments = (body: body, geoURI: geoURI, description: description, zoomLevel: zoomLevel, assetType: assetType, threadRootEventID: threadRootEventID)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeReceivedInvocations.append((body: body, geoURI: geoURI, description: description, zoomLevel: zoomLevel, assetType: assetType))
|
self.sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDReceivedInvocations.append((body: body, geoURI: geoURI, description: description, zoomLevel: zoomLevel, assetType: assetType, threadRootEventID: threadRootEventID))
|
||||||
}
|
}
|
||||||
if let sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure = sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure {
|
if let sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDClosure = sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDClosure {
|
||||||
return await sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure(body, geoURI, description, zoomLevel, assetType)
|
return await sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDClosure(body, geoURI, description, zoomLevel, assetType, threadRootEventID)
|
||||||
} else {
|
} else {
|
||||||
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeReturnValue
|
return sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeThreadRootEventIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendVideo
|
//MARK: - sendVideo
|
||||||
|
|
||||||
var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount = 0
|
var sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = 0
|
||||||
var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCallsCount: Int {
|
var sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount
|
return sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount
|
returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16431,27 +16431,27 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingCallsCount = newValue
|
sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCalled: Bool {
|
var sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleCalled: Bool {
|
||||||
return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCallsCount > 0
|
return sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleCallsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
var sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue
|
return sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue
|
returnValue = sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16459,35 +16459,35 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleUnderlyingReturnValue = newValue
|
sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure: ((URL, URL, VideoInfo, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
var sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleClosure: ((URL, URL, VideoInfo, String?, String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
func sendVideo(url: URL, thumbnailURL: URL, videoInfo: VideoInfo, caption: String?, threadRootEventID: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleCallsCount += 1
|
sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleCallsCount += 1
|
||||||
if let sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure {
|
if let sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleClosure = sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleClosure {
|
||||||
return await sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure(url, thumbnailURL, videoInfo, caption, requestHandle)
|
return await sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleClosure(url, thumbnailURL, videoInfo, caption, threadRootEventID, requestHandle)
|
||||||
} else {
|
} else {
|
||||||
return sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleReturnValue
|
return sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendVoiceMessage
|
//MARK: - sendVoiceMessage
|
||||||
|
|
||||||
var sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount = 0
|
var sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingCallsCount = 0
|
||||||
var sendVoiceMessageUrlAudioInfoWaveformRequestHandleCallsCount: Int {
|
var sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount
|
return sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount
|
returnValue = sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16495,27 +16495,27 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount = newValue
|
sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingCallsCount = newValue
|
sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendVoiceMessageUrlAudioInfoWaveformRequestHandleCalled: Bool {
|
var sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleCalled: Bool {
|
||||||
return sendVoiceMessageUrlAudioInfoWaveformRequestHandleCallsCount > 0
|
return sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleCallsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
var sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue
|
return sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue
|
returnValue = sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16523,22 +16523,22 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue = newValue
|
sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendVoiceMessageUrlAudioInfoWaveformRequestHandleUnderlyingReturnValue = newValue
|
sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure: ((URL, AudioInfo, [UInt16], @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
var sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleClosure: ((URL, AudioInfo, [UInt16], String?, @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func sendVoiceMessage(url: URL, audioInfo: AudioInfo, waveform: [UInt16], requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
func sendVoiceMessage(url: URL, audioInfo: AudioInfo, waveform: [UInt16], threadRootEventID: String?, requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
sendVoiceMessageUrlAudioInfoWaveformRequestHandleCallsCount += 1
|
sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleCallsCount += 1
|
||||||
if let sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure = sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure {
|
if let sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleClosure = sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleClosure {
|
||||||
return await sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure(url, audioInfo, waveform, requestHandle)
|
return await sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleClosure(url, audioInfo, waveform, threadRootEventID, requestHandle)
|
||||||
} else {
|
} else {
|
||||||
return sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue
|
return sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - sendReadReceipt
|
//MARK: - sendReadReceipt
|
||||||
@@ -16823,15 +16823,15 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
//MARK: - createPoll
|
//MARK: - createPoll
|
||||||
|
|
||||||
var createPollQuestionAnswersPollKindUnderlyingCallsCount = 0
|
var createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingCallsCount = 0
|
||||||
var createPollQuestionAnswersPollKindCallsCount: Int {
|
var createPollQuestionAnswersPollKindThreadRootEventIDCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return createPollQuestionAnswersPollKindUnderlyingCallsCount
|
return createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = createPollQuestionAnswersPollKindUnderlyingCallsCount
|
returnValue = createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16839,29 +16839,29 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
createPollQuestionAnswersPollKindUnderlyingCallsCount = newValue
|
createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
createPollQuestionAnswersPollKindUnderlyingCallsCount = newValue
|
createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var createPollQuestionAnswersPollKindCalled: Bool {
|
var createPollQuestionAnswersPollKindThreadRootEventIDCalled: Bool {
|
||||||
return createPollQuestionAnswersPollKindCallsCount > 0
|
return createPollQuestionAnswersPollKindThreadRootEventIDCallsCount > 0
|
||||||
}
|
}
|
||||||
var createPollQuestionAnswersPollKindReceivedArguments: (question: String, answers: [String], pollKind: Poll.Kind)?
|
var createPollQuestionAnswersPollKindThreadRootEventIDReceivedArguments: (question: String, answers: [String], pollKind: Poll.Kind, threadRootEventID: String?)?
|
||||||
var createPollQuestionAnswersPollKindReceivedInvocations: [(question: String, answers: [String], pollKind: Poll.Kind)] = []
|
var createPollQuestionAnswersPollKindThreadRootEventIDReceivedInvocations: [(question: String, answers: [String], pollKind: Poll.Kind, threadRootEventID: String?)] = []
|
||||||
|
|
||||||
var createPollQuestionAnswersPollKindUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
var createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingReturnValue: Result<Void, TimelineProxyError>!
|
||||||
var createPollQuestionAnswersPollKindReturnValue: Result<Void, TimelineProxyError>! {
|
var createPollQuestionAnswersPollKindThreadRootEventIDReturnValue: Result<Void, TimelineProxyError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return createPollQuestionAnswersPollKindUnderlyingReturnValue
|
return createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, TimelineProxyError>? = nil
|
var returnValue: Result<Void, TimelineProxyError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = createPollQuestionAnswersPollKindUnderlyingReturnValue
|
returnValue = createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -16869,26 +16869,26 @@ class TimelineProxyMock: TimelineProxyProtocol, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
createPollQuestionAnswersPollKindUnderlyingReturnValue = newValue
|
createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
createPollQuestionAnswersPollKindUnderlyingReturnValue = newValue
|
createPollQuestionAnswersPollKindThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var createPollQuestionAnswersPollKindClosure: ((String, [String], Poll.Kind) async -> Result<Void, TimelineProxyError>)?
|
var createPollQuestionAnswersPollKindThreadRootEventIDClosure: ((String, [String], Poll.Kind, String?) async -> Result<Void, TimelineProxyError>)?
|
||||||
|
|
||||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError> {
|
func createPoll(question: String, answers: [String], pollKind: Poll.Kind, threadRootEventID: String?) async -> Result<Void, TimelineProxyError> {
|
||||||
createPollQuestionAnswersPollKindCallsCount += 1
|
createPollQuestionAnswersPollKindThreadRootEventIDCallsCount += 1
|
||||||
createPollQuestionAnswersPollKindReceivedArguments = (question: question, answers: answers, pollKind: pollKind)
|
createPollQuestionAnswersPollKindThreadRootEventIDReceivedArguments = (question: question, answers: answers, pollKind: pollKind, threadRootEventID: threadRootEventID)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.createPollQuestionAnswersPollKindReceivedInvocations.append((question: question, answers: answers, pollKind: pollKind))
|
self.createPollQuestionAnswersPollKindThreadRootEventIDReceivedInvocations.append((question: question, answers: answers, pollKind: pollKind, threadRootEventID: threadRootEventID))
|
||||||
}
|
}
|
||||||
if let createPollQuestionAnswersPollKindClosure = createPollQuestionAnswersPollKindClosure {
|
if let createPollQuestionAnswersPollKindThreadRootEventIDClosure = createPollQuestionAnswersPollKindThreadRootEventIDClosure {
|
||||||
return await createPollQuestionAnswersPollKindClosure(question, answers, pollKind)
|
return await createPollQuestionAnswersPollKindThreadRootEventIDClosure(question, answers, pollKind, threadRootEventID)
|
||||||
} else {
|
} else {
|
||||||
return createPollQuestionAnswersPollKindReturnValue
|
return createPollQuestionAnswersPollKindThreadRootEventIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//MARK: - editPoll
|
//MARK: - editPoll
|
||||||
@@ -18819,15 +18819,15 @@ class VoiceMessageRecorderMock: VoiceMessageRecorderProtocol, @unchecked Sendabl
|
|||||||
}
|
}
|
||||||
//MARK: - sendVoiceMessage
|
//MARK: - sendVoiceMessage
|
||||||
|
|
||||||
var sendVoiceMessageInRoomAudioConverterUnderlyingCallsCount = 0
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingCallsCount = 0
|
||||||
var sendVoiceMessageInRoomAudioConverterCallsCount: Int {
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDCallsCount: Int {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendVoiceMessageInRoomAudioConverterUnderlyingCallsCount
|
return sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingCallsCount
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Int? = nil
|
var returnValue: Int? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendVoiceMessageInRoomAudioConverterUnderlyingCallsCount
|
returnValue = sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingCallsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -18835,29 +18835,29 @@ class VoiceMessageRecorderMock: VoiceMessageRecorderProtocol, @unchecked Sendabl
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendVoiceMessageInRoomAudioConverterUnderlyingCallsCount = newValue
|
sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendVoiceMessageInRoomAudioConverterUnderlyingCallsCount = newValue
|
sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingCallsCount = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendVoiceMessageInRoomAudioConverterCalled: Bool {
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDCalled: Bool {
|
||||||
return sendVoiceMessageInRoomAudioConverterCallsCount > 0
|
return sendVoiceMessageInRoomAudioConverterThreadRootEventIDCallsCount > 0
|
||||||
}
|
}
|
||||||
var sendVoiceMessageInRoomAudioConverterReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol)?
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDReceivedArguments: (roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol, threadRootEventID: String?)?
|
||||||
var sendVoiceMessageInRoomAudioConverterReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol)] = []
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDReceivedInvocations: [(roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol, threadRootEventID: String?)] = []
|
||||||
|
|
||||||
var sendVoiceMessageInRoomAudioConverterUnderlyingReturnValue: Result<Void, VoiceMessageRecorderError>!
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingReturnValue: Result<Void, VoiceMessageRecorderError>!
|
||||||
var sendVoiceMessageInRoomAudioConverterReturnValue: Result<Void, VoiceMessageRecorderError>! {
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDReturnValue: Result<Void, VoiceMessageRecorderError>! {
|
||||||
get {
|
get {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
return sendVoiceMessageInRoomAudioConverterUnderlyingReturnValue
|
return sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingReturnValue
|
||||||
} else {
|
} else {
|
||||||
var returnValue: Result<Void, VoiceMessageRecorderError>? = nil
|
var returnValue: Result<Void, VoiceMessageRecorderError>? = nil
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
returnValue = sendVoiceMessageInRoomAudioConverterUnderlyingReturnValue
|
returnValue = sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue!
|
return returnValue!
|
||||||
@@ -18865,26 +18865,26 @@ class VoiceMessageRecorderMock: VoiceMessageRecorderProtocol, @unchecked Sendabl
|
|||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
if Thread.isMainThread {
|
if Thread.isMainThread {
|
||||||
sendVoiceMessageInRoomAudioConverterUnderlyingReturnValue = newValue
|
sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
} else {
|
} else {
|
||||||
DispatchQueue.main.sync {
|
DispatchQueue.main.sync {
|
||||||
sendVoiceMessageInRoomAudioConverterUnderlyingReturnValue = newValue
|
sendVoiceMessageInRoomAudioConverterThreadRootEventIDUnderlyingReturnValue = newValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sendVoiceMessageInRoomAudioConverterClosure: ((JoinedRoomProxyProtocol, AudioConverterProtocol) async -> Result<Void, VoiceMessageRecorderError>)?
|
var sendVoiceMessageInRoomAudioConverterThreadRootEventIDClosure: ((JoinedRoomProxyProtocol, AudioConverterProtocol, String?) async -> Result<Void, VoiceMessageRecorderError>)?
|
||||||
|
|
||||||
func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result<Void, VoiceMessageRecorderError> {
|
func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol, threadRootEventID: String?) async -> Result<Void, VoiceMessageRecorderError> {
|
||||||
sendVoiceMessageInRoomAudioConverterCallsCount += 1
|
sendVoiceMessageInRoomAudioConverterThreadRootEventIDCallsCount += 1
|
||||||
sendVoiceMessageInRoomAudioConverterReceivedArguments = (roomProxy: roomProxy, audioConverter: audioConverter)
|
sendVoiceMessageInRoomAudioConverterThreadRootEventIDReceivedArguments = (roomProxy: roomProxy, audioConverter: audioConverter, threadRootEventID: threadRootEventID)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.sendVoiceMessageInRoomAudioConverterReceivedInvocations.append((roomProxy: roomProxy, audioConverter: audioConverter))
|
self.sendVoiceMessageInRoomAudioConverterThreadRootEventIDReceivedInvocations.append((roomProxy: roomProxy, audioConverter: audioConverter, threadRootEventID: threadRootEventID))
|
||||||
}
|
}
|
||||||
if let sendVoiceMessageInRoomAudioConverterClosure = sendVoiceMessageInRoomAudioConverterClosure {
|
if let sendVoiceMessageInRoomAudioConverterThreadRootEventIDClosure = sendVoiceMessageInRoomAudioConverterThreadRootEventIDClosure {
|
||||||
return await sendVoiceMessageInRoomAudioConverterClosure(roomProxy, audioConverter)
|
return await sendVoiceMessageInRoomAudioConverterThreadRootEventIDClosure(roomProxy, audioConverter, threadRootEventID)
|
||||||
} else {
|
} else {
|
||||||
return sendVoiceMessageInRoomAudioConverterReturnValue
|
return sendVoiceMessageInRoomAudioConverterThreadRootEventIDReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -14,6 +14,7 @@ struct MediaUploadPreviewScreenCoordinatorParameters {
|
|||||||
let mediaUploadingPreprocessor: MediaUploadingPreprocessor
|
let mediaUploadingPreprocessor: MediaUploadingPreprocessor
|
||||||
let title: String?
|
let title: String?
|
||||||
let url: URL
|
let url: URL
|
||||||
|
let threadRootEventID: String?
|
||||||
let shouldShowCaptionWarning: Bool
|
let shouldShowCaptionWarning: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ final class MediaUploadPreviewScreenCoordinator: CoordinatorProtocol {
|
|||||||
mediaUploadingPreprocessor: parameters.mediaUploadingPreprocessor,
|
mediaUploadingPreprocessor: parameters.mediaUploadingPreprocessor,
|
||||||
title: parameters.title,
|
title: parameters.title,
|
||||||
url: parameters.url,
|
url: parameters.url,
|
||||||
|
threadRootEventID: parameters.threadRootEventID,
|
||||||
shouldShowCaptionWarning: parameters.shouldShowCaptionWarning)
|
shouldShowCaptionWarning: parameters.shouldShowCaptionWarning)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -16,6 +16,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
|
|||||||
private let roomProxy: JoinedRoomProxyProtocol
|
private let roomProxy: JoinedRoomProxyProtocol
|
||||||
private let mediaUploadingPreprocessor: MediaUploadingPreprocessor
|
private let mediaUploadingPreprocessor: MediaUploadingPreprocessor
|
||||||
private let url: URL
|
private let url: URL
|
||||||
|
private let threadRootEventID: String?
|
||||||
|
|
||||||
private var processingTask: Task<Result<MediaInfo, MediaUploadingPreprocessorError>, Never>
|
private var processingTask: Task<Result<MediaInfo, MediaUploadingPreprocessorError>, Never>
|
||||||
private var requestHandle: SendAttachmentJoinHandleProtocol?
|
private var requestHandle: SendAttachmentJoinHandleProtocol?
|
||||||
@@ -31,11 +32,13 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
|
|||||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor,
|
mediaUploadingPreprocessor: MediaUploadingPreprocessor,
|
||||||
title: String?,
|
title: String?,
|
||||||
url: URL,
|
url: URL,
|
||||||
|
threadRootEventID: String?,
|
||||||
shouldShowCaptionWarning: Bool) {
|
shouldShowCaptionWarning: Bool) {
|
||||||
self.userIndicatorController = userIndicatorController
|
self.userIndicatorController = userIndicatorController
|
||||||
self.roomProxy = roomProxy
|
self.roomProxy = roomProxy
|
||||||
self.mediaUploadingPreprocessor = mediaUploadingPreprocessor
|
self.mediaUploadingPreprocessor = mediaUploadingPreprocessor
|
||||||
self.url = url
|
self.url = url
|
||||||
|
self.threadRootEventID = threadRootEventID
|
||||||
|
|
||||||
// Start processing the media whilst the user is reviewing it/adding a caption.
|
// Start processing the media whilst the user is reviewing it/adding a caption.
|
||||||
processingTask = Task { await mediaUploadingPreprocessor.processMedia(at: url) }
|
processingTask = Task { await mediaUploadingPreprocessor.processMedia(at: url) }
|
||||||
@@ -57,7 +60,9 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
|
|||||||
Task {
|
Task {
|
||||||
switch await processingTask.value {
|
switch await processingTask.value {
|
||||||
case .success(let mediaInfo):
|
case .success(let mediaInfo):
|
||||||
switch await sendAttachment(mediaInfo: mediaInfo, caption: caption) {
|
switch await sendAttachment(mediaInfo: mediaInfo,
|
||||||
|
caption: caption,
|
||||||
|
threadRootEventID: threadRootEventID) {
|
||||||
case .success:
|
case .success:
|
||||||
actionsSubject.send(.dismiss)
|
actionsSubject.send(.dismiss)
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
@@ -85,7 +90,7 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
|
|||||||
|
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func sendAttachment(mediaInfo: MediaInfo, caption: String?) async -> Result<Void, TimelineProxyError> {
|
private func sendAttachment(mediaInfo: MediaInfo, caption: String?, threadRootEventID: String?) async -> Result<Void, TimelineProxyError> {
|
||||||
let requestHandle: ((SendAttachmentJoinHandleProtocol) -> Void) = { [weak self] handle in
|
let requestHandle: ((SendAttachmentJoinHandleProtocol) -> Void) = { [weak self] handle in
|
||||||
self?.requestHandle = handle
|
self?.requestHandle = handle
|
||||||
}
|
}
|
||||||
@@ -96,22 +101,26 @@ class MediaUploadPreviewScreenViewModel: MediaUploadPreviewScreenViewModelType,
|
|||||||
thumbnailURL: thumbnailURL,
|
thumbnailURL: thumbnailURL,
|
||||||
imageInfo: imageInfo,
|
imageInfo: imageInfo,
|
||||||
caption: caption,
|
caption: caption,
|
||||||
|
threadRootEventID: threadRootEventID,
|
||||||
requestHandle: requestHandle)
|
requestHandle: requestHandle)
|
||||||
case let .video(videoURL, thumbnailURL, videoInfo):
|
case let .video(videoURL, thumbnailURL, videoInfo):
|
||||||
return await roomProxy.timeline.sendVideo(url: videoURL,
|
return await roomProxy.timeline.sendVideo(url: videoURL,
|
||||||
thumbnailURL: thumbnailURL,
|
thumbnailURL: thumbnailURL,
|
||||||
videoInfo: videoInfo,
|
videoInfo: videoInfo,
|
||||||
caption: caption,
|
caption: caption,
|
||||||
|
threadRootEventID: threadRootEventID,
|
||||||
requestHandle: requestHandle)
|
requestHandle: requestHandle)
|
||||||
case let .audio(audioURL, audioInfo):
|
case let .audio(audioURL, audioInfo):
|
||||||
return await roomProxy.timeline.sendAudio(url: audioURL,
|
return await roomProxy.timeline.sendAudio(url: audioURL,
|
||||||
audioInfo: audioInfo,
|
audioInfo: audioInfo,
|
||||||
caption: caption,
|
caption: caption,
|
||||||
|
threadRootEventID: threadRootEventID,
|
||||||
requestHandle: requestHandle)
|
requestHandle: requestHandle)
|
||||||
case let .file(fileURL, fileInfo):
|
case let .file(fileURL, fileInfo):
|
||||||
return await roomProxy.timeline.sendFile(url: fileURL,
|
return await roomProxy.timeline.sendFile(url: fileURL,
|
||||||
fileInfo: fileInfo,
|
fileInfo: fileInfo,
|
||||||
caption: caption,
|
caption: caption,
|
||||||
|
threadRootEventID: threadRootEventID,
|
||||||
requestHandle: requestHandle)
|
requestHandle: requestHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview {
|
|||||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings),
|
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings),
|
||||||
title: "App Icon.png",
|
title: "App Icon.png",
|
||||||
url: snapshotURL,
|
url: snapshotURL,
|
||||||
|
threadRootEventID: nil,
|
||||||
shouldShowCaptionWarning: true)
|
shouldShowCaptionWarning: true)
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ struct ComposerToolbarViewState: BindableState {
|
|||||||
|
|
||||||
var keyCommands: [WysiwygKeyCommand] = []
|
var keyCommands: [WysiwygKeyCommand] = []
|
||||||
|
|
||||||
|
var isInThread: Bool
|
||||||
|
|
||||||
var bindings: ComposerToolbarViewStateBindings
|
var bindings: ComposerToolbarViewStateBindings
|
||||||
|
|
||||||
var isUploading: Bool {
|
var isUploading: Bool {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
|||||||
|
|
||||||
init(initialText: String? = nil,
|
init(initialText: String? = nil,
|
||||||
roomProxy: JoinedRoomProxyProtocol,
|
roomProxy: JoinedRoomProxyProtocol,
|
||||||
|
isInThread: Bool = false,
|
||||||
wysiwygViewModel: WysiwygComposerViewModel,
|
wysiwygViewModel: WysiwygComposerViewModel,
|
||||||
completionSuggestionService: CompletionSuggestionServiceProtocol,
|
completionSuggestionService: CompletionSuggestionServiceProtocol,
|
||||||
mediaProvider: MediaProviderProtocol,
|
mediaProvider: MediaProviderProtocol,
|
||||||
@@ -68,6 +69,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
|||||||
audioRecorderState: .init(),
|
audioRecorderState: .init(),
|
||||||
isRoomEncrypted: roomProxy.infoPublisher.value.isEncrypted,
|
isRoomEncrypted: roomProxy.infoPublisher.value.isEncrypted,
|
||||||
isLocationSharingEnabled: appSettings.mapTilerConfiguration.isEnabled,
|
isLocationSharingEnabled: appSettings.mapTilerConfiguration.isEnabled,
|
||||||
|
isInThread: isInThread,
|
||||||
bindings: .init()),
|
bindings: .init()),
|
||||||
mediaProvider: mediaProvider)
|
mediaProvider: mediaProvider)
|
||||||
|
|
||||||
|
|||||||
@@ -40,14 +40,16 @@ struct RoomAttachmentPicker: View {
|
|||||||
}
|
}
|
||||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerTextFormatting)
|
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerTextFormatting)
|
||||||
|
|
||||||
Button {
|
if !context.viewState.isInThread {
|
||||||
context.send(viewAction: .attach(.poll))
|
Button {
|
||||||
} label: {
|
context.send(viewAction: .attach(.poll))
|
||||||
Label(L10n.screenRoomAttachmentSourcePoll, icon: \.polls)
|
} label: {
|
||||||
|
Label(L10n.screenRoomAttachmentSourcePoll, icon: \.polls)
|
||||||
|
}
|
||||||
|
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerPoll)
|
||||||
}
|
}
|
||||||
.accessibilityIdentifier(A11yIdentifiers.roomScreen.attachmentPickerPoll)
|
|
||||||
|
|
||||||
if context.viewState.isLocationSharingEnabled {
|
if !context.viewState.isInThread, context.viewState.isLocationSharingEnabled {
|
||||||
Button {
|
Button {
|
||||||
context.send(viewAction: .attach(.location))
|
context.send(viewAction: .attach(.location))
|
||||||
} label: {
|
} label: {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
|||||||
parserStyle: .elementX)
|
parserStyle: .elementX)
|
||||||
let composerViewModel = ComposerToolbarViewModel(initialText: parameters.sharedText,
|
let composerViewModel = ComposerToolbarViewModel(initialText: parameters.sharedText,
|
||||||
roomProxy: parameters.roomProxy,
|
roomProxy: parameters.roomProxy,
|
||||||
|
isInThread: false,
|
||||||
wysiwygViewModel: wysiwygViewModel,
|
wysiwygViewModel: wysiwygViewModel,
|
||||||
completionSuggestionService: parameters.completionSuggestionService,
|
completionSuggestionService: parameters.completionSuggestionService,
|
||||||
mediaProvider: parameters.mediaProvider,
|
mediaProvider: parameters.mediaProvider,
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ struct ThreadTimelineScreenCoordinatorParameters {
|
|||||||
|
|
||||||
enum ThreadTimelineScreenCoordinatorAction {
|
enum ThreadTimelineScreenCoordinatorAction {
|
||||||
case presentReportContent(itemID: TimelineItemIdentifier, senderID: String)
|
case presentReportContent(itemID: TimelineItemIdentifier, senderID: String)
|
||||||
case presentMediaUploadPicker(MediaPickerScreenSource)
|
case presentMediaUploadPicker(MediaPickerScreenSource, threadRootEventID: String?)
|
||||||
case presentMediaUploadPreviewScreen(URL)
|
case presentMediaUploadPreviewScreen(url: URL, threadRootEventID: String?)
|
||||||
case presentLocationPicker
|
case presentLocationPicker
|
||||||
case presentPollForm(mode: PollFormMode)
|
case presentPollForm(mode: PollFormMode)
|
||||||
case presentLocationViewer(body: String, geoURI: GeoURI, description: String?)
|
case presentLocationViewer(body: String, geoURI: GeoURI, description: String?)
|
||||||
@@ -78,6 +78,7 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol {
|
|||||||
|
|
||||||
composerViewModel = ComposerToolbarViewModel(initialText: nil,
|
composerViewModel = ComposerToolbarViewModel(initialText: nil,
|
||||||
roomProxy: parameters.roomProxy,
|
roomProxy: parameters.roomProxy,
|
||||||
|
isInThread: true,
|
||||||
wysiwygViewModel: wysiwygViewModel,
|
wysiwygViewModel: wysiwygViewModel,
|
||||||
completionSuggestionService: parameters.completionSuggestionService,
|
completionSuggestionService: parameters.completionSuggestionService,
|
||||||
mediaProvider: parameters.mediaProvider,
|
mediaProvider: parameters.mediaProvider,
|
||||||
@@ -98,11 +99,11 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol {
|
|||||||
case .displayReportContent(let itemID, let senderID):
|
case .displayReportContent(let itemID, let senderID):
|
||||||
actionsSubject.send(.presentReportContent(itemID: itemID, senderID: senderID))
|
actionsSubject.send(.presentReportContent(itemID: itemID, senderID: senderID))
|
||||||
case .displayCameraPicker:
|
case .displayCameraPicker:
|
||||||
actionsSubject.send(.presentMediaUploadPicker(.camera))
|
actionsSubject.send(.presentMediaUploadPicker(.camera, threadRootEventID: parameters.timelineController.timelineKind.threadRootEventID))
|
||||||
case .displayMediaPicker:
|
case .displayMediaPicker:
|
||||||
actionsSubject.send(.presentMediaUploadPicker(.photoLibrary))
|
actionsSubject.send(.presentMediaUploadPicker(.photoLibrary, threadRootEventID: parameters.timelineController.timelineKind.threadRootEventID))
|
||||||
case .displayDocumentPicker:
|
case .displayDocumentPicker:
|
||||||
actionsSubject.send(.presentMediaUploadPicker(.documents))
|
actionsSubject.send(.presentMediaUploadPicker(.documents, threadRootEventID: parameters.timelineController.timelineKind.threadRootEventID))
|
||||||
case .displayMediaPreview(let mediaPreviewViewModel):
|
case .displayMediaPreview(let mediaPreviewViewModel):
|
||||||
viewModel.displayMediaPreview(mediaPreviewViewModel)
|
viewModel.displayMediaPreview(mediaPreviewViewModel)
|
||||||
case .displayLocationPicker:
|
case .displayLocationPicker:
|
||||||
@@ -110,7 +111,7 @@ final class ThreadTimelineScreenCoordinator: CoordinatorProtocol {
|
|||||||
case .displayPollForm(let mode):
|
case .displayPollForm(let mode):
|
||||||
actionsSubject.send(.presentPollForm(mode: mode))
|
actionsSubject.send(.presentPollForm(mode: mode))
|
||||||
case .displayMediaUploadPreviewScreen(let url):
|
case .displayMediaUploadPreviewScreen(let url):
|
||||||
actionsSubject.send(.presentMediaUploadPreviewScreen(url))
|
actionsSubject.send(.presentMediaUploadPreviewScreen(url: url, threadRootEventID: parameters.timelineController.timelineKind.threadRootEventID))
|
||||||
case .displaySenderDetails(userID: let userID):
|
case .displaySenderDetails(userID: let userID):
|
||||||
actionsSubject.send(.presentRoomMemberDetails(userID: userID))
|
actionsSubject.send(.presentRoomMemberDetails(userID: userID))
|
||||||
case .displayMessageForwarding(let forwardingItem):
|
case .displayMessageForwarding(let forwardingItem):
|
||||||
|
|||||||
@@ -362,7 +362,9 @@ class TimelineInteractionHandler {
|
|||||||
|
|
||||||
actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: true))))
|
actionsSubject.send(.composer(action: .setMode(mode: .previewVoiceMessage(state: audioPlayerState, waveform: .url(recordingURL), isUploading: true))))
|
||||||
await voiceMessageRecorder.stopPlayback()
|
await voiceMessageRecorder.stopPlayback()
|
||||||
switch await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: AudioConverter()) {
|
switch await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy,
|
||||||
|
audioConverter: AudioConverter(),
|
||||||
|
threadRootEventID: timelineController.timelineKind.threadRootEventID) {
|
||||||
case .success:
|
case .success:
|
||||||
await deleteCurrentVoiceMessage()
|
await deleteCurrentVoiceMessage()
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
|||||||
@@ -229,15 +229,22 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
func sendAudio(url: URL,
|
func sendAudio(url: URL,
|
||||||
audioInfo: AudioInfo,
|
audioInfo: AudioInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending audio")
|
MXLog.info("Sending audio")
|
||||||
|
|
||||||
|
let replyParameters: ReplyParameters? = if let threadRootEventID {
|
||||||
|
ReplyParameters(eventId: threadRootEventID, enforceThread: true, replyWithinThread: false)
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let handle = try timeline.sendAudio(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
let handle = try timeline.sendAudio(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
||||||
caption: caption,
|
caption: caption,
|
||||||
formattedCaption: nil, // Rust will build this from the caption's markdown.
|
formattedCaption: nil, // Rust will build this from the caption's markdown.
|
||||||
mentions: nil,
|
mentions: nil,
|
||||||
replyParams: nil,
|
replyParams: replyParameters,
|
||||||
useSendQueue: true),
|
useSendQueue: true),
|
||||||
audioInfo: audioInfo,
|
audioInfo: audioInfo,
|
||||||
progressWatcher: nil)
|
progressWatcher: nil)
|
||||||
@@ -257,15 +264,22 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
func sendFile(url: URL,
|
func sendFile(url: URL,
|
||||||
fileInfo: FileInfo,
|
fileInfo: FileInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending file")
|
MXLog.info("Sending file")
|
||||||
|
|
||||||
|
let replyParameters: ReplyParameters? = if let threadRootEventID {
|
||||||
|
ReplyParameters(eventId: threadRootEventID, enforceThread: true, replyWithinThread: false)
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let handle = try timeline.sendFile(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
let handle = try timeline.sendFile(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
||||||
caption: caption,
|
caption: caption,
|
||||||
formattedCaption: nil, // Rust will build this from the caption's markdown.
|
formattedCaption: nil, // Rust will build this from the caption's markdown.
|
||||||
mentions: nil,
|
mentions: nil,
|
||||||
replyParams: nil,
|
replyParams: replyParameters,
|
||||||
useSendQueue: true),
|
useSendQueue: true),
|
||||||
fileInfo: fileInfo,
|
fileInfo: fileInfo,
|
||||||
progressWatcher: nil)
|
progressWatcher: nil)
|
||||||
@@ -286,15 +300,22 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
thumbnailURL: URL,
|
thumbnailURL: URL,
|
||||||
imageInfo: ImageInfo,
|
imageInfo: ImageInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending image")
|
MXLog.info("Sending image")
|
||||||
|
|
||||||
|
let replyParameters: ReplyParameters? = if let threadRootEventID {
|
||||||
|
ReplyParameters(eventId: threadRootEventID, enforceThread: true, replyWithinThread: false)
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let handle = try timeline.sendImage(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
let handle = try timeline.sendImage(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
||||||
caption: caption,
|
caption: caption,
|
||||||
formattedCaption: nil, // Rust will build this from the caption's markdown.
|
formattedCaption: nil, // Rust will build this from the caption's markdown.
|
||||||
mentions: nil,
|
mentions: nil,
|
||||||
replyParams: nil,
|
replyParams: replyParameters,
|
||||||
useSendQueue: true),
|
useSendQueue: true),
|
||||||
thumbnailPath: thumbnailURL.path(percentEncoded: false),
|
thumbnailPath: thumbnailURL.path(percentEncoded: false),
|
||||||
imageInfo: imageInfo,
|
imageInfo: imageInfo,
|
||||||
@@ -316,7 +337,8 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
geoURI: GeoURI,
|
geoURI: GeoURI,
|
||||||
description: String?,
|
description: String?,
|
||||||
zoomLevel: UInt8?,
|
zoomLevel: UInt8?,
|
||||||
assetType: AssetType?) async -> Result<Void, TimelineProxyError> {
|
assetType: AssetType?,
|
||||||
|
threadRootEventID: String?) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending location")
|
MXLog.info("Sending location")
|
||||||
|
|
||||||
await timeline.sendLocation(body: body,
|
await timeline.sendLocation(body: body,
|
||||||
@@ -334,15 +356,22 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
thumbnailURL: URL,
|
thumbnailURL: URL,
|
||||||
videoInfo: VideoInfo,
|
videoInfo: VideoInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending video")
|
MXLog.info("Sending video")
|
||||||
|
|
||||||
|
let replyParameters: ReplyParameters? = if let threadRootEventID {
|
||||||
|
ReplyParameters(eventId: threadRootEventID, enforceThread: true, replyWithinThread: false)
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let handle = try timeline.sendVideo(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
let handle = try timeline.sendVideo(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
||||||
caption: caption,
|
caption: caption,
|
||||||
formattedCaption: nil,
|
formattedCaption: nil,
|
||||||
mentions: nil,
|
mentions: nil,
|
||||||
replyParams: nil,
|
replyParams: replyParameters,
|
||||||
useSendQueue: true),
|
useSendQueue: true),
|
||||||
thumbnailPath: thumbnailURL.path(percentEncoded: false),
|
thumbnailPath: thumbnailURL.path(percentEncoded: false),
|
||||||
videoInfo: videoInfo,
|
videoInfo: videoInfo,
|
||||||
@@ -363,15 +392,22 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
func sendVoiceMessage(url: URL,
|
func sendVoiceMessage(url: URL,
|
||||||
audioInfo: AudioInfo,
|
audioInfo: AudioInfo,
|
||||||
waveform: [UInt16],
|
waveform: [UInt16],
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Sending voice message")
|
MXLog.info("Sending voice message")
|
||||||
|
|
||||||
|
let replyParameters: ReplyParameters? = if let threadRootEventID {
|
||||||
|
ReplyParameters(eventId: threadRootEventID, enforceThread: true, replyWithinThread: false)
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let handle = try timeline.sendVoiceMessage(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
let handle = try timeline.sendVoiceMessage(params: .init(source: .file(filename: url.path(percentEncoded: false)),
|
||||||
caption: nil,
|
caption: nil,
|
||||||
formattedCaption: nil,
|
formattedCaption: nil,
|
||||||
mentions: nil,
|
mentions: nil,
|
||||||
replyParams: nil,
|
replyParams: replyParameters,
|
||||||
useSendQueue: true),
|
useSendQueue: true),
|
||||||
audioInfo: audioInfo,
|
audioInfo: audioInfo,
|
||||||
waveform: waveform,
|
waveform: waveform,
|
||||||
@@ -481,7 +517,9 @@ final class TimelineProxy: TimelineProxyProtocol {
|
|||||||
|
|
||||||
// MARK: - Polls
|
// MARK: - Polls
|
||||||
|
|
||||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError> {
|
func createPoll(question: String, answers: [String],
|
||||||
|
pollKind: Poll.Kind,
|
||||||
|
threadRootEventID: String? = nil) async -> Result<Void, TimelineProxyError> {
|
||||||
MXLog.info("Creating poll")
|
MXLog.info("Creating poll")
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|||||||
@@ -82,34 +82,40 @@ protocol TimelineProxyProtocol {
|
|||||||
func sendAudio(url: URL,
|
func sendAudio(url: URL,
|
||||||
audioInfo: AudioInfo,
|
audioInfo: AudioInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendFile(url: URL,
|
func sendFile(url: URL,
|
||||||
fileInfo: FileInfo,
|
fileInfo: FileInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendImage(url: URL,
|
func sendImage(url: URL,
|
||||||
thumbnailURL: URL,
|
thumbnailURL: URL,
|
||||||
imageInfo: ImageInfo,
|
imageInfo: ImageInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendLocation(body: String,
|
func sendLocation(body: String,
|
||||||
geoURI: GeoURI,
|
geoURI: GeoURI,
|
||||||
description: String?,
|
description: String?,
|
||||||
zoomLevel: UInt8?,
|
zoomLevel: UInt8?,
|
||||||
assetType: AssetType?) async -> Result<Void, TimelineProxyError>
|
assetType: AssetType?,
|
||||||
|
threadRootEventID: String?) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendVideo(url: URL,
|
func sendVideo(url: URL,
|
||||||
thumbnailURL: URL,
|
thumbnailURL: URL,
|
||||||
videoInfo: VideoInfo,
|
videoInfo: VideoInfo,
|
||||||
caption: String?,
|
caption: String?,
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendVoiceMessage(url: URL,
|
func sendVoiceMessage(url: URL,
|
||||||
audioInfo: AudioInfo,
|
audioInfo: AudioInfo,
|
||||||
waveform: [UInt16],
|
waveform: [UInt16],
|
||||||
|
threadRootEventID: String?,
|
||||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func sendReadReceipt(for eventID: String, type: ReceiptType) async -> Result<Void, TimelineProxyError>
|
func sendReadReceipt(for eventID: String, type: ReceiptType) async -> Result<Void, TimelineProxyError>
|
||||||
@@ -124,7 +130,7 @@ protocol TimelineProxyProtocol {
|
|||||||
|
|
||||||
func toggleReaction(_ reaction: String, to eventID: TimelineItemIdentifier.EventOrTransactionID) async -> Result<Void, TimelineProxyError>
|
func toggleReaction(_ reaction: String, to eventID: TimelineItemIdentifier.EventOrTransactionID) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineProxyError>
|
func createPoll(question: String, answers: [String], pollKind: Poll.Kind, threadRootEventID: String?) async -> Result<Void, TimelineProxyError>
|
||||||
|
|
||||||
func editPoll(original eventID: String,
|
func editPoll(original eventID: String,
|
||||||
question: String,
|
question: String,
|
||||||
|
|||||||
@@ -144,7 +144,9 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol {
|
|||||||
return .success(waveformData)
|
return .success(waveformData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result<Void, VoiceMessageRecorderError> {
|
func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol,
|
||||||
|
audioConverter: AudioConverterProtocol,
|
||||||
|
threadRootEventID: String?) async -> Result<Void, VoiceMessageRecorderError> {
|
||||||
guard let url = audioRecorder.audioFileURL else {
|
guard let url = audioRecorder.audioFileURL else {
|
||||||
return .failure(VoiceMessageRecorderError.missingRecordingFile)
|
return .failure(VoiceMessageRecorderError.missingRecordingFile)
|
||||||
}
|
}
|
||||||
@@ -178,7 +180,8 @@ class VoiceMessageRecorder: VoiceMessageRecorderProtocol {
|
|||||||
|
|
||||||
let result = await roomProxy.timeline.sendVoiceMessage(url: oggFile,
|
let result = await roomProxy.timeline.sendVoiceMessage(url: oggFile,
|
||||||
audioInfo: audioInfo,
|
audioInfo: audioInfo,
|
||||||
waveform: waveform) { _ in }
|
waveform: waveform,
|
||||||
|
threadRootEventID: threadRootEventID) { _ in }
|
||||||
|
|
||||||
if case .failure(let error) = result {
|
if case .failure(let error) = result {
|
||||||
MXLog.error("Failed to send the voice message. \(error)")
|
MXLog.error("Failed to send the voice message. \(error)")
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ protocol VoiceMessageRecorderProtocol {
|
|||||||
func seekPlayback(to progress: Double) async
|
func seekPlayback(to progress: Double) async
|
||||||
func deleteRecording() async
|
func deleteRecording() async
|
||||||
|
|
||||||
func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol, audioConverter: AudioConverterProtocol) async -> Result<Void, VoiceMessageRecorderError>
|
func sendVoiceMessage(inRoom roomProxy: JoinedRoomProxyProtocol,
|
||||||
|
audioConverter: AudioConverterProtocol,
|
||||||
|
threadRootEventID: String?) async -> Result<Void, VoiceMessageRecorderError>
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourcery: AutoMockable
|
// sourcery: AutoMockable
|
||||||
|
|||||||
@@ -106,16 +106,16 @@ class MediaUploadPreviewScreenViewModelTests: XCTestCase {
|
|||||||
|
|
||||||
private func setUpViewModel(url: URL, expectedCaption: String?) {
|
private func setUpViewModel(url: URL, expectedCaption: String?) {
|
||||||
timelineProxy = TimelineProxyMock(.init())
|
timelineProxy = TimelineProxyMock(.init())
|
||||||
timelineProxy.sendAudioUrlAudioInfoCaptionRequestHandleClosure = { [weak self] _, _, caption, _ in
|
timelineProxy.sendAudioUrlAudioInfoCaptionThreadRootEventIDRequestHandleClosure = { [weak self] _, _, caption, _, _ in
|
||||||
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
||||||
}
|
}
|
||||||
timelineProxy.sendFileUrlFileInfoCaptionRequestHandleClosure = { [weak self] _, _, caption, _ in
|
timelineProxy.sendFileUrlFileInfoCaptionThreadRootEventIDRequestHandleClosure = { [weak self] _, _, caption, _, _ in
|
||||||
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
||||||
}
|
}
|
||||||
timelineProxy.sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure = { [weak self] _, _, _, caption, _ in
|
timelineProxy.sendImageUrlThumbnailURLImageInfoCaptionThreadRootEventIDRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in
|
||||||
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
||||||
}
|
}
|
||||||
timelineProxy.sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure = { [weak self] _, _, _, caption, _ in
|
timelineProxy.sendVideoUrlThumbnailURLVideoInfoCaptionThreadRootEventIDRequestHandleClosure = { [weak self] _, _, _, caption, _, _ in
|
||||||
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
self?.verifyCaption(caption, expectedCaption: expectedCaption) ?? .failure(.sdkError(TestError.unknown))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +126,7 @@ class MediaUploadPreviewScreenViewModelTests: XCTestCase {
|
|||||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings),
|
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: ServiceLocator.shared.settings),
|
||||||
title: "Some File",
|
title: "Some File",
|
||||||
url: url,
|
url: url,
|
||||||
|
threadRootEventID: nil,
|
||||||
shouldShowCaptionWarning: true)
|
shouldShowCaptionWarning: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,7 +196,9 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
|
|
||||||
// If there is no recording file, an error is expected
|
// If there is no recording file, an error is expected
|
||||||
audioRecorder.audioFileURL = nil
|
audioRecorder.audioFileURL = nil
|
||||||
guard case .failure(.missingRecordingFile) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else {
|
guard case .failure(.missingRecordingFile) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy,
|
||||||
|
audioConverter: audioConverter,
|
||||||
|
threadRootEventID: nil) else {
|
||||||
XCTFail("An error is expected")
|
XCTFail("An error is expected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -208,7 +210,9 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
audioConverter.convertToOpusOggSourceURLDestinationURLThrowableError = AudioConverterError.conversionFailed(nil)
|
audioConverter.convertToOpusOggSourceURLDestinationURLThrowableError = AudioConverterError.conversionFailed(nil)
|
||||||
|
|
||||||
let roomProxy = JoinedRoomProxyMock()
|
let roomProxy = JoinedRoomProxyMock()
|
||||||
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else {
|
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy,
|
||||||
|
audioConverter: audioConverter,
|
||||||
|
threadRootEventID: nil) else {
|
||||||
XCTFail("An error is expected")
|
XCTFail("An error is expected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -227,8 +231,10 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
let timelineProxy = TimelineProxyMock()
|
let timelineProxy = TimelineProxyMock()
|
||||||
let roomProxy = JoinedRoomProxyMock()
|
let roomProxy = JoinedRoomProxyMock()
|
||||||
roomProxy.timeline = timelineProxy
|
roomProxy.timeline = timelineProxy
|
||||||
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue = .failure(.sdkError(SDKError.generic))
|
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleReturnValue = .failure(.sdkError(SDKError.generic))
|
||||||
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else {
|
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy,
|
||||||
|
audioConverter: audioConverter,
|
||||||
|
threadRootEventID: nil) else {
|
||||||
XCTFail("An error is expected")
|
XCTFail("An error is expected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -248,8 +254,10 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
let timelineProxy = TimelineProxyMock()
|
let timelineProxy = TimelineProxyMock()
|
||||||
let roomProxy = JoinedRoomProxyMock()
|
let roomProxy = JoinedRoomProxyMock()
|
||||||
roomProxy.timeline = timelineProxy
|
roomProxy.timeline = timelineProxy
|
||||||
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue = .failure(.sdkError(SDKError.generic))
|
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleReturnValue = .failure(.sdkError(SDKError.generic))
|
||||||
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else {
|
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy,
|
||||||
|
audioConverter: audioConverter,
|
||||||
|
threadRootEventID: nil) else {
|
||||||
XCTFail("An error is expected")
|
XCTFail("An error is expected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -271,8 +279,10 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
let timelineProxy = TimelineProxyMock()
|
let timelineProxy = TimelineProxyMock()
|
||||||
let roomProxy = JoinedRoomProxyMock()
|
let roomProxy = JoinedRoomProxyMock()
|
||||||
roomProxy.timeline = timelineProxy
|
roomProxy.timeline = timelineProxy
|
||||||
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleReturnValue = .failure(.sdkError(SDKError.generic))
|
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleReturnValue = .failure(.sdkError(SDKError.generic))
|
||||||
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else {
|
guard case .failure(.failedSendingVoiceMessage) = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy,
|
||||||
|
audioConverter: audioConverter,
|
||||||
|
threadRootEventID: nil) else {
|
||||||
XCTFail("An error is expected")
|
XCTFail("An error is expected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -307,7 +317,7 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
XCTAssertEqual(destination.pathExtension, "ogg")
|
XCTAssertEqual(destination.pathExtension, "ogg")
|
||||||
}
|
}
|
||||||
|
|
||||||
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure = { url, audioInfo, waveform, _ in
|
timelineProxy.sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleClosure = { url, audioInfo, waveform, _, _ in
|
||||||
XCTAssertEqual(url, convertedFileURL)
|
XCTAssertEqual(url, convertedFileURL)
|
||||||
XCTAssertEqual(audioInfo.duration, self.audioRecorder.currentTime)
|
XCTAssertEqual(audioInfo.duration, self.audioRecorder.currentTime)
|
||||||
XCTAssertEqual(audioInfo.size, convertedFileSize)
|
XCTAssertEqual(audioInfo.size, convertedFileSize)
|
||||||
@@ -317,13 +327,13 @@ class VoiceMessageRecorderTests: XCTestCase {
|
|||||||
return .success(())
|
return .success(())
|
||||||
}
|
}
|
||||||
|
|
||||||
guard case .success = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter) else {
|
guard case .success = await voiceMessageRecorder.sendVoiceMessage(inRoom: roomProxy, audioConverter: audioConverter, threadRootEventID: nil) else {
|
||||||
XCTFail("A success is expected")
|
XCTFail("A success is expected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
XCTAssert(audioConverter.convertToOpusOggSourceURLDestinationURLCalled)
|
XCTAssert(audioConverter.convertToOpusOggSourceURLDestinationURLCalled)
|
||||||
XCTAssert(timelineProxy.sendVoiceMessageUrlAudioInfoWaveformRequestHandleCalled)
|
XCTAssert(timelineProxy.sendVoiceMessageUrlAudioInfoWaveformThreadRootEventIDRequestHandleCalled)
|
||||||
|
|
||||||
// the converted file must have been deleted
|
// the converted file must have been deleted
|
||||||
if let convertedFileURL {
|
if let convertedFileURL {
|
||||||
|
|||||||
Reference in New Issue
Block a user