mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Convert the old MockTimelineController to the generated TimelineControllerMock
This commit is contained in:
@@ -21,7 +21,7 @@ extension TimelineControllerFactoryMock {
|
||||
if let timelineController = configuration.threadTimelineController {
|
||||
return timelineController
|
||||
} else {
|
||||
return MockTimelineController(timelineItems: RoomTimelineItemFixtures.largeChunk)
|
||||
return TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.largeChunk))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ extension TimelineControllerFactoryMock {
|
||||
if let timelineController = configuration.threadTimelineController {
|
||||
return .success(timelineController)
|
||||
} else {
|
||||
let timelineController = MockTimelineController(timelineKind: .thread(rootEventID: threadRootEventID), timelineItems: RoomTimelineItemFixtures.largeChunk)
|
||||
let timelineController = TimelineControllerMock(.init(timelineKind: .thread(rootEventID: threadRootEventID), timelineItems: RoomTimelineItemFixtures.largeChunk))
|
||||
return .success(timelineController)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ struct PollFormScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
static func makeViewModel(mode: PollFormMode) -> PollFormScreenViewModel {
|
||||
PollFormScreenViewModel(mode: mode,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
analytics: AnalyticsServiceMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ struct EmojiPickerScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModel = EmojiPickerScreenViewModel(itemID: .randomEvent,
|
||||
selectedEmojis: ["😀", "😄"],
|
||||
emojiProvider: EmojiProvider(appSettings: .volatile()),
|
||||
timelineController: MockTimelineController())
|
||||
timelineController: TimelineControllerMock(.init()))
|
||||
|
||||
static var previews: some View {
|
||||
EmojiPickerScreen(context: viewModel.context)
|
||||
@@ -117,7 +117,7 @@ struct EmojiPickerScreenSheet_Previews: PreviewProvider {
|
||||
static let viewModel = EmojiPickerScreenViewModel(itemID: .randomEvent,
|
||||
selectedEmojis: ["😀", "😄"],
|
||||
emojiProvider: EmojiProvider(appSettings: .volatile()),
|
||||
timelineController: MockTimelineController())
|
||||
timelineController: TimelineControllerMock(.init()))
|
||||
|
||||
static var previews: some View {
|
||||
Text("Timeline view")
|
||||
|
||||
@@ -163,7 +163,7 @@ struct TimelineMediaPreviewModifier_Previews: PreviewProvider {
|
||||
thumbnailSource: nil,
|
||||
contentType: .pdf))
|
||||
|
||||
let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: [item])
|
||||
let timelineController = TimelineControllerMock(.init(timelineKind: .media(.mediaFilesScreen), timelineItems: [item]))
|
||||
|
||||
let mediaProvider = MediaProviderMock(.init())
|
||||
|
||||
|
||||
+1
-1
@@ -220,7 +220,7 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie
|
||||
contentType: contentType))
|
||||
|
||||
let timelineKind = TimelineKind.media(isPresentedOnRoomScreen ? .roomScreenLive : .mediaFilesScreen)
|
||||
let timelineController = MockTimelineController(timelineKind: timelineKind, timelineItems: [item])
|
||||
let timelineController = TimelineControllerMock(.init(timelineKind: timelineKind, timelineItems: [item]))
|
||||
|
||||
let viewModel = TimelineMediaPreviewViewModel(initialItem: item,
|
||||
timelineViewModel: TimelineViewModel.mock(timelineKind: timelineKind,
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ struct TimelineMediaPreviewRedactConfirmationView_Previews: PreviewProvider, Tes
|
||||
thumbnailInfo: .mockThumbnail,
|
||||
contentType: contentType))
|
||||
|
||||
let timelineController = MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: [item])
|
||||
let timelineController = TimelineControllerMock(.init(timelineKind: .media(.mediaFilesScreen), timelineItems: [item]))
|
||||
return TimelineMediaPreviewViewModel(initialItem: item,
|
||||
timelineViewModel: TimelineViewModel.mock(timelineKind: timelineController.timelineKind,
|
||||
timelineController: timelineController),
|
||||
|
||||
@@ -392,7 +392,7 @@ extension LocationSharingScreenViewModel {
|
||||
return LocationSharingScreenViewModel(interactionMode: interactionMode,
|
||||
mapURLBuilder: AppSettings.volatile().mapTilerSettings.publisher.value,
|
||||
roomProxy: roomProxy,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
liveLocationManager: LiveLocationManagerMock(),
|
||||
analytics: AnalyticsServiceMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
+2
-2
@@ -305,9 +305,9 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
private static func makeTimelineViewModel(empty: Bool) -> TimelineViewModel {
|
||||
let timelineController = if empty {
|
||||
MockTimelineController.emptyMediaGallery
|
||||
TimelineControllerMock.emptyMediaGallery
|
||||
} else {
|
||||
MockTimelineController.mediaGallery
|
||||
TimelineControllerMock.mediaGallery
|
||||
}
|
||||
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
+1
-1
@@ -372,7 +372,7 @@ struct MediaUploadPreviewScreen_Previews: PreviewProvider, TestablePreview {
|
||||
isRoomEncrypted: true,
|
||||
shouldShowCaptionWarning: true,
|
||||
mediaUploadingPreprocessor: MediaUploadingPreprocessor(appSettings: .volatile()),
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
clientProxy: ClientProxyMock(.init()),
|
||||
userIndicatorController: UserIndicatorControllerMock())
|
||||
static var previews: some View {
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ struct PinnedEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
|
||||
analyticsService: AnalyticsServiceMock(.init()))
|
||||
|
||||
static let emptyTimelineViewModel: TimelineViewModel = {
|
||||
let timelineController = MockTimelineController(timelineKind: .pinned, timelineItems: [])
|
||||
let timelineController = TimelineControllerMock(.init(timelineKind: .pinned, timelineItems: []))
|
||||
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ private extension DateFormatter {
|
||||
|
||||
struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview {
|
||||
static let viewModelEmpty: RoomPollsHistoryScreenViewModel = {
|
||||
let timelineController = MockTimelineController(timelineItems: [])
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: []))
|
||||
let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls")
|
||||
return RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(),
|
||||
timelineController: timelineController,
|
||||
@@ -134,8 +134,8 @@ struct RoomPollsHistoryScreen_Previews: PreviewProvider, TestablePreview {
|
||||
timelineItemsTimestamps[item.id] = date
|
||||
}
|
||||
|
||||
let timelineController = MockTimelineController(timelineItems: polls,
|
||||
timelineItemsTimestamps: timelineItemsTimestamps)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: polls,
|
||||
timelineItemsTimestamps: timelineItemsTimestamps))
|
||||
|
||||
let roomProxyMockConfiguration = JoinedRoomProxyMockConfiguration(name: "Polls", timelineStartReached: true)
|
||||
return RoomPollsHistoryScreenViewModel(pollInteractionHandler: PollInteractionHandlerMock(),
|
||||
|
||||
@@ -364,7 +364,7 @@ struct RoomScreen_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
let appSettings = AppSettings.volatile()
|
||||
let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -1115,7 +1115,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
|
||||
extension TimelineViewModel {
|
||||
static let mock = mock(timelineKind: .live)
|
||||
|
||||
static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil, hasPredecessor: Bool = false) -> TimelineViewModel {
|
||||
static func mock(timelineKind: TimelineKind = .live, timelineController: TimelineControllerMock? = nil, hasPredecessor: Bool = false) -> TimelineViewModel {
|
||||
let clientProxyMock = ClientProxyMock(.init())
|
||||
clientProxyMock.roomSummaryForAliasReturnValue = .mock(id: "!room:matrix.org", name: "Room")
|
||||
clientProxyMock.roomSummaryForIdentifierReturnValue = .mock(id: "!room:matrix.org", name: "Room", canonicalAlias: "#room:matrix.org")
|
||||
@@ -1125,7 +1125,7 @@ extension TimelineViewModel {
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxy,
|
||||
focussedEventID: nil,
|
||||
timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
|
||||
timelineController: timelineController ?? TimelineControllerMock(.init(timelineKind: timelineKind)),
|
||||
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -48,7 +48,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -340,7 +340,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
||||
let roomProxy = JoinedRoomProxyMock(.init())
|
||||
return TimelineViewModel(roomProxy: roomProxy,
|
||||
focussedEventID: nil,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
@@ -359,7 +359,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
|
||||
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: ["pinned"]))
|
||||
return TimelineViewModel(roomProxy: roomProxy,
|
||||
focussedEventID: nil,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -83,7 +83,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)),
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxyMock,
|
||||
focussedEventID: focussedEventID,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
@@ -156,7 +156,7 @@ struct TimelineView_Previews: PreviewProvider { // Not testable as this preview
|
||||
let appSettings = AppSettings.volatile()
|
||||
|
||||
return TimelineViewModel(roomProxy: roomProxyMock,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
userSession: UserSessionMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
userIndicatorController: UserIndicatorControllerMock(),
|
||||
|
||||
+200
-280
@@ -12,318 +12,238 @@ import Combine
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
class MockTimelineController: TimelineControllerProtocol {
|
||||
private let lastInsertedMessageID: TimelineItemIdentifier = .event(uniqueID: .init("last_message"),
|
||||
eventOrTransactionID: .eventID("last_message"))
|
||||
|
||||
private var roomProxy: JoinedRoomProxyProtocol?
|
||||
private var timelineProxy: TimelineProxyProtocol?
|
||||
|
||||
var roomID: String {
|
||||
roomProxy?.id ?? "MockRoomIdentifier"
|
||||
}
|
||||
|
||||
private(set) var timelineKind: TimelineKind
|
||||
|
||||
let callbacks = PassthroughSubject<TimelineControllerCallback, Never>()
|
||||
|
||||
private(set) var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default {
|
||||
didSet {
|
||||
callbacks.send(.updatedTimelineItems(timelineItems: timelineItems, isSwitchingTimelines: false))
|
||||
}
|
||||
}
|
||||
|
||||
private let timelineItemsTimestamps: [TimelineItemIdentifier: Date]
|
||||
|
||||
/// An array of timeline item arrays that will be inserted in order for each back pagination request.
|
||||
var backPaginationResponses: [[RoomTimelineItemProtocol]] = []
|
||||
|
||||
var paginationState: TimelinePaginationState = .initial {
|
||||
didSet {
|
||||
callbacks.send(.paginationState(paginationState))
|
||||
}
|
||||
}
|
||||
|
||||
static var mediaGallery: MockTimelineController {
|
||||
MockTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in
|
||||
struct TimelineControllerMockConfiguration {
|
||||
var roomProxy: JoinedRoomProxyProtocol?
|
||||
var timelineKind: TimelineKind = .live
|
||||
var timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default
|
||||
var timelineProxy: TimelineProxyProtocol?
|
||||
var timelineItemsTimestamps: [TimelineItemIdentifier: Date] = [:]
|
||||
var paginationState: TimelinePaginationState = .initial
|
||||
}
|
||||
|
||||
extension TimelineControllerMock {
|
||||
static var mediaGallery: TimelineControllerMock {
|
||||
TimelineControllerMock(.init(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in
|
||||
partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
static var emptyMediaGallery: MockTimelineController {
|
||||
let mock = MockTimelineController(timelineKind: .media(.mediaFilesScreen))
|
||||
mock.paginationState = TimelinePaginationState(backward: .endReached, forward: .endReached)
|
||||
return mock
|
||||
static var emptyMediaGallery: TimelineControllerMock {
|
||||
TimelineControllerMock(.init(timelineKind: .media(.mediaFilesScreen),
|
||||
paginationState: TimelinePaginationState(backward: .endReached, forward: .endReached)))
|
||||
}
|
||||
|
||||
init(roomProxy: JoinedRoomProxyProtocol? = nil,
|
||||
timelineKind: TimelineKind = .live,
|
||||
timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default,
|
||||
timelineProxy: TimelineProxyProtocol? = nil,
|
||||
timelineItemsTimestamps: [TimelineItemIdentifier: Date] = [TimelineItemIdentifier: Date]()) {
|
||||
self.roomProxy = roomProxy
|
||||
self.timelineKind = timelineKind
|
||||
self.timelineItems = timelineItems
|
||||
self.timelineProxy = timelineProxy
|
||||
self.timelineItemsTimestamps = timelineItemsTimestamps
|
||||
// swiftlint:disable:next function_body_length cyclomatic_complexity
|
||||
convenience init(_ configuration: TimelineControllerMockConfiguration) {
|
||||
self.init()
|
||||
|
||||
callbacks.send(.paginationState(paginationState))
|
||||
let lastInsertedMessageID: TimelineItemIdentifier = .event(uniqueID: .init("last_message"),
|
||||
eventOrTransactionID: .eventID("last_message"))
|
||||
let roomProxy = configuration.roomProxy
|
||||
let timelineProxy = configuration.timelineProxy
|
||||
let timelineItemsTimestamps = configuration.timelineItemsTimestamps
|
||||
|
||||
underlyingCallbacks = PassthroughSubject()
|
||||
underlyingRoomID = roomProxy?.id ?? "MockRoomIdentifier"
|
||||
underlyingTimelineKind = configuration.timelineKind
|
||||
underlyingPaginationState = configuration.paginationState
|
||||
timelineItems = configuration.timelineItems
|
||||
|
||||
callbacks.send(.paginationState(configuration.paginationState))
|
||||
callbacks.send(.isLive(true))
|
||||
}
|
||||
|
||||
private(set) var focusOnEventCallCount = 0
|
||||
func focusOnEvent(_ eventID: String, timelineSize: UInt16) async -> Result<Void, TimelineControllerError> {
|
||||
focusOnEventCallCount += 1
|
||||
callbacks.send(.isLive(false))
|
||||
return .success(())
|
||||
}
|
||||
|
||||
private(set) var focusLiveCallCount = 0
|
||||
func focusLive() {
|
||||
focusLiveCallCount += 1
|
||||
callbacks.send(.isLive(true))
|
||||
}
|
||||
|
||||
private(set) var paginateBackwardsCallCount = 0
|
||||
func paginateBackwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
|
||||
paginateBackwardsCallCount += 1
|
||||
paginationState = TimelinePaginationState(backward: .paginating, forward: .endReached)
|
||||
simulateBackPagination()
|
||||
return .success(())
|
||||
}
|
||||
|
||||
private func simulateBackPagination() {
|
||||
defer {
|
||||
paginationState = TimelinePaginationState(backward: backPaginationResponses.isEmpty ? .endReached : .idle,
|
||||
forward: .endReached)
|
||||
|
||||
focusOnEventTimelineSizeClosure = { [weak self] _, _ in
|
||||
self?.callbacks.send(.isLive(false))
|
||||
return .success(())
|
||||
}
|
||||
|
||||
guard !backPaginationResponses.isEmpty else { return }
|
||||
|
||||
let newItems = backPaginationResponses.removeFirst()
|
||||
timelineItems.insert(contentsOf: newItems, at: 0)
|
||||
}
|
||||
|
||||
private(set) var paginateForwardsCallCount = 0
|
||||
func paginateForwards(requestSize: UInt16) async -> Result<Void, TimelineControllerError> {
|
||||
paginateForwardsCallCount += 1
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func sendReadReceipt(for itemID: TimelineItemIdentifier) async {
|
||||
guard let roomProxy, let eventID = itemID.eventID else { return }
|
||||
_ = await roomProxy.timeline.sendReadReceipt(for: eventID, type: .read)
|
||||
}
|
||||
|
||||
func processItemAppearance(_ itemID: TimelineItemIdentifier) async { }
|
||||
|
||||
func processItemDisappearance(_ itemID: TimelineItemIdentifier) async { }
|
||||
|
||||
func toggleReaction(_ reaction: String, to eventID: TimelineItemIdentifier.EventOrTransactionID) async {
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.toggleReaction(reaction, to: eventID)
|
||||
focusLiveClosure = { [weak self] in
|
||||
self?.callbacks.send(.isLive(true))
|
||||
}
|
||||
}
|
||||
|
||||
func edit(_ eventOrTransactionID: TimelineItemIdentifier.EventOrTransactionID,
|
||||
message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
timelineItems[timelineItems.endIndex - 1] = TextRoomTimelineItem(id: lastInsertedMessageID,
|
||||
timestamp: .distantFuture,
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
canBeRepliedTo: true,
|
||||
sender: .test,
|
||||
content: .init(body: message),
|
||||
properties: .init(isEdited: true))
|
||||
}
|
||||
|
||||
func editCaption(_ eventOrTransactionID: TimelineItemIdentifier.EventOrTransactionID,
|
||||
message: String,
|
||||
html: String?,
|
||||
intentionalMentions: IntentionalMentions) async { }
|
||||
|
||||
func removeCaption(_ eventOrTransactionID: TimelineItemIdentifier.EventOrTransactionID) async { }
|
||||
|
||||
private(set) var redactCalled = false
|
||||
func redact(_ eventOrTransactionID: TimelineItemIdentifier.EventOrTransactionID) async {
|
||||
if let timelineProxy {
|
||||
paginateBackwardsRequestSizeReturnValue = .success(())
|
||||
paginateForwardsRequestSizeReturnValue = .success(())
|
||||
|
||||
sendReadReceiptForClosure = { [roomProxy] itemID in
|
||||
guard let roomProxy, let eventID = itemID.eventID else { return }
|
||||
_ = await roomProxy.timeline.sendReadReceipt(for: eventID, type: .read)
|
||||
}
|
||||
|
||||
toggleReactionToClosure = { [timelineProxy] reaction, eventOrTransactionID in
|
||||
guard let timelineProxy else { return }
|
||||
_ = await timelineProxy.toggleReaction(reaction, to: eventOrTransactionID)
|
||||
}
|
||||
|
||||
redactClosure = { [timelineProxy] eventOrTransactionID in
|
||||
guard let timelineProxy else { return }
|
||||
_ = await timelineProxy.redact(eventOrTransactionID, reason: nil)
|
||||
}
|
||||
redactCalled = true
|
||||
}
|
||||
|
||||
func pin(eventID: String) async { }
|
||||
|
||||
func unpin(eventID: String) async { }
|
||||
|
||||
func messageEventContent(for itemID: TimelineItemIdentifier) -> RoomMessageEventContentWithoutRelation? {
|
||||
.init(noHandle: .init())
|
||||
}
|
||||
|
||||
func debugInfo(for itemID: TimelineItemIdentifier) -> TimelineItemDebugInfo {
|
||||
.init(model: "Mock debug description", originalJSON: nil, latestEditJSON: nil)
|
||||
}
|
||||
|
||||
func sendHandle(for itemID: TimelineItemIdentifier) -> SendHandleProxy? {
|
||||
nil
|
||||
}
|
||||
|
||||
func eventTimestamp(for itemID: TimelineItemIdentifier) -> Date? {
|
||||
timelineItemsTimestamps[itemID] ?? .now
|
||||
}
|
||||
|
||||
// MARK: - Sending
|
||||
|
||||
func sendMessage(_ message: String,
|
||||
html: String?,
|
||||
inReplyToEventID: String?,
|
||||
intentionalMentions: IntentionalMentions) async {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
timelineItems.append(TextRoomTimelineItem(id: lastInsertedMessageID,
|
||||
timestamp: .distantFuture,
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
canBeRepliedTo: true,
|
||||
sender: .test,
|
||||
content: .init(body: message)))
|
||||
}
|
||||
|
||||
func sendAudio(url: URL,
|
||||
audioInfo: MatrixRustSDK.AudioInfo,
|
||||
caption: String?,
|
||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendAudio(url: url,
|
||||
audioInfo: audioInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
editMessageHtmlIntentionalMentionsClosure = { [weak self] _, message, _, _ in
|
||||
guard let self else { return }
|
||||
self.callbacks.send(.messageSentOrEdited)
|
||||
self.timelineItems[self.timelineItems.endIndex - 1] = TextRoomTimelineItem(id: lastInsertedMessageID,
|
||||
timestamp: .distantFuture,
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
canBeRepliedTo: true,
|
||||
sender: .test,
|
||||
content: .init(body: message),
|
||||
properties: .init(isEdited: true))
|
||||
self.callbacks.send(.updatedTimelineItems(timelineItems: self.timelineItems, isSwitchingTimelines: false))
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func sendFile(url: URL,
|
||||
fileInfo: MatrixRustSDK.FileInfo,
|
||||
caption: String?,
|
||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendFile(url: url,
|
||||
fileInfo: fileInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
sendMessageHtmlInReplyToEventIDIntentionalMentionsClosure = { [weak self] message, _, _, _ in
|
||||
guard let self else { return }
|
||||
self.callbacks.send(.messageSentOrEdited)
|
||||
self.timelineItems.append(TextRoomTimelineItem(id: lastInsertedMessageID,
|
||||
timestamp: .distantFuture,
|
||||
isOutgoing: true,
|
||||
isEditable: true,
|
||||
canBeRepliedTo: true,
|
||||
sender: .test,
|
||||
content: .init(body: message)))
|
||||
self.callbacks.send(.updatedTimelineItems(timelineItems: self.timelineItems, isSwitchingTimelines: false))
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func sendImage(url: URL,
|
||||
thumbnailURL: URL,
|
||||
imageInfo: MatrixRustSDK.ImageInfo,
|
||||
caption: String?,
|
||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendImage(url: url,
|
||||
thumbnailURL: thumbnailURL,
|
||||
imageInfo: imageInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
sendAudioUrlAudioInfoCaptionRequestHandleClosure = { [weak self, timelineProxy] url, audioInfo, caption, requestHandle in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendAudio(url: url,
|
||||
audioInfo: audioInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func sendLocation(body: String,
|
||||
geoURI: GeoURI,
|
||||
description: String?,
|
||||
zoomLevel: UInt8?,
|
||||
assetType: MatrixRustSDK.AssetType?) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendLocation(body: body,
|
||||
geoURI: geoURI,
|
||||
description: description,
|
||||
zoomLevel: zoomLevel,
|
||||
assetType: assetType).mapError(TimelineControllerError.timelineProxyError)
|
||||
sendFileUrlFileInfoCaptionRequestHandleClosure = { [weak self, timelineProxy] url, fileInfo, caption, requestHandle in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendFile(url: url,
|
||||
fileInfo: fileInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func sendVideo(url: URL,
|
||||
thumbnailURL: URL,
|
||||
videoInfo: MatrixRustSDK.VideoInfo,
|
||||
caption: String?,
|
||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendVideo(url: url,
|
||||
thumbnailURL: thumbnailURL,
|
||||
videoInfo: videoInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
sendImageUrlThumbnailURLImageInfoCaptionRequestHandleClosure = { [weak self, timelineProxy] url, thumbnailURL, imageInfo, caption, requestHandle in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendImage(url: url,
|
||||
thumbnailURL: thumbnailURL,
|
||||
imageInfo: imageInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func sendVoiceMessage(url: URL,
|
||||
audioInfo: MatrixRustSDK.AudioInfo,
|
||||
waveform: [Float],
|
||||
requestHandle: @MainActor (SendAttachmentJoinHandleProtocol) -> Void) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendVoiceMessage(url: url,
|
||||
audioInfo: audioInfo,
|
||||
waveform: waveform,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
sendLocationBodyGeoURIDescriptionZoomLevelAssetTypeClosure = { [weak self, timelineProxy] body, geoURI, description, zoomLevel, assetType in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendLocation(body: body,
|
||||
geoURI: geoURI,
|
||||
description: description,
|
||||
zoomLevel: zoomLevel,
|
||||
assetType: assetType).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
|
||||
// MARK: - Polls
|
||||
|
||||
func createPoll(question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
|
||||
callbacks.send(.messageSentOrEdited)
|
||||
sendVideoUrlThumbnailURLVideoInfoCaptionRequestHandleClosure = { [weak self, timelineProxy] url, thumbnailURL, videoInfo, caption, requestHandle in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendVideo(url: url,
|
||||
thumbnailURL: thumbnailURL,
|
||||
videoInfo: videoInfo,
|
||||
caption: caption,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.createPoll(question: question, answers: answers, pollKind: pollKind)
|
||||
sendVoiceMessageUrlAudioInfoWaveformRequestHandleClosure = { [weak self, timelineProxy] url, audioInfo, waveform, requestHandle in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
return await timelineProxy.sendVoiceMessage(url: url,
|
||||
audioInfo: audioInfo,
|
||||
waveform: waveform,
|
||||
requestHandle: requestHandle).mapError(TimelineControllerError.timelineProxyError)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
createPollQuestionAnswersPollKindClosure = { [weak self, timelineProxy] question, answers, pollKind in
|
||||
self?.callbacks.send(.messageSentOrEdited)
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.createPoll(question: question, answers: answers, pollKind: pollKind)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
editPollOriginalQuestionAnswersPollKindClosure = { [timelineProxy] eventID, question, answers, pollKind in
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.editPoll(original: eventID, question: question, answers: answers, pollKind: pollKind)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
sendPollResponsePollStartIDAnswersClosure = { [timelineProxy] pollStartID, answers in
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.sendPollResponse(pollStartID: pollStartID, answers: answers)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
endPollPollStartIDTextClosure = { [timelineProxy] pollStartID, text in
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.endPoll(pollStartID: pollStartID, text: text)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
messageEventContentForReturnValue = .init(noHandle: .init())
|
||||
debugInfoForReturnValue = .init(model: "Mock debug description", originalJSON: nil, latestEditJSON: nil)
|
||||
|
||||
eventTimestampForClosure = { [timelineItemsTimestamps] itemID in
|
||||
timelineItemsTimestamps[itemID] ?? .now
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func editPoll(original eventID: String, question: String, answers: [String], pollKind: Poll.Kind) async -> Result<Void, TimelineControllerError> {
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.editPoll(original: eventID, question: question, answers: answers, pollKind: pollKind)
|
||||
}
|
||||
return .success(())
|
||||
func update(paginationState: TimelinePaginationState) {
|
||||
self.paginationState = paginationState
|
||||
callbacks.send(.paginationState(paginationState))
|
||||
}
|
||||
|
||||
func sendPollResponse(pollStartID: String, answers: [String]) async -> Result<Void, TimelineControllerError> {
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.sendPollResponse(pollStartID: pollStartID, answers: answers)
|
||||
/// Configures `paginateBackwardsRequestSizeClosure` to simulate back pagination from the given response queue,
|
||||
/// sending the appropriate `updatedTimelineItems` and `paginationState` callbacks each time.
|
||||
func setupBackPagination(responses: [[RoomTimelineItemProtocol]]) {
|
||||
var queue = responses
|
||||
paginateBackwardsRequestSizeClosure = { [weak self] _ in
|
||||
guard let self else { return .success(()) }
|
||||
|
||||
let paginating = TimelinePaginationState(backward: .paginating, forward: .endReached)
|
||||
self.paginationState = paginating
|
||||
self.callbacks.send(.paginationState(paginating))
|
||||
|
||||
guard !queue.isEmpty else {
|
||||
let end = TimelinePaginationState(backward: .endReached, forward: .endReached)
|
||||
self.paginationState = end
|
||||
self.callbacks.send(.paginationState(end))
|
||||
return .success(())
|
||||
}
|
||||
|
||||
let newItems = queue.removeFirst()
|
||||
self.timelineItems.insert(contentsOf: newItems, at: 0)
|
||||
self.callbacks.send(.updatedTimelineItems(timelineItems: self.timelineItems, isSwitchingTimelines: false))
|
||||
|
||||
let final = TimelinePaginationState(backward: queue.isEmpty ? .endReached : .idle, forward: .endReached)
|
||||
self.paginationState = final
|
||||
self.callbacks.send(.paginationState(final))
|
||||
|
||||
return .success(())
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
|
||||
func endPoll(pollStartID: String, text: String) async -> Result<Void, TimelineControllerError> {
|
||||
if let timelineProxy {
|
||||
_ = await timelineProxy.endPoll(pollStartID: pollStartID, text: text)
|
||||
}
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ class MockScreen: Identifiable {
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Some room name", avatarURL: nil)),
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
mediaPlayerProvider: MediaPlayerProviderMock(),
|
||||
emojiProvider: EmojiProvider(appSettings: appSettings),
|
||||
linkMetadataProvider: LinkMetadataProvider(),
|
||||
@@ -308,7 +308,7 @@ class MockScreen: Identifiable {
|
||||
return navigationStackCoordinator
|
||||
case .roomSmallTimeline:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.smallChunk)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.smallChunk))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -329,7 +329,7 @@ class MockScreen: Identifiable {
|
||||
return navigationStackCoordinator
|
||||
case .roomSmallTimelineWithReactions:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.default)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.default))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -349,7 +349,7 @@ class MockScreen: Identifiable {
|
||||
return navigationStackCoordinator
|
||||
case .roomSmallTimelineWithReadReceipts:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.smallChunkWithReadReceipts)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.smallChunkWithReadReceipts))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "New room", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -501,7 +501,7 @@ class MockScreen: Identifiable {
|
||||
case .roomLayoutHighlight:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.permalinkChunk)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.permalinkChunk))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Timeline highlight", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -536,7 +536,7 @@ class MockScreen: Identifiable {
|
||||
case .roomWithDisclosedPolls:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.disclosedPolls)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.disclosedPolls))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -558,7 +558,7 @@ class MockScreen: Identifiable {
|
||||
case .roomWithUndisclosedPolls:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.undisclosedPolls)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.undisclosedPolls))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -580,7 +580,7 @@ class MockScreen: Identifiable {
|
||||
case .roomWithOutgoingPolls:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let timelineController = MockTimelineController(timelineItems: RoomTimelineItemFixtures.outgoingPolls)
|
||||
let timelineController = TimelineControllerMock(.init(timelineItems: RoomTimelineItemFixtures.outgoingPolls))
|
||||
let parameters = RoomScreenCoordinatorParameters(userSession: UserSessionMock(.init()),
|
||||
roomProxy: JoinedRoomProxyMock(.init(name: "Polls timeline", avatarURL: .mockMXCAvatar)),
|
||||
timelineController: timelineController,
|
||||
@@ -732,7 +732,7 @@ class MockScreen: Identifiable {
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
let coordinator = PollFormScreenCoordinator(parameters: .init(mode: .new(topic: nil),
|
||||
maxNumberOfOptions: 10,
|
||||
timelineController: MockTimelineController(),
|
||||
timelineController: TimelineControllerMock(.init()),
|
||||
analytics: analytics,
|
||||
userIndicatorController: UserIndicatorControllerMock()))
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator)
|
||||
|
||||
Reference in New Issue
Block a user