Skip to content

Commit

Permalink
Refactor theTimelineItemIdentifier handling; stop relying on option…
Browse files Browse the repository at this point in the history
…al `EventOrTransactionId`s and be explicit when setting composer modes from the draft service.
  • Loading branch information
stefanceriu committed Oct 16, 2024
1 parent 236d142 commit d357fd9
Show file tree
Hide file tree
Showing 56 changed files with 313 additions and 298 deletions.
4 changes: 4 additions & 0 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@
86F9D3028A1F4AE819D75560 /* RoomChangePermissionsScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D879FC4E881E748BB9B34DC /* RoomChangePermissionsScreenCoordinator.swift */; };
872A6457DF573AF8CEAE927A /* LoginHomeserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9349F590E35CE514A71E6764 /* LoginHomeserver.swift */; };
874FEFB9D4A4AF447E0E086E /* AuthenticationStartScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0F7CCC4A9D1927223F559D5 /* AuthenticationStartScreenViewModelProtocol.swift */; };
877D3CE8680536DB430DE6A2 /* TimelineItemIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */; };
878070573C7BF19E735707B4 /* RoomTimelineItemProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DE8D25D6A91030175D52A20 /* RoomTimelineItemProperties.swift */; };
87B4E59A4467F8EC75F82372 /* VoiceMessageRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B70A50C41C5871B4DB905E7E /* VoiceMessageRoomTimelineView.swift */; };
87CEA3E07B602705BC2D2A20 /* ClientBuilderHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC0CD1CAFD3F8B057F9AEA5 /* ClientBuilderHook.swift */; };
Expand Down Expand Up @@ -2189,6 +2190,7 @@
E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioConverter.swift; sourceTree = "<group>"; };
E45EBAFF1A83538D54ABDF92 /* ServerSelectionScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModelTests.swift; sourceTree = "<group>"; };
E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteURLParserTests.swift; sourceTree = "<group>"; };
E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemIdentifier.swift; sourceTree = "<group>"; };
E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = "<group>"; };
E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = "<group>"; };
E55B5EA766E89FF1F87C3ACB /* RoomNotificationSettingsProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomNotificationSettingsProxyProtocol.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5473,6 +5475,7 @@
0DF5CBAF69BDF5DF31C661E1 /* IntentionalMentions.swift */,
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */,
095AED4CF56DFF3EB7BB84C8 /* RoomTimelineProviderProtocol.swift */,
E48C91C8BE55CAE1A3DBC3BC /* TimelineItemIdentifier.swift */,
2D505843AB66822EB91F0DF0 /* TimelineItemProxy.swift */,
55AEEF8142DF1B59DB40FB93 /* TimelineItemSender.swift */,
F9E543072DE58E751F028998 /* TimelineProxy.swift */,
Expand Down Expand Up @@ -6931,6 +6934,7 @@
E6FA87F773424B27614B23E9 /* TimelineItemAccessibilityModifier.swift in Sources */,
79959F8E45C3749997482A7F /* TimelineItemBubbledStylerView.swift in Sources */,
A808DC3F72D15C6C5A52317E /* TimelineItemDebugView.swift in Sources */,
877D3CE8680536DB430DE6A2 /* TimelineItemIdentifier.swift in Sources */,
C0B97FFEC0083F3A36609E61 /* TimelineItemMacContextMenu.swift in Sources */,
6C98153D60FF9B648C166C27 /* TimelineItemMenu.swift in Sources */,
AE07F215EBC2B9CBF17AA54B /* TimelineItemMenuAction.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions ElementX/Sources/Application/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg

switch await roomProxy.timeline.sendMessage(replyText,
html: nil,
inReplyToEventID: nil,
intentionalMentions: .empty) {
case .success:
break
Expand Down
62 changes: 31 additions & 31 deletions ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13987,8 +13987,8 @@ class TimelineProxyMock: TimelineProxyProtocol {
var editNewContentCalled: Bool {
return editNewContentCallsCount > 0
}
var editNewContentReceivedArguments: (timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation)?
var editNewContentReceivedInvocations: [(timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation)] = []
var editNewContentReceivedArguments: (eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation)?
var editNewContentReceivedInvocations: [(eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation)] = []

var editNewContentUnderlyingReturnValue: Result<Void, TimelineProxyError>!
var editNewContentReturnValue: Result<Void, TimelineProxyError>! {
Expand All @@ -14014,16 +14014,16 @@ class TimelineProxyMock: TimelineProxyProtocol {
}
}
}
var editNewContentClosure: ((EventTimelineItem, RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>)?
var editNewContentClosure: ((EventOrTransactionId, RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError>)?

func edit(_ timelineItem: EventTimelineItem, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError> {
func edit(_ eventOrTransactionID: EventOrTransactionId, newContent: RoomMessageEventContentWithoutRelation) async -> Result<Void, TimelineProxyError> {
editNewContentCallsCount += 1
editNewContentReceivedArguments = (timelineItem: timelineItem, newContent: newContent)
editNewContentReceivedArguments = (eventOrTransactionID: eventOrTransactionID, newContent: newContent)
DispatchQueue.main.async {
self.editNewContentReceivedInvocations.append((timelineItem: timelineItem, newContent: newContent))
self.editNewContentReceivedInvocations.append((eventOrTransactionID: eventOrTransactionID, newContent: newContent))
}
if let editNewContentClosure = editNewContentClosure {
return await editNewContentClosure(timelineItem, newContent)
return await editNewContentClosure(eventOrTransactionID, newContent)
} else {
return editNewContentReturnValue
}
Expand Down Expand Up @@ -14770,72 +14770,72 @@ class TimelineProxyMock: TimelineProxyProtocol {
}
//MARK: - sendMessage

var sendMessageHtmlInReplyToIntentionalMentionsUnderlyingCallsCount = 0
var sendMessageHtmlInReplyToIntentionalMentionsCallsCount: Int {
var sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingCallsCount = 0
var sendMessageHtmlInReplyToEventIDIntentionalMentionsCallsCount: Int {
get {
if Thread.isMainThread {
return sendMessageHtmlInReplyToIntentionalMentionsUnderlyingCallsCount
return sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = sendMessageHtmlInReplyToIntentionalMentionsUnderlyingCallsCount
returnValue = sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingCallsCount
}

return returnValue!
}
}
set {
if Thread.isMainThread {
sendMessageHtmlInReplyToIntentionalMentionsUnderlyingCallsCount = newValue
sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
sendMessageHtmlInReplyToIntentionalMentionsUnderlyingCallsCount = newValue
sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingCallsCount = newValue
}
}
}
}
var sendMessageHtmlInReplyToIntentionalMentionsCalled: Bool {
return sendMessageHtmlInReplyToIntentionalMentionsCallsCount > 0
var sendMessageHtmlInReplyToEventIDIntentionalMentionsCalled: Bool {
return sendMessageHtmlInReplyToEventIDIntentionalMentionsCallsCount > 0
}
var sendMessageHtmlInReplyToIntentionalMentionsReceivedArguments: (message: String, html: String?, eventID: String?, intentionalMentions: IntentionalMentions)?
var sendMessageHtmlInReplyToIntentionalMentionsReceivedInvocations: [(message: String, html: String?, eventID: String?, intentionalMentions: IntentionalMentions)] = []
var sendMessageHtmlInReplyToEventIDIntentionalMentionsReceivedArguments: (message: String, html: String?, inReplyToEventID: String?, intentionalMentions: IntentionalMentions)?
var sendMessageHtmlInReplyToEventIDIntentionalMentionsReceivedInvocations: [(message: String, html: String?, inReplyToEventID: String?, intentionalMentions: IntentionalMentions)] = []

var sendMessageHtmlInReplyToIntentionalMentionsUnderlyingReturnValue: Result<Void, TimelineProxyError>!
var sendMessageHtmlInReplyToIntentionalMentionsReturnValue: Result<Void, TimelineProxyError>! {
var sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingReturnValue: Result<Void, TimelineProxyError>!
var sendMessageHtmlInReplyToEventIDIntentionalMentionsReturnValue: Result<Void, TimelineProxyError>! {
get {
if Thread.isMainThread {
return sendMessageHtmlInReplyToIntentionalMentionsUnderlyingReturnValue
return sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingReturnValue
} else {
var returnValue: Result<Void, TimelineProxyError>? = nil
DispatchQueue.main.sync {
returnValue = sendMessageHtmlInReplyToIntentionalMentionsUnderlyingReturnValue
returnValue = sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingReturnValue
}

return returnValue!
}
}
set {
if Thread.isMainThread {
sendMessageHtmlInReplyToIntentionalMentionsUnderlyingReturnValue = newValue
sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
sendMessageHtmlInReplyToIntentionalMentionsUnderlyingReturnValue = newValue
sendMessageHtmlInReplyToEventIDIntentionalMentionsUnderlyingReturnValue = newValue
}
}
}
}
var sendMessageHtmlInReplyToIntentionalMentionsClosure: ((String, String?, String?, IntentionalMentions) async -> Result<Void, TimelineProxyError>)?
var sendMessageHtmlInReplyToEventIDIntentionalMentionsClosure: ((String, String?, String?, IntentionalMentions) async -> Result<Void, TimelineProxyError>)?

func sendMessage(_ message: String, html: String?, inReplyTo eventID: String?, intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
sendMessageHtmlInReplyToIntentionalMentionsCallsCount += 1
sendMessageHtmlInReplyToIntentionalMentionsReceivedArguments = (message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions)
func sendMessage(_ message: String, html: String?, inReplyToEventID: String?, intentionalMentions: IntentionalMentions) async -> Result<Void, TimelineProxyError> {
sendMessageHtmlInReplyToEventIDIntentionalMentionsCallsCount += 1
sendMessageHtmlInReplyToEventIDIntentionalMentionsReceivedArguments = (message: message, html: html, inReplyToEventID: inReplyToEventID, intentionalMentions: intentionalMentions)
DispatchQueue.main.async {
self.sendMessageHtmlInReplyToIntentionalMentionsReceivedInvocations.append((message: message, html: html, eventID: eventID, intentionalMentions: intentionalMentions))
self.sendMessageHtmlInReplyToEventIDIntentionalMentionsReceivedInvocations.append((message: message, html: html, inReplyToEventID: inReplyToEventID, intentionalMentions: intentionalMentions))
}
if let sendMessageHtmlInReplyToIntentionalMentionsClosure = sendMessageHtmlInReplyToIntentionalMentionsClosure {
return await sendMessageHtmlInReplyToIntentionalMentionsClosure(message, html, eventID, intentionalMentions)
if let sendMessageHtmlInReplyToEventIDIntentionalMentionsClosure = sendMessageHtmlInReplyToEventIDIntentionalMentionsClosure {
return await sendMessageHtmlInReplyToEventIDIntentionalMentionsClosure(message, html, inReplyToEventID, intentionalMentions)
} else {
return sendMessageHtmlInReplyToIntentionalMentionsReturnValue
return sendMessageHtmlInReplyToEventIDIntentionalMentionsReturnValue
}
}
//MARK: - toggleReaction
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Mocks/PollMock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension Poll.Option {

extension PollRoomTimelineItem {
static func mock(poll: Poll, isOutgoing: Bool = true, isEditable: Bool = false) -> Self {
.init(id: .random,
.init(id: .randomEvent,
poll: poll,
body: "poll",
timestamp: "Now",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ private struct MessageForwardingListRow: View {
struct MessageForwardingScreen_Previews: PreviewProvider, TestablePreview {
static var previews: some View {
let summaryProvider = RoomSummaryProviderMock(.init(state: .loaded(.mockRooms)))
let viewModel = MessageForwardingScreenViewModel(forwardingItem: .init(id: .init(uniqueID: ""),
let viewModel = MessageForwardingScreenViewModel(forwardingItem: .init(id: .randomEvent,
roomID: "",
content: .init(noPointer: .init())),
clientProxy: ClientProxyMock(.init()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ struct ResolveVerifiedUserSendFailureScreen_Previews: PreviewProvider, TestableP

static func makeViewModel(failure: TimelineItemSendFailure.VerifiedUser) -> ResolveVerifiedUserSendFailureScreenViewModel {
ResolveVerifiedUserSendFailureScreenViewModel(failure: failure,
itemID: .random,
itemID: .randomEvent,
roomProxy: JoinedRoomProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock())
}
}

struct ResolveVerifiedUserSendFailureScreenSheet_Previews: PreviewProvider {
static let viewModel = ResolveVerifiedUserSendFailureScreenViewModel(failure: .changedIdentity(users: ["@alice:matrix.org"]),
itemID: .random,
itemID: .randomEvent,
roomProxy: JoinedRoomProxyMock(.init()),
userIndicatorController: UserIndicatorControllerMock())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Compound
import MatrixRustSDK
import SwiftUI
import WysiwygComposer

Expand Down Expand Up @@ -283,9 +284,14 @@ extension FormatType {
}

enum ComposerMode: Equatable {
enum EditSource {
case timeline
case draftService
}

case `default`
case reply(itemID: TimelineItemIdentifier, replyDetails: TimelineItemReplyDetails, isThread: Bool)
case edit(originalItemId: TimelineItemIdentifier)
case reply(eventID: String, replyDetails: TimelineItemReplyDetails, isThread: Bool)
case edit(originalEventOrTransactionID: EventOrTransactionId, source: EditSource)
case recordVoiceMessage(state: AudioRecorderState)
case previewVoiceMessage(state: AudioPlayerState, waveform: WaveformSource, isUploading: Bool)

Expand Down Expand Up @@ -323,8 +329,8 @@ enum ComposerMode: Equatable {

var replyEventID: String? {
switch self {
case .reply(let itemID, _, _):
return itemID.eventID
case .reply(let eventID, _, _):
return eventID
default:
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
case .newMessage:
set(mode: .default)
case .edit(let eventID):
set(mode: .edit(originalItemId: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: eventID))))
set(mode: .edit(originalEventOrTransactionID: .eventId(eventId: eventID), source: .draftService))
case .reply(let eventID):
set(mode: .reply(itemID: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: eventID)), replyDetails: .loading(eventID: eventID), isThread: false))
set(mode: .reply(eventID: eventID, replyDetails: .loading(eventID: eventID), isThread: false))
replyLoadingTask = Task {
let reply = switch await draftService.getReply(eventID: eventID) {
case .success(let reply):
Expand All @@ -273,7 +273,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
return
}

set(mode: .reply(itemID: .init(uniqueID: "", eventOrTransactionID: .eventId(eventId: eventID)), replyDetails: reply.details, isThread: reply.isThreaded))
set(mode: .reply(eventID: eventID, replyDetails: reply.details, isThread: reply.isThreaded))
}
}
}
Expand Down Expand Up @@ -314,17 +314,9 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
switch state.composerMode {
case .default:
type = .newMessage
case .edit(let itemID):
guard let eventID = itemID.eventID else {
MXLog.error("The event id for this message is missing")
return
}
type = .edit(eventID: eventID)
case .reply(let itemID, _, _):
guard let eventID = itemID.eventID else {
MXLog.error("The event id for this message is missing")
return
}
case .edit(.eventId(let originalEventID), _):
type = .edit(eventID: originalEventID)
case .reply(let eventID, _, _):
type = .reply(eventID: eventID)
default:
if isVolatile {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,10 @@ extension ComposerToolbar {
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
analyticsService: ServiceLocator.shared.analytics,
composerDraftService: ComposerDraftServiceMock())
model.state.composerMode = isLoading ? .reply(itemID: .init(uniqueID: ""),
model.state.composerMode = isLoading ? .reply(eventID: UUID().uuidString,
replyDetails: .loading(eventID: ""),
isThread: false) :
.reply(itemID: .init(uniqueID: ""),
.reply(eventID: UUID().uuidString,
replyDetails: .loaded(sender: .init(id: "",
displayName: "Test"),
eventID: "", eventContent: .message(.text(.init(body: "Hello World!")))), isThread: false)
Expand Down
Loading

0 comments on commit d357fd9

Please sign in to comment.