From bce3b3a3851b556a89ade7f2ef6bea60598946e3 Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:23:06 +0100 Subject: [PATCH] using `roomPreview` API for invited rooms (#3530) * using roomPreview for invited rooms * Update ElementX/Sources/Services/Room/RoomInfoProxy.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * improved code * fix, but requires a SDK PR * update sdk * package resolved * fixed the tests --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> --- ElementX.xcodeproj/project.pbxproj | 10 +-- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Mocks/Generated/GeneratedMocks.swift | 69 +------------------ .../Sources/Mocks/InvitedRoomProxyMock.swift | 1 + .../HomeScreen/HomeScreenViewModel.swift | 2 +- .../JoinRoomScreenViewModel.swift | 2 +- .../Sources/Services/Client/ClientProxy.swift | 7 +- .../Services/Room/InvitedRoomProxy.swift | 34 ++++----- .../Services/Room/KnockedRoomProxy.swift | 7 +- .../Sources/Services/Room/RoomInfoProxy.swift | 22 ++++-- .../Services/Room/RoomProxyProtocol.swift | 4 +- project.yml | 2 +- 12 files changed, 52 insertions(+), 112 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index e58469ce8..5403ca071 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -117,6 +117,7 @@ 1621BF6316FFFEF5AE067C77 /* Avatars.swift in Sources */ = {isa = PBXBuildFile; fileRef = C142248014E08E885E323E56 /* Avatars.swift */; }; 1653275750CE11F5CE94DDFD /* ReadReceiptsSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8063E65441E771200108C558 /* ReadReceiptsSummaryView.swift */; }; 167D00CAA13FAFB822298021 /* MediaProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A81CCC2516D9CF9322DF01 /* MediaProviderTests.swift */; }; + 16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */; }; 16CBD087038DE3815CDA512C /* PollMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D38391154120264910D19528 /* PollMock.swift */; }; 16E4F1B8B9BFE1367F96DDA7 /* CompletionSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 989FC684408B31A677F5538B /* CompletionSuggestionView.swift */; }; 1702981A8085BE4FB0EC001B /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = D33116993D54FADC0C721C1F /* Application.swift */; }; @@ -689,7 +690,6 @@ 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; 914BDF61447C723F104BCE33 /* SessionDirectories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C2067FF58B4996323EB40C /* SessionDirectories.swift */; }; 915B4CDAF220D9AEB4047D45 /* PollInteractionHandlerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 259E5B05BDE6E20C26CF11B4 /* PollInteractionHandlerProtocol.swift */; }; - 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */; }; 91ABC91758A6E4A5FAA2E9C4 /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 314F1C79850BE46E8ABEAFCB /* ReadReceipt.swift */; }; 91C6AC0E9D2B9C0C76CC6AD4 /* RoomDirectorySearchScreenScreenModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3984C93B8E9B10C92DADF9EE /* RoomDirectorySearchScreenScreenModelProtocol.swift */; }; 91D1A46A733EC24C081DD353 /* SessionVerificationRequestDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A1265FAF2C0AF1C30605BE7 /* SessionVerificationRequestDetailsView.swift */; }; @@ -1353,6 +1353,7 @@ 16D09C79746BDCD9173EB3A7 /* RoomDetailsEditScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenModels.swift; sourceTree = ""; }; 1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalyticsClient.swift; sourceTree = ""; }; 1734A445A58ED855B977A0A8 /* TracingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingConfigurationTests.swift; sourceTree = ""; }; + 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; 18486B87745B1811E7FBD3D2 /* AnalyticsPromptScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenModels.swift; sourceTree = ""; }; 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecorationTimelineItemProtocol.swift; sourceTree = ""; }; 18F2958E6D247AE2516BEEE8 /* ClientProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientProxy.swift; sourceTree = ""; }; @@ -1901,7 +1902,6 @@ 90F2F8998E5632668B0AD848 /* RoomTimelineItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemView.swift; sourceTree = ""; }; 913C8E13B8B602C7B6C0C4AE /* PillTextAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillTextAttachmentData.swift; sourceTree = ""; }; 91868EB98818044E6FEBE532 /* NotificationPermissionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionsScreenCoordinator.swift; sourceTree = ""; }; - 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineProxyMock.swift; sourceTree = ""; }; 91C8BD78F7B9247AC57FA1A3 /* RedactedRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineView.swift; sourceTree = ""; }; 91CF6F7D08228D16BA69B63B /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/Localizable.strings"; sourceTree = ""; }; 91FFE1F410969ECB23FE9BB2 /* TimelineItemMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMenu.swift; sourceTree = ""; }; @@ -3028,13 +3028,13 @@ F74532E01B317C56C1BE8FA8 /* RoomTimelineProviderMock.swift */, 4AB29A2D95D3469B5F016655 /* SecureBackupControllerMock.swift */, 248649EBA5BC33DB93698734 /* SessionVerificationControllerProxyMock.swift */, + 17A8AA0DFA06012A9DAB951E /* TimelineProxyMock.swift */, 7893780A1FD6E3F38B3E9049 /* UserIndicatorControllerMock.swift */, AAD01F7FC2BBAC7351948595 /* UserProfile+Mock.swift */, F4469F6AE311BDC439B3A5EC /* UserSessionMock.swift */, 9EB9BA2F30EB8C33226D8FF1 /* UserSessionStoreMock.swift */, B23135B06B044CB811139D2F /* Generated */, E5E545F92D01588360A9BAC5 /* SDK */, - 919BAE482CECA981009F6A5B /* TimelineProxyMock.swift */, ); path = Mocks; sourceTree = ""; @@ -7099,7 +7099,6 @@ 50C90117FE25390BFBD40173 /* RustTracing.swift in Sources */, D43F0503EF2CBC55272538FE /* SDKGeneratedMocks.swift in Sources */, 88CBF1595E39CE697928DE48 /* SFNumberedListView.swift in Sources */, - 919BAE492CECA981009F6A5B /* TimelineProxyMock.swift in Sources */, FB595EC9C00AB32F39034055 /* SceneDelegate.swift in Sources */, 0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */, 0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */, @@ -7222,6 +7221,7 @@ 562EFB9AB62B38830D9AA778 /* TimelineMediaFrame.swift in Sources */, B818580464CFB5400A3EF6AE /* TimelineModels.swift in Sources */, E82E13CC3EB923CCB8F8273C /* TimelineProxy.swift in Sources */, + 16A1F6C703305FCAF4E14EC6 /* TimelineProxyMock.swift in Sources */, 2FEC6652055984389CE1BBEC /* TimelineProxyProtocol.swift in Sources */, 8446C2A7ECEFDA79F622725F /* TimelineReactionsView.swift in Sources */, 4DAEE2468669848B6C9F55B4 /* TimelineReadReceiptsView.swift in Sources */, @@ -8138,7 +8138,7 @@ repositoryURL = "https://github.com/element-hq/matrix-rust-components-swift"; requirement = { kind = exactVersion; - version = 1.0.69; + version = 1.0.70; }; }; 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 8b26c4c61..af01bfc35 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -149,8 +149,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/element-hq/matrix-rust-components-swift", "state" : { - "revision" : "7f6beb6a5aceca7d573c3370ece96cfd8589b94a", - "version" : "1.0.69" + "revision" : "e1651193fa976d2184526a0ca4699535e410d94d", + "version" : "1.0.70" } }, { diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index db4da917b..a8def51e0 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -5831,11 +5831,12 @@ class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol { } } class InvitedRoomProxyMock: InvitedRoomProxyProtocol { - var info: RoomInfoProxy { + var info: BaseRoomInfoProxyProtocol { get { return underlyingInfo } set(value) { underlyingInfo = value } } - var underlyingInfo: RoomInfoProxy! + var underlyingInfo: BaseRoomInfoProxyProtocol! + var inviter: RoomMemberProxyProtocol? var id: String { get { return underlyingId } set(value) { underlyingId = value } @@ -5911,70 +5912,6 @@ class InvitedRoomProxyMock: InvitedRoomProxyProtocol { return rejectInvitationReturnValue } } - //MARK: - acceptInvitation - - var acceptInvitationUnderlyingCallsCount = 0 - var acceptInvitationCallsCount: Int { - get { - if Thread.isMainThread { - return acceptInvitationUnderlyingCallsCount - } else { - var returnValue: Int? = nil - DispatchQueue.main.sync { - returnValue = acceptInvitationUnderlyingCallsCount - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - acceptInvitationUnderlyingCallsCount = newValue - } else { - DispatchQueue.main.sync { - acceptInvitationUnderlyingCallsCount = newValue - } - } - } - } - var acceptInvitationCalled: Bool { - return acceptInvitationCallsCount > 0 - } - - var acceptInvitationUnderlyingReturnValue: Result! - var acceptInvitationReturnValue: Result! { - get { - if Thread.isMainThread { - return acceptInvitationUnderlyingReturnValue - } else { - var returnValue: Result? = nil - DispatchQueue.main.sync { - returnValue = acceptInvitationUnderlyingReturnValue - } - - return returnValue! - } - } - set { - if Thread.isMainThread { - acceptInvitationUnderlyingReturnValue = newValue - } else { - DispatchQueue.main.sync { - acceptInvitationUnderlyingReturnValue = newValue - } - } - } - } - var acceptInvitationClosure: (() async -> Result)? - - func acceptInvitation() async -> Result { - acceptInvitationCallsCount += 1 - if let acceptInvitationClosure = acceptInvitationClosure { - return await acceptInvitationClosure() - } else { - return acceptInvitationReturnValue - } - } } class JoinedRoomProxyMock: JoinedRoomProxyProtocol { var isEncrypted: Bool { diff --git a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift index 66bc9a93f..65c71d8ea 100644 --- a/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift +++ b/ElementX/Sources/Mocks/InvitedRoomProxyMock.swift @@ -23,6 +23,7 @@ extension InvitedRoomProxyMock { convenience init(_ configuration: InvitedRoomProxyMockConfiguration) { self.init() id = configuration.id + inviter = configuration.inviter info = RoomInfoProxy(roomInfo: .init(configuration)) } } diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index 9bd00e2b2..12313779a 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -408,7 +408,7 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol return } - switch await roomProxy.acceptInvitation() { + switch await userSession.clientProxy.joinRoom(roomID, via: []) { case .success: actionsSubject.send(.presentRoom(roomIdentifier: roomID)) analyticsService.trackJoinedRoom(isDM: roomProxy.info.isDirect, diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift index 828d1a28c..631292469 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenViewModel.swift @@ -109,7 +109,7 @@ class JoinRoomScreenViewModel: JoinRoomScreenViewModelType, JoinRoomScreenViewMo case .joined(let joinedRoomProxy): roomPreviewInfo = joinedRoomProxy.infoPublisher.value case .invited(let invitedRoomProxy): - inviter = invitedRoomProxy.info.inviter.flatMap(RoomInviterDetails.init) + inviter = invitedRoomProxy.inviter.map(RoomInviterDetails.init) roomPreviewInfo = invitedRoomProxy.info case .knocked(let knockedRoomProxy): roomPreviewInfo = knockedRoomProxy.info diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index f36ff6d7b..61c0aa488 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -930,16 +930,15 @@ class ClientProxy: ClientProxyProtocol { switch roomListItem.membership() { case .invited: return try await .invited(InvitedRoomProxy(roomListItem: roomListItem, - room: roomListItem.invitedRoom())) + roomPreview: roomListItem.previewRoom(via: []), + ownUserID: userID)) case .knocked: if appSettings.knockingEnabled { return try await .knocked(KnockedRoomProxy(roomListItem: roomListItem, roomPreview: roomListItem.previewRoom(via: []), ownUserID: userID)) - } else { - return try await .invited(InvitedRoomProxy(roomListItem: roomListItem, - room: roomListItem.invitedRoom())) } + return nil case .joined: if roomListItem.isTimelineInitialized() == false { try await roomListItem.initTimeline(eventTypeFilter: eventFilters, internalIdPrefix: nil) diff --git a/ElementX/Sources/Services/Room/InvitedRoomProxy.swift b/ElementX/Sources/Services/Room/InvitedRoomProxy.swift index 4e2be76cc..33bf851da 100644 --- a/ElementX/Sources/Services/Room/InvitedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/InvitedRoomProxy.swift @@ -11,36 +11,28 @@ import UIKit class InvitedRoomProxy: InvitedRoomProxyProtocol { private let roomListItem: RoomListItemProtocol - private let room: RoomProtocol + private let roomPreview: RoomPreviewProtocol + let info: BaseRoomInfoProxyProtocol + let ownUserID: String + let inviter: RoomMemberProxyProtocol? // A room identifier is constant and lazy stops it from being fetched // multiple times over FFI - lazy var id: String = room.id() - - var ownUserID: String { room.ownUserId() } - - let info: RoomInfoProxy - + lazy var id: String = info.id + init(roomListItem: RoomListItemProtocol, - room: RoomProtocol) async throws { + roomPreview: RoomPreviewProtocol, + ownUserID: String) async throws { self.roomListItem = roomListItem - self.room = room - info = try await RoomInfoProxy(roomInfo: room.roomInfo()) - } - - func acceptInvitation() async -> Result { - do { - try await room.join() - return .success(()) - } catch { - MXLog.error("Failed accepting invitation with error: \(error)") - return .failure(.sdkError(error)) - } + self.roomPreview = roomPreview + self.ownUserID = ownUserID + info = try RoomPreviewInfoProxy(roomPreviewInfo: roomPreview.info()) + inviter = await roomPreview.inviter().map(RoomMemberProxy.init) } func rejectInvitation() async -> Result { do { - return try await .success(room.leave()) + return try await .success(roomPreview.leave()) } catch { MXLog.error("Failed rejecting invitiation with error: \(error)") return .failure(.sdkError(error)) diff --git a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift index c2c35de05..00321bf69 100644 --- a/ElementX/Sources/Services/Room/KnockedRoomProxy.swift +++ b/ElementX/Sources/Services/Room/KnockedRoomProxy.swift @@ -13,16 +13,15 @@ class KnockedRoomProxy: KnockedRoomProxyProtocol { private let roomListItem: RoomListItemProtocol private let roomPreview: RoomPreviewProtocol let info: BaseRoomInfoProxyProtocol + let ownUserID: String // A room identifier is constant and lazy stops it from being fetched // multiple times over FFI lazy var id = info.id - - let ownUserID: String - + init(roomListItem: RoomListItemProtocol, roomPreview: RoomPreviewProtocol, - ownUserID: String) async throws { + ownUserID: String) throws { self.roomListItem = roomListItem self.roomPreview = roomPreview self.ownUserID = ownUserID diff --git a/ElementX/Sources/Services/Room/RoomInfoProxy.swift b/ElementX/Sources/Services/Room/RoomInfoProxy.swift index 7fa274ff8..9cd290228 100644 --- a/ElementX/Sources/Services/Room/RoomInfoProxy.swift +++ b/ElementX/Sources/Services/Room/RoomInfoProxy.swift @@ -16,6 +16,8 @@ protocol BaseRoomInfoProxyProtocol { var canonicalAlias: String? { get } var avatarURL: URL? { get } var activeMembersCount: Int { get } + var isDirect: Bool { get } + var isSpace: Bool { get } } struct RoomInfoProxy: BaseRoomInfoProxyProtocol { @@ -70,12 +72,22 @@ struct RoomPreviewInfoProxy: BaseRoomInfoProxyProtocol { var id: String { roomPreviewInfo.roomId } var displayName: String? { roomPreviewInfo.name } - var avatar: RoomAvatar { - .room(id: id, name: displayName, avatarURL: avatarURL) - } - + var heroes: [RoomHero] { roomPreviewInfo.heroes ?? [] } var topic: String? { roomPreviewInfo.topic } var canonicalAlias: String? { roomPreviewInfo.canonicalAlias } var avatarURL: URL? { roomPreviewInfo.avatarUrl.flatMap(URL.init) } - var activeMembersCount: Int { Int(roomPreviewInfo.numJoinedMembers) } + var isDirect: Bool { roomPreviewInfo.isDirect ?? false } + var isSpace: Bool { roomPreviewInfo.roomType == .space } + var activeMembersCount: Int { Int(roomPreviewInfo.numActiveMembers ?? roomPreviewInfo.numJoinedMembers) } + + /// The room's avatar info for use in a ``RoomAvatarImage``. + var avatar: RoomAvatar { + if isDirect, avatarURL == nil { + if heroes.count == 1 { + return .heroes(heroes.map(UserProfileProxy.init)) + } + } + + return .room(id: id, name: displayName, avatarURL: avatarURL) + } } diff --git a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift index 550fcc0ea..a19a735e7 100644 --- a/ElementX/Sources/Services/Room/RoomProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomProxyProtocol.swift @@ -33,9 +33,9 @@ protocol RoomProxyProtocol { // sourcery: AutoMockable protocol InvitedRoomProxyProtocol: RoomProxyProtocol { - var info: RoomInfoProxy { get } + var info: BaseRoomInfoProxyProtocol { get } + var inviter: RoomMemberProxyProtocol? { get } func rejectInvitation() async -> Result - func acceptInvitation() async -> Result } // sourcery: AutoMockable diff --git a/project.yml b/project.yml index d80b04657..1f07f1159 100644 --- a/project.yml +++ b/project.yml @@ -61,7 +61,7 @@ packages: # Element/Matrix dependencies MatrixRustSDK: url: https://github.com/element-hq/matrix-rust-components-swift - exactVersion: 1.0.69 + exactVersion: 1.0.70 # path: ../matrix-rust-sdk Compound: url: https://github.com/element-hq/compound-ios