diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 327062dc1..605bf86a8 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 182BC48127C4EBBB00A30C33 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 182BC48027C4EBBB00A30C33 /* Kingfisher */; }; 183E023227E4A3CF00903BED /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183E023127E4A3CF00903BED /* PlaceholderAvatarImage.swift */; }; + 183E023427E4A73C00903BED /* MemberDetailsProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183E023327E4A73C00903BED /* MemberDetailsProviderProtocol.swift */; }; + 183E023627E4A79D00903BED /* RoomTimelineProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 183E023527E4A79D00903BED /* RoomTimelineProviderProtocol.swift */; }; 184B31DF27D898960075A669 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 184B31DE27D898960075A669 /* Introspect */; }; 1850253F27B6918D002E6B18 /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1850253E27B6918D002E6B18 /* ElementXTests.swift */; }; 1850254927B6918D002E6B18 /* ElementXUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1850254827B6918D002E6B18 /* ElementXUITests.swift */; }; @@ -123,6 +125,8 @@ /* Begin PBXFileReference section */ 181716DC27E11EF1002B8E3F /* matrix-rust-components-swift */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "matrix-rust-components-swift"; path = "../matrix-rust-components-swift"; sourceTree = ""; }; 183E023127E4A3CF00903BED /* PlaceholderAvatarImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PlaceholderAvatarImage.swift; path = ../../../../../../../../Desktop/PlaceholderAvatarImage.swift; sourceTree = ""; }; + 183E023327E4A73C00903BED /* MemberDetailsProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberDetailsProviderProtocol.swift; sourceTree = ""; }; + 183E023527E4A79D00903BED /* RoomTimelineProviderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProviderProtocol.swift; sourceTree = ""; }; 1850252427B6918C002E6B18 /* ElementX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ElementX.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1850253A27B6918D002E6B18 /* ElementXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ElementXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 1850253E27B6918D002E6B18 /* ElementXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementXTests.swift; sourceTree = ""; }; @@ -399,6 +403,7 @@ 18DF7C5127E4753A00291672 /* Members */ = { isa = PBXGroup; children = ( + 183E023327E4A73C00903BED /* MemberDetailsProviderProtocol.swift */, 18DF7C5227E4754500291672 /* MemberDetailsProvider.swift */, ); path = Members; @@ -418,10 +423,11 @@ 18F2BA7627D25B4000DD1988 /* Timeline */ = { isa = PBXGroup; children = ( + 183E023527E4A79D00903BED /* RoomTimelineProviderProtocol.swift */, + 18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */, 18F2BB2927D2648900DD1988 /* RoomTimelineControllerProtocol.swift */, 18F2BB1927D25BE800DD1988 /* RoomTimelineController.swift */, 18F2BB2727D2647A00DD1988 /* MockRoomTimelineController.swift */, - 18F2BA7727D25B4000DD1988 /* RoomTimelineProvider.swift */, 18DF7C3427E4670600291672 /* TimelineItems */, ); path = Timeline; @@ -858,6 +864,7 @@ 18DF7C4127E4670600291672 /* RoomTimelineViewProvider.swift in Sources */, 18F2BB0F27D25B4000DD1988 /* RoomScreen.swift in Sources */, 18F2BAFF27D25B4000DD1988 /* HomeScreenModels.swift in Sources */, + 183E023427E4A73C00903BED /* MemberDetailsProviderProtocol.swift in Sources */, 18DF7C4E27E4673E00291672 /* DecorationTimelineItemProtocol.swift in Sources */, 18F2BB1527D25B4000DD1988 /* LoginScreenViewModelProtocol.swift in Sources */, 18F2BAEB27D25B4000DD1988 /* LabelledActivityIndicatorView.swift in Sources */, @@ -870,6 +877,7 @@ 18F2BB1227D25B4000DD1988 /* LoginScreenViewModel.swift in Sources */, 18F2BAE727D25B4000DD1988 /* RoundedToastView.swift in Sources */, 18F2BAF227D25B4000DD1988 /* WeakDictionaryKeyReference.swift in Sources */, + 183E023627E4A79D00903BED /* RoomTimelineProviderProtocol.swift in Sources */, 18DF7C4727E4670600291672 /* TextRoomTimelineItem.swift in Sources */, 18F2BAE027D25B4000DD1988 /* NavigationRouter.swift in Sources */, 18F2BAF627D25B4000DD1988 /* Coordinator.swift in Sources */, diff --git a/ElementX/Sources/Services/Room/Members/MemberDetailsProvider.swift b/ElementX/Sources/Services/Room/Members/MemberDetailsProvider.swift index b00624ad1..6c093c802 100644 --- a/ElementX/Sources/Services/Room/Members/MemberDetailsProvider.swift +++ b/ElementX/Sources/Services/Room/Members/MemberDetailsProvider.swift @@ -8,12 +8,7 @@ import Foundation -enum MemberDetailsProviderError: Error { - case invalidRoomProxy - case failedRetrievingUserAvatarURL -} - -class MemberDetailsProvider { +class MemberDetailsProvider: MemberDetailsProviderProtocol { private let roomProxy: RoomProxyProtocol? private let processingQueue = DispatchQueue(label: "MemberDetailsProviderProcessingQueue") private var memberAvatars = [String: String]() diff --git a/ElementX/Sources/Services/Room/Members/MemberDetailsProviderProtocol.swift b/ElementX/Sources/Services/Room/Members/MemberDetailsProviderProtocol.swift new file mode 100644 index 000000000..3fb2c81f5 --- /dev/null +++ b/ElementX/Sources/Services/Room/Members/MemberDetailsProviderProtocol.swift @@ -0,0 +1,19 @@ +// +// MemberDetailsProviderProtocol.swift +// ElementX +// +// Created by Stefan Ceriu on 18/03/2022. +// Copyright © 2022 Element. All rights reserved. +// + +import Foundation + +enum MemberDetailsProviderError: Error { + case invalidRoomProxy + case failedRetrievingUserAvatarURL +} + +protocol MemberDetailsProviderProtocol { + func avatarURLForUserId(_ userId: String) -> String? + func avatarURLForUserId(_ userId: String, completion: @escaping (Result) -> Void) +} diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineController.swift b/ElementX/Sources/Services/Timeline/RoomTimelineController.swift index f51c050e0..6baa6b3dc 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineController.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineController.swift @@ -10,10 +10,10 @@ import Foundation import Combine class RoomTimelineController: RoomTimelineControllerProtocol { - private let timelineProvider: RoomTimelineProvider + private let timelineProvider: RoomTimelineProviderProtocol private let timelineItemFactory: RoomTimelineItemFactory private let mediaProvider: MediaProviderProtocol - private let memberDetailsProvider: MemberDetailsProvider + private let memberDetailsProvider: MemberDetailsProviderProtocol private var cancellables = Set() @@ -21,10 +21,10 @@ class RoomTimelineController: RoomTimelineControllerProtocol { private(set) var timelineItems = [RoomTimelineItemProtocol]() - init(timelineProvider: RoomTimelineProvider, + init(timelineProvider: RoomTimelineProviderProtocol, timelineItemFactory: RoomTimelineItemFactory, mediaProvider: MediaProviderProtocol, - memberDetailsProvider: MemberDetailsProvider) { + memberDetailsProvider: MemberDetailsProviderProtocol) { self.timelineProvider = timelineProvider self.timelineItemFactory = timelineItemFactory self.mediaProvider = mediaProvider diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift index 23b2f984d..9f945f59a 100644 --- a/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProvider.swift @@ -9,15 +9,7 @@ import Foundation import Combine -enum RoomTimelineCallback { - case addedMessage -} - -enum RoomTimelineError: Error { - case generic -} - -class RoomTimelineProvider { +class RoomTimelineProvider: RoomTimelineProviderProtocol { private let roomProxy: RoomProxyProtocol private var cancellables = Set() @@ -51,16 +43,4 @@ class RoomTimelineProvider { } } } - - // This is probably not the right place for this method. We need a RoomMemberProvider or something - func avatarURLForUserId(_ userId: String, completion: @escaping (Result) -> Void) { - self.roomProxy.avatarURLForUserId(userId) { result in - switch result { - case .success(let avatarURL): - completion(.success(avatarURL)) - case .failure: - completion(.failure(.generic)) - } - } - } } diff --git a/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift new file mode 100644 index 000000000..c4dbef939 --- /dev/null +++ b/ElementX/Sources/Services/Timeline/RoomTimelineProviderProtocol.swift @@ -0,0 +1,26 @@ +// +// RoomTimelineProviderProtocol.swift +// ElementX +// +// Created by Stefan Ceriu on 18/03/2022. +// Copyright © 2022 Element. All rights reserved. +// + +import Foundation +import Combine + +enum RoomTimelineCallback { + case addedMessage +} + +enum RoomTimelineError: Error { + case generic +} + +protocol RoomTimelineProviderProtocol { + var callbacks: PassthroughSubject { get } + + var messages: [RoomMessageProtocol] { get } + + func paginateBackwards(_ count: UInt, callback: ((Result<([RoomMessageProtocol]), RoomTimelineError>) -> Void)?) +} diff --git a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift index 590910231..aac9e09b7 100644 --- a/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift +++ b/ElementX/Sources/Services/Timeline/TimelineItems/RoomTimelineItemFactory.swift @@ -11,10 +11,10 @@ import UIKit struct RoomTimelineItemFactory { private let mediaProvider: MediaProviderProtocol - private let memberDetailsProvider: MemberDetailsProvider + private let memberDetailsProvider: MemberDetailsProviderProtocol init(mediaProvider: MediaProviderProtocol, - memberDetailsProvider: MemberDetailsProvider) { + memberDetailsProvider: MemberDetailsProviderProtocol) { self.mediaProvider = mediaProvider self.memberDetailsProvider = memberDetailsProvider }