diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 3714f2594..05cfd088e 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ 0DC815CA24E1BD7F408F37D3 /* CollapsibleTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7C4EA55DA62F9D0F984A2AE /* CollapsibleTimelineItem.swift */; }; 0DFCEAB8C82B151718F71D49 /* FrequentlyUsedEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A2074C0449B83D5858BD2D7 /* FrequentlyUsedEmoji.swift */; }; 0E08BB72B2258652CF501A8B /* Version in Frameworks */ = {isa = PBXBuildFile; productRef = 2B9ACE4FCACB5A8812154424 /* Version */; }; + 0E6B97E4F4DAC3E5B64B215F /* UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66653C5417592A727B549533 /* UserProfile.swift */; }; 0E8C480700870BB34A2A360F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4003BC24B24C9E63D3304177 /* DeviceKit */; }; 0EA6537A07E2DC882AEA5962 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 187853A7E643995EE49FAD43 /* Localizable.stringsdict */; }; 0EBF0A411E1C46D4BFA2B087 /* ManageAuthorizedSpacesScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB9CD3A0A39BC063438E12D4 /* ManageAuthorizedSpacesScreenCoordinator.swift */; }; @@ -1353,7 +1354,6 @@ E1C67E5D9E22135A8FEBBD60 /* StackedAvatarsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8558D41DD4B553A752C868A /* StackedAvatarsView.swift */; }; E1DE8A5422643F759385290F /* AppSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD5523BDEDB247E29228476 /* AppSettings.swift */; }; E1DF24D085572A55C9758A2D /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E89E530A8E92EC44301CA1 /* Bundle.swift */; }; - E21FE4C5B614F311C0955859 /* UserProfileProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */; }; E26E702F325F0AA49B8A5CFD /* RoomPowerLevelsProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E944F717FC10A428D027074D /* RoomPowerLevelsProxyMock.swift */; }; E27C4D1A1F8BB77CA790B403 /* InviteUsersScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A861DA5932B128FE1DCB5CE2 /* InviteUsersScreenCoordinator.swift */; }; E290C78E7F09F47FD2662986 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40C19719687984FD9478FBE /* Task.swift */; }; @@ -2114,7 +2114,6 @@ 510E89B989477E5EE8E503C0 /* PinnedEventsTimelineScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineScreenViewModelProtocol.swift; sourceTree = ""; }; 514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelTests.swift; sourceTree = ""; }; 51C2BCE0BC1FC69C1B36E688 /* BugReportScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BugReportScreenModels.swift; sourceTree = ""; }; - 51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileProxy.swift; sourceTree = ""; }; 51F14C0F5FD4A1814D5527E6 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = fa.lproj/InfoPlist.strings; sourceTree = ""; }; 52135BD9E0E7A091688F627A /* MessageForwardingScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageForwardingScreenModels.swift; sourceTree = ""; }; 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreen.swift; sourceTree = ""; }; @@ -2222,6 +2221,7 @@ 664ABD745A746C45CB842158 /* CallInviteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInviteRoomTimelineView.swift; sourceTree = ""; }; 664D3C710B4A12CE4E623645 /* DeactivateAccountScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeactivateAccountScreenModels.swift; sourceTree = ""; }; 6654859746B0BE9611459391 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = cs; path = cs.lproj/Localizable.stringsdict; sourceTree = ""; }; + 66653C5417592A727B549533 /* UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfile.swift; sourceTree = ""; }; 667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = ""; }; 6695C64F066628411EAD21E9 /* RoomPreviewProxyMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPreviewProxyMock.swift; sourceTree = ""; }; 669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = ""; }; @@ -6740,7 +6740,7 @@ 7F615A00DB223FF3280204D2 /* UserDiscoveryServiceProtocol.swift */, 964093C7CA8823CAB7FFD88E /* UserIdentityProxy.swift */, 0F793C422BDACE0C60C774F4 /* UserIdentityProxyProtocol.swift */, - 51C454AE59914B551A6D02C0 /* UserProfileProxy.swift */, + 66653C5417592A727B549533 /* UserProfile.swift */, ); path = Users; sourceTree = ""; @@ -9182,8 +9182,8 @@ A8DB299C5C891EDAE74A22F4 /* UserLocationCell.swift in Sources */, E3291AD16D7A5CB14781819C /* UserNotificationCenterProtocol.swift in Sources */, 80DEA2A4B20F9E279EAE6B2B /* UserProfile+Mock.swift in Sources */, + 0E6B97E4F4DAC3E5B64B215F /* UserProfile.swift in Sources */, ED90A59F068FD0CA27E602ED /* UserProfileListRow.swift in Sources */, - E21FE4C5B614F311C0955859 /* UserProfileProxy.swift in Sources */, 1A3B073568D1DC8F76F1F3A0 /* UserProfileScreen.swift in Sources */, 6AEB650311F694A5702255C9 /* UserProfileScreenCoordinator.swift in Sources */, D4CB979EB4FE26AAD9F9A72B /* UserProfileScreenModels.swift in Sources */, diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index af8c4b4e1..776351069 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -64,7 +64,7 @@ enum InviteUsersFlow: Hashable { /// Invite people into the current room. case existingRoom /// Start a new room with the given invitee pre-selected and mandatory. - case newRoom(mandatoryInvitee: UserProfileProxy) + case newRoom(mandatoryInvitee: UserProfile) } // swiftlint:disable:next type_body_length diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index e0f3f9d7f..bc51a073f 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -405,7 +405,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { MXLog.info("Received session verification request") - if details.senderProfile.userID == userSession.clientProxy.userID { + if details.senderProfile.id == userSession.clientProxy.userID { presentSessionVerificationScreen(flow: .deviceResponder(requestDetails: details)) } else { presentSessionVerificationScreen(flow: .userResponder(requestDetails: details)) diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 59d628e07..d843851f1 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -3533,14 +3533,14 @@ nonisolated class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { } private let profileForReturnValueLock = NSLock() - private nonisolated(unsafe) var profileForUnderlyingReturnValue: Result! - var profileForReturnValue: Result! { + private nonisolated(unsafe) var profileForUnderlyingReturnValue: Result! + var profileForReturnValue: Result! { get { profileForReturnValueLock.withLock { profileForUnderlyingReturnValue } } set { profileForReturnValueLock.withLock { profileForUnderlyingReturnValue = newValue } } } - nonisolated(unsafe) var profileForClosure: ((String) async -> Result)? + nonisolated(unsafe) var profileForClosure: ((String) async -> Result)? - @concurrent func profile(for userID: String) async -> Result { + @concurrent func profile(for userID: String) async -> Result { profileForCallsCountLock.withLock { profileForUnderlyingCallsCount += 1 } profileForReceivedUserID = userID profileForReceivedInvocationsLock.withLock { profileForUnderlyingReceivedInvocations.append(userID) } @@ -3972,14 +3972,14 @@ nonisolated class ClientProxyMock: ClientProxyProtocol, @unchecked Sendable { } private let recentConversationCounterpartsReturnValueLock = NSLock() - private nonisolated(unsafe) var recentConversationCounterpartsUnderlyingReturnValue: [UserProfileProxy]! - var recentConversationCounterpartsReturnValue: [UserProfileProxy]! { + private nonisolated(unsafe) var recentConversationCounterpartsUnderlyingReturnValue: [UserProfile]! + var recentConversationCounterpartsReturnValue: [UserProfile]! { get { recentConversationCounterpartsReturnValueLock.withLock { recentConversationCounterpartsUnderlyingReturnValue } } set { recentConversationCounterpartsReturnValueLock.withLock { recentConversationCounterpartsUnderlyingReturnValue = newValue } } } - nonisolated(unsafe) var recentConversationCounterpartsClosure: (() async -> [UserProfileProxy])? + nonisolated(unsafe) var recentConversationCounterpartsClosure: (() async -> [UserProfile])? - @concurrent func recentConversationCounterparts() async -> [UserProfileProxy] { + @concurrent func recentConversationCounterparts() async -> [UserProfile] { recentConversationCounterpartsCallsCountLock.withLock { recentConversationCounterpartsUnderlyingCallsCount += 1 } if let recentConversationCounterpartsClosure = recentConversationCounterpartsClosure { return await recentConversationCounterpartsClosure() @@ -14057,14 +14057,14 @@ nonisolated class UserDiscoveryServiceMock: UserDiscoveryServiceProtocol, @unche } private let searchProfilesWithReturnValueLock = NSLock() - private nonisolated(unsafe) var searchProfilesWithUnderlyingReturnValue: Result<[UserProfileProxy], UserDiscoveryErrorType>! - var searchProfilesWithReturnValue: Result<[UserProfileProxy], UserDiscoveryErrorType>! { + private nonisolated(unsafe) var searchProfilesWithUnderlyingReturnValue: Result<[UserProfile], UserDiscoveryErrorType>! + var searchProfilesWithReturnValue: Result<[UserProfile], UserDiscoveryErrorType>! { get { searchProfilesWithReturnValueLock.withLock { searchProfilesWithUnderlyingReturnValue } } set { searchProfilesWithReturnValueLock.withLock { searchProfilesWithUnderlyingReturnValue = newValue } } } - nonisolated(unsafe) var searchProfilesWithClosure: ((String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType>)? + nonisolated(unsafe) var searchProfilesWithClosure: ((String) async -> Result<[UserProfile], UserDiscoveryErrorType>)? - @concurrent func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> { + @concurrent func searchProfiles(with searchQuery: String) async -> Result<[UserProfile], UserDiscoveryErrorType> { searchProfilesWithCallsCountLock.withLock { searchProfilesWithUnderlyingCallsCount += 1 } searchProfilesWithReceivedSearchQuery = searchQuery searchProfilesWithReceivedInvocationsLock.withLock { searchProfilesWithUnderlyingReceivedInvocations.append(searchQuery) } diff --git a/ElementX/Sources/Mocks/UserProfile+Mock.swift b/ElementX/Sources/Mocks/UserProfile+Mock.swift index b2650e980..71f4a953d 100644 --- a/ElementX/Sources/Mocks/UserProfile+Mock.swift +++ b/ElementX/Sources/Mocks/UserProfile+Mock.swift @@ -8,29 +8,29 @@ import Foundation -extension UserProfileProxy { +extension UserProfile { /// Mocks - static var mockAlice: UserProfileProxy { + static var mockAlice: UserProfile { .init(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: "mxc://matrix.org/UcCimidcvpFvWkPzvjXMQPHA") } - static var mockBob: UserProfileProxy { + static var mockBob: UserProfile { .init(userID: "@bob:matrix.org", displayName: "Bob", avatarURL: nil) } - static var mockBobby: UserProfileProxy { + static var mockBobby: UserProfile { .init(userID: "@bobby:matrix.org", displayName: "Bobby", avatarURL: nil) } - static var mockCharlie: UserProfileProxy { + static var mockCharlie: UserProfile { .init(userID: "@charlie:matrix.org", displayName: "Charlie", avatarURL: nil) } - static var mockDan: UserProfileProxy { + static var mockDan: UserProfile { .init(userID: "@dan:matrix.org", displayName: "Dan", avatarURL: .mockMXCUserAvatar) } - static var mockVerbose: UserProfileProxy { + static var mockVerbose: UserProfile { .init(userID: "@charlie:matrix.org", displayName: "Charlie is the best display name", avatarURL: nil) } } diff --git a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift index 04a9c7198..a4e6b39fc 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/AvatarHeaderView.swift @@ -13,7 +13,7 @@ import SwiftUI struct AvatarHeaderView: View { private enum AvatarInfo { case room(RoomAvatar) - case user(UserProfileProxy) + case user(UserProfile) } private enum Badge: Hashable { @@ -44,7 +44,7 @@ struct AvatarHeaderView: View { if let roomAlias = room.canonicalAlias { subtitle = roomAlias } else if room.isDirect, case let .heroes(heroes) = room.avatar, heroes.count == 1 { - subtitle = heroes[0].userID + subtitle = heroes[0].id } else { subtitle = nil } @@ -70,10 +70,10 @@ struct AvatarHeaderView: View { mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { - let dmRecipientProfile = UserProfileProxy(member: dmRecipient) - avatarInfo = .room(.heroes([dmRecipientProfile, UserProfileProxy(member: accountOwner)])) - title = dmRecipientProfile.displayName ?? dmRecipientProfile.userID - subtitle = dmRecipientProfile.displayName == nil ? nil : dmRecipientProfile.userID + let dmRecipientProfile = UserProfile(member: dmRecipient) + avatarInfo = .room(.heroes([dmRecipientProfile, UserProfile(member: accountOwner)])) + title = dmRecipientProfile.displayName ?? dmRecipientProfile.id + subtitle = dmRecipientProfile.displayName == nil ? nil : dmRecipientProfile.id avatarSize = .user(on: .dmDetails) self.mediaProvider = mediaProvider @@ -89,7 +89,7 @@ struct AvatarHeaderView: View { mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { - let profile = UserProfileProxy(member: member) + let profile = UserProfile(member: member) self.init(user: profile, isVerified: isVerified, @@ -99,15 +99,15 @@ struct AvatarHeaderView: View { footer: footer) } - init(user: UserProfileProxy, + init(user: UserProfile, isVerified: Bool, avatarSize: Avatars.Size, mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { avatarInfo = .user(user) - title = user.displayName ?? user.userID - subtitle = user.displayName == nil ? nil : user.userID + title = user.displayName ?? user.id + subtitle = user.displayName == nil ? nil : user.id self.avatarSize = avatarSize self.mediaProvider = mediaProvider @@ -123,7 +123,7 @@ struct AvatarHeaderView: View { mediaProvider: MediaProviderProtocol? = nil, onAvatarTap: ((URL) -> Void)? = nil, @ViewBuilder footer: @escaping () -> Footer) { - let profile = UserProfileProxy(sender: sender) + let profile = UserProfile(sender: sender) self.init(user: profile, isVerified: false, @@ -180,8 +180,8 @@ struct AvatarHeaderView: View { switch avatarInfo { case .room(let roomAvatar): return roomAvatar.hasURL ? L10n.a11yViewAvatar : L10n.a11yAvatar - case .user(let userProfileProxy): - return userProfileProxy.avatarURL != nil ? L10n.a11yViewAvatar : L10n.a11yAvatar + case .user(let userProfile): + return userProfile.avatarURL != nil ? L10n.a11yViewAvatar : L10n.a11yAvatar } } @@ -198,7 +198,7 @@ struct AvatarHeaderView: View { case .user(let userProfile): LoadableAvatarImage(url: userProfile.avatarURL, name: userProfile.displayName, - contentID: userProfile.userID, + contentID: userProfile.id, avatarSize: avatarSize, mediaProvider: mediaProvider, onTap: onAvatarTap) diff --git a/ElementX/Sources/Other/SwiftUI/Views/JoinedMembersBadgeView.swift b/ElementX/Sources/Other/SwiftUI/Views/JoinedMembersBadgeView.swift index 6f5d0e7cc..b8f8e6e48 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/JoinedMembersBadgeView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/JoinedMembersBadgeView.swift @@ -10,7 +10,7 @@ import Compound import SwiftUI struct JoinedMembersBadgeView: View { - let heroes: [UserProfileProxy] + let heroes: [UserProfile] var shouldHideAvatars = false let joinedCount: Int @@ -46,7 +46,7 @@ struct JoinedMembersBadgeView: View { ForEach(heroes.prefix(3).reversed()) { hero in LoadableAvatarImage(url: shouldHideAvatars ? nil : hero.avatarURL, name: hero.displayName, - contentID: hero.userID, + contentID: hero.id, avatarSize: .user(on: .spaceHeader), mediaProvider: mediaProvider) .mask { diff --git a/ElementX/Sources/Other/SwiftUI/Views/LocationMarkerView.swift b/ElementX/Sources/Other/SwiftUI/Views/LocationMarkerView.swift index f64acc6e9..ed9271b78 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/LocationMarkerView.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/LocationMarkerView.swift @@ -69,7 +69,7 @@ struct LocationMarkerView: View { if let userProfile = kind.userProfile { LoadableAvatarImage(url: userProfile.avatarURL, name: userProfile.displayName, - contentID: userProfile.userID, + contentID: userProfile.id, avatarSize: .user(on: .map), mediaProvider: mediaProvider) .overlay { diff --git a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift index a4ec63bf4..784662dce 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/RoomAvatarImage.swift @@ -13,7 +13,7 @@ enum RoomAvatar: Equatable { /// An avatar generated from a Room's details. case room(id: String, name: String?, avatarURL: URL?) /// An avatar generated from a collection of room heroes. - case heroes([UserProfileProxy]) + case heroes([UserProfile]) /// An avatar generated from a Space's details. case space(id: String, name: String?, avatarURL: URL?) /// A static avatar for a tombstoned room. @@ -24,7 +24,7 @@ enum RoomAvatar: Equatable { case let .room(id, name, _): .room(id: id, name: name, avatarURL: nil) case let .heroes(users): - .heroes(users.map { .init(userID: $0.userID, displayName: $0.displayName, avatarURL: nil) }) + .heroes(users.map { .init(userID: $0.id, displayName: $0.displayName, avatarURL: nil) }) case .space(let id, let name, _): .space(id: id, name: name, avatarURL: nil) case .tombstoned: @@ -76,7 +76,7 @@ struct RoomAvatarImage: View { ZStack { LoadableAvatarImage(url: users[0].avatarURL, name: users[0].displayName, - contentID: users[0].userID, + contentID: users[0].id, avatarSize: avatarSize, mediaProvider: mediaProvider, onTap: onAvatarTap) @@ -84,7 +84,7 @@ struct RoomAvatarImage: View { LoadableAvatarImage(url: users[1].avatarURL, name: users[1].displayName, - contentID: users[1].userID, + contentID: users[1].id, avatarSize: avatarSize, mediaProvider: mediaProvider, onTap: onAvatarTap) @@ -107,7 +107,7 @@ struct RoomAvatarImage: View { } else { LoadableAvatarImage(url: users[0].avatarURL, name: users[0].displayName, - contentID: users[0].userID, + contentID: users[0].id, avatarSize: avatarSize, mediaProvider: mediaProvider, onTap: onAvatarTap) diff --git a/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift b/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift index 3aff52387..c240d0ce9 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/UserProfileListRow.swift @@ -11,7 +11,7 @@ import MatrixRustSDK import SwiftUI struct UserProfileListRow: View { - let user: UserProfileProxy + let user: UserProfile let membership: MembershipState? let mediaProvider: MediaProviderProtocol? @@ -27,14 +27,14 @@ struct UserProfileListRow: View { if let membershipText = membership?.localizedDescription { return membershipText } else if user.displayName != nil { - return user.userID + return user.id } else { return nil } } var body: some View { - ListRow(label: .avatar(title: user.displayName ?? user.userID, + ListRow(label: .avatar(title: user.displayName ?? user.id, description: subtitle, icon: avatar, role: isUnknownProfile ? .error : nil), @@ -44,7 +44,7 @@ struct UserProfileListRow: View { var avatar: LoadableAvatarImage { LoadableAvatarImage(url: user.avatarURL, name: user.displayName, - contentID: user.userID, + contentID: user.id, avatarSize: .user(on: .startChat), mediaProvider: mediaProvider) } diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift index b09ea101d..2b1412bb7 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenModels.swift @@ -9,7 +9,7 @@ import Foundation struct BlockedUsersScreenViewState: BindableState { - var blockedUsers: [UserProfileProxy] + var blockedUsers: [UserProfile] var processingUserID: String? var bindings = BlockedUsersScreenViewStateBindings() @@ -20,7 +20,7 @@ struct BlockedUsersScreenViewStateBindings { } enum BlockedUsersScreenViewAction { - case unblockUser(UserProfileProxy) + case unblockUser(UserProfile) } enum BlockedUsersScreenViewStateAlertType: Hashable { diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift index b59c5db0d..cdd66f6ea 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/BlockedUsersScreenViewModel.swift @@ -23,7 +23,7 @@ class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsers clientProxy = userSession.clientProxy self.userIndicatorController = userIndicatorController - let ignoredUsers = clientProxy.ignoredUsersPublisher.value?.map { UserProfileProxy(userID: $0) } + let ignoredUsers = clientProxy.ignoredUsersPublisher.value?.map { UserProfile(userID: $0) } super.init(initialViewState: BlockedUsersScreenViewState(blockedUsers: ignoredUsers ?? []), mediaProvider: userSession.mediaProvider) @@ -64,16 +64,16 @@ class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsers defer { hideLoadingIndicator() } if hideProfiles { - state.blockedUsers = blockedUsers.map { UserProfileProxy(userID: $0) } + state.blockedUsers = blockedUsers.map { UserProfile(userID: $0) } } else { - state.blockedUsers = await withTaskGroup(of: UserProfileProxy.self) { group in + state.blockedUsers = await withTaskGroup(of: UserProfile.self) { group in for userID in blockedUsers { group.addTask { await self.profile(for: userID) } } - var profiles = [UserProfileProxy]() + var profiles = [UserProfile]() for await profile in group { profiles.append(profile) } @@ -84,19 +84,19 @@ class BlockedUsersScreenViewModel: BlockedUsersScreenViewModelType, BlockedUsers /// The client proxy isn't Sendable, fetch through this helper so that it /// never leaves the main actor when running calls in parallel. - private func profile(for userID: String) async -> UserProfileProxy { + private func profile(for userID: String) async -> UserProfile { switch await clientProxy.profile(for: userID) { case .success(let profile): profile - case .failure: UserProfileProxy(userID: userID) + case .failure: UserProfile(userID: userID) } } - private func unblockUser(_ user: UserProfileProxy) { + private func unblockUser(_ user: UserProfile) { showLoadingIndicator() - state.processingUserID = user.userID + state.processingUserID = user.id Task { - if case .failure = await clientProxy.unignoreUser(user.userID) { + if case .failure = await clientProxy.unignoreUser(user.id) { state.bindings.alertInfo = .init(id: .error) } diff --git a/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift b/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift index 52b6d2267..a22ac0409 100644 --- a/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift +++ b/ElementX/Sources/Screens/BlockedUsersScreen/View/BlockedUsersScreen.swift @@ -33,20 +33,20 @@ struct BlockedUsersScreen: View { } else { Form { ForEach(context.viewState.blockedUsers, id: \.self) { user in - ListRow(label: .avatar(title: user.displayName ?? user.userID, - description: user.displayName != nil ? user.userID : nil, + ListRow(label: .avatar(title: user.displayName ?? user.id, + description: user.displayName != nil ? user.id : nil, icon: avatar(for: user)), - details: .isWaiting(context.viewState.processingUserID == user.userID), + details: .isWaiting(context.viewState.processingUserID == user.id), kind: .button { context.send(viewAction: .unblockUser(user)) }) } } } } - private func avatar(for user: UserProfileProxy) -> some View { + private func avatar(for user: UserProfile) -> some View { LoadableAvatarImage(url: user.avatarURL, name: user.displayName, - contentID: user.userID, + contentID: user.id, avatarSize: .user(on: .blockedUsers), mediaProvider: context.mediaProvider) .accessibilityHidden(true) diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift index adcd80f30..81405188b 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenModels.swift @@ -20,7 +20,7 @@ enum InviteUsersScreenViewModelAction { } enum InviteUsersScreenRoomType { - case draft(mandatoryInvitees: [UserProfileProxy]) + case draft(mandatoryInvitees: [UserProfile]) case existingRoom(roomProxy: JoinedRoomProxyProtocol) } @@ -29,10 +29,10 @@ struct InviteUsersScreenViewState: BindableState { var usersSection: UserDiscoverySection = .init(type: .suggestions, users: []) - var selectedUsers: [UserProfileProxy] = [] - var mandatoryInvitees: [UserProfileProxy] = [] + var selectedUsers: [UserProfile] = [] + var mandatoryInvitees: [UserProfile] = [] var membershipState: [String: MembershipState] = .init() - var usersToConfirm: [UserProfileProxy] = [] + var usersToConfirm: [UserProfile] = [] var isSearching = false @@ -44,11 +44,11 @@ struct InviteUsersScreenViewState: BindableState { selectedUsers.contains { !isInviteeMandatory($0) } } - func isUserSelected(_ user: UserProfileProxy) -> Bool { - isUserDisabled(user) || selectedUsers.contains { $0.userID == user.userID } + func isUserSelected(_ user: UserProfile) -> Bool { + isUserDisabled(user) || selectedUsers.contains { $0.id == user.id } } - func isUserDisabled(_ user: UserProfileProxy) -> Bool { + func isUserDisabled(_ user: UserProfile) -> Bool { if isInviteeMandatory(user) { return true } @@ -56,12 +56,12 @@ struct InviteUsersScreenViewState: BindableState { return membershipState == .invite || membershipState == .join } - func isInviteeMandatory(_ user: UserProfileProxy) -> Bool { - mandatoryInvitees.contains { $0.userID == user.userID } + func isInviteeMandatory(_ user: UserProfile) -> Bool { + mandatoryInvitees.contains { $0.id == user.id } } - func membershipState(_ user: UserProfileProxy) -> MembershipState? { - membershipState[user.userID] + func membershipState(_ user: UserProfile) -> MembershipState? { + membershipState[user.id] } let isSkippable: Bool @@ -83,5 +83,5 @@ enum InviteUsersScreenViewAction { case proceed case removeUnknownUsers case confirmUnknownUsers - case toggleUser(UserProfileProxy) + case toggleUser(UserProfile) } diff --git a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift index 2a441e2b6..5fe05d688 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/InviteUsersScreenViewModel.swift @@ -19,7 +19,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr private let userIndicatorController: UserIndicatorControllerProtocol private let appSettings: AppSettings - private var suggestedUsers = [UserProfileProxy]() + private var suggestedUsers = [UserProfile]() private let actionsSubject: PassthroughSubject = .init() var actions: AnyPublisher { @@ -38,7 +38,7 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr self.userIndicatorController = userIndicatorController self.appSettings = appSettings - let mandatoryInvitees: [UserProfileProxy] = if case .draft(let invitees) = roomType { + let mandatoryInvitees: [UserProfile] = if case .draft(let invitees) = roomType { invitees } else { [] @@ -70,12 +70,12 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr case .proceed: switch roomType { case .draft: - createDraftRoom(mandatoryUserIDs: state.selectedUsers.map(\.userID)) + createDraftRoom(mandatoryUserIDs: state.selectedUsers.map(\.id)) case .existingRoom(let roomProxy): guard roomProxy.details.historySharingState != RoomHistorySharingState.hidden, !state.usersToConfirm.isEmpty, !state.isSkippable else { - inviteUsers(state.selectedUsers.map(\.userID), roomProxy: roomProxy) + inviteUsers(state.selectedUsers.map(\.id), roomProxy: roomProxy) return } state.bindings.presentConfirmationDialog = true @@ -83,14 +83,14 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr case .removeUnknownUsers: state.bindings.presentConfirmationDialog = false state.selectedUsers.removeAll { user in - state.usersToConfirm.contains { $0.userID == user.userID } + state.usersToConfirm.contains { $0.id == user.id } } state.usersToConfirm = [] case .confirmUnknownUsers: state.bindings.presentConfirmationDialog = false state.usersToConfirm = [] if case .existingRoom(let roomProxy) = roomType { - inviteUsers(state.selectedUsers.map(\.userID), roomProxy: roomProxy) + inviteUsers(state.selectedUsers.map(\.id), roomProxy: roomProxy) } case .toggleUser(let user): toggleUser(user) @@ -99,16 +99,16 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr // MARK: - Private - private func toggleUser(_ user: UserProfileProxy) { + private func toggleUser(_ user: UserProfile) { guard !state.isInviteeMandatory(user) else { return } if state.selectedUsers.contains(user) { - state.selectedUsers.removeAll { $0.userID == user.userID } + state.selectedUsers.removeAll { $0.id == user.id } } else { state.selectedUsers.append(user) - withElementAnimation(.easeInOut) { state.bindings.selectedUsersPosition = user.userID } + withElementAnimation(.easeInOut) { state.bindings.selectedUsersPosition = user.id } Task { - let identityUnknown = if case .success(let identity) = await self.clientProxy.userIdentity(for: user.userID, fallBackToServer: false) { + let identityUnknown = if case .success(let identity) = await self.clientProxy.userIdentity(for: user.id, fallBackToServer: false) { identity == nil } else { true diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersConfirmationSheetView.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersConfirmationSheetView.swift index 5472f69db..4f6ed2570 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersConfirmationSheetView.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersConfirmationSheetView.swift @@ -12,7 +12,7 @@ struct InviteUsersConfirmationSheetView: View { @ObservedObject var context: InviteUsersScreenViewModel.Context /// The users whose identities we wish the user to confirm. - var users: [UserProfileProxy] + var users: [UserProfile] var body: some View { FullscreenDialog(topPadding: 24, horizontalPadding: 24) { @@ -22,7 +22,7 @@ struct InviteUsersConfirmationSheetView: View { icon: \.userAddSolid, iconStyle: .defaultSolid) VStack(spacing: 0) { - ForEach(users, id: \.userID) { user in + ForEach(users, id: \.id) { user in UserProfileListRow(user: user, membership: nil, mediaProvider: context.mediaProvider, diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift index 8e46a6582..be84fe34a 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreen.swift @@ -83,7 +83,7 @@ struct InviteUsersScreen: View { private var usersSection: some View { if !context.viewState.usersSection.users.isEmpty { Section { - ForEach(context.viewState.usersSection.users, id: \.userID) { user in + ForEach(context.viewState.usersSection.users, id: \.id) { user in UserProfileListRow(user: user, membership: context.viewState.membershipState(user), mediaProvider: context.mediaProvider, @@ -109,7 +109,7 @@ struct InviteUsersScreen: View { private var selectedUsersSection: some View { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 8) { - ForEach(context.viewState.selectedUsers, id: \.userID) { user in + ForEach(context.viewState.selectedUsers, id: \.id) { user in InviteUsersScreenSelectedItem(user: user, mediaProvider: context.mediaProvider, isLocked: context.viewState.isInviteeMandatory(user)) { @@ -150,7 +150,7 @@ struct InviteUsersScreen: View { } } - private func deselect(_ user: UserProfileProxy) { + private func deselect(_ user: UserProfile) { context.send(viewAction: .toggleUser(user)) } } diff --git a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift index 963a19430..9174b3559 100644 --- a/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift +++ b/ElementX/Sources/Screens/InviteUsersScreen/View/InviteUsersScreenSelectedItem.swift @@ -10,7 +10,7 @@ import Compound import SwiftUI struct InviteUsersScreenSelectedItem: View { - let user: UserProfileProxy + let user: UserProfile let mediaProvider: MediaProviderProtocol? var isLocked = false let dismissAction: () -> Void @@ -20,7 +20,7 @@ struct InviteUsersScreenSelectedItem: View { avatar .accessibilityHidden(true) - Text(user.displayName ?? user.userID) + Text(user.displayName ?? user.id) .font(.compound.bodySM) .foregroundColor(.compound.textSecondary) .lineLimit(1) @@ -39,7 +39,7 @@ struct InviteUsersScreenSelectedItem: View { var avatar: some View { let avatarImage = LoadableAvatarImage(url: user.avatarURL, name: user.displayName, - contentID: user.userID, + contentID: user.id, avatarSize: .user(on: .inviteUsers), mediaProvider: mediaProvider) if isLocked { @@ -58,12 +58,12 @@ struct InviteUsersScreenSelectedItem: View { } struct InviteUsersScreenSelectedItem_Previews: PreviewProvider, TestablePreview { - static let people: [UserProfileProxy] = [.mockAlice, .mockVerbose] + static let people: [UserProfile] = [.mockAlice, .mockVerbose] static var previews: some View { ScrollView(.horizontal) { HStack(spacing: 8) { - ForEach(people, id: \.userID) { user in + ForEach(people, id: \.id) { user in InviteUsersScreenSelectedItem(user: user, mediaProvider: MediaProviderMock(.init())) { } .frame(width: 80) } diff --git a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift index 1ee0ba951..cca26f2bb 100644 --- a/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift +++ b/ElementX/Sources/Screens/JoinRoomScreen/JoinRoomScreenModels.swift @@ -43,7 +43,7 @@ struct JoinRoomScreenRoomDetails { let canonicalAlias: String? let avatar: RoomAvatar? let memberCount: Int? - let heroes: [UserProfileProxy] + let heroes: [UserProfile] let inviter: RoomInviterDetails? let isDirect: Bool? diff --git a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift index 9a1660e29..6a5c6aa36 100644 --- a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift +++ b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenModels.swift @@ -52,7 +52,7 @@ struct LocationSharingScreenViewState: BindableState { self.mapURLBuilder = mapURLBuilder self.ownUserID = ownUserID - let initialProfile: UserProfileProxy = switch interactionMode { + let initialProfile: UserProfile = switch interactionMode { case .viewStatic(let locationData): .init(sender: locationData.sender) case .viewLive(let sender, _): @@ -64,7 +64,7 @@ struct LocationSharingScreenViewState: BindableState { case .picker: .init(userID: ownUserID) } - userProfiles = [initialProfile.userID: initialProfile] + userProfiles = [initialProfile.id: initialProfile] if case .viewLive(_, let initialLiveLocationShare) = interactionMode, let initialLiveLocationShare { liveLocationShares = [initialLiveLocationShare] @@ -79,7 +79,7 @@ struct LocationSharingScreenViewState: BindableState { let interactionMode: LocationSharingInteractionMode let mapURLBuilder: MapTilerURLBuilderProtocol let ownUserID: String - var userProfiles: [String: UserProfileProxy] + var userProfiles: [String: UserProfile] var liveLocationShares: [LiveLocationShare] = [] var isStoppingLiveLocation = false /// Whether this device has an active live location sharing session in the room. @@ -103,10 +103,10 @@ struct LocationSharingScreenViewState: BindableState { return nil } - let profile = userProfiles[share.userID] ?? UserProfileProxy(userID: share.userID) + let profile = userProfiles[share.userID] ?? UserProfile(userID: share.userID) let kind = LocationMarkerKind.liveUser(profile) let coordinate = CLLocationCoordinate2D(latitude: geoURI.latitude, longitude: geoURI.longitude) - return LocationAnnotation(id: profile.userID, coordinate: coordinate, kind: kind) + return LocationAnnotation(id: profile.id, coordinate: coordinate, kind: kind) } case .picker: return [] @@ -287,8 +287,8 @@ extension AlertInfo where T == LocationSharingViewAlert { enum LocationMarkerKind: Equatable { case pin - case staticUser(UserProfileProxy) - case liveUser(UserProfileProxy) + case staticUser(UserProfile) + case liveUser(UserProfile) case placeholder var id: String { @@ -296,7 +296,7 @@ enum LocationMarkerKind: Equatable { case .pin, .placeholder: UUID().uuidString case .staticUser(let profile), .liveUser(let profile): - profile.userID + profile.id } } @@ -309,7 +309,7 @@ enum LocationMarkerKind: Equatable { } } - var userProfile: UserProfileProxy? { + var userProfile: UserProfile? { switch self { case .pin, .placeholder: nil diff --git a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift index 276cef4ef..282564e35 100644 --- a/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift +++ b/ElementX/Sources/Screens/LocationSharing/LocationSharingScreenViewModel.swift @@ -194,11 +194,11 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati private func updateUserProfiles(members: [RoomMemberProxyProtocol]) { switch state.interactionMode { case .picker: - let ownUser = members.first { $0.userID == roomProxy.ownUserID }.map(UserProfileProxy.init) ?? .init(userID: roomProxy.ownUserID) - state.userProfiles = [ownUser.userID: ownUser] + let ownUser = members.first { $0.userID == roomProxy.ownUserID }.map(UserProfile.init) ?? .init(userID: roomProxy.ownUserID) + state.userProfiles = [ownUser.id: ownUser] case .viewStatic(let location): - let sender = members.first { $0.userID == location.sender.id }.map(UserProfileProxy.init) ?? .init(sender: location.sender) - state.userProfiles = [sender.userID: sender] + let sender = members.first { $0.userID == location.sender.id }.map(UserProfile.init) ?? .init(sender: location.sender) + state.userProfiles = [sender.id: sender] case .viewLive(let sender, _): var userIDs = Set(state.liveLocationShares.map(\.userID)) if let senderID = sender?.id { @@ -206,9 +206,9 @@ class LocationSharingScreenViewModel: LocationSharingScreenViewModelType, Locati } state.userProfiles = userIDs.reduce(into: [:]) { dict, userID in if let member = members.first(where: { $0.userID == userID }) { - dict[userID] = UserProfileProxy(member: member) + dict[userID] = UserProfile(member: member) } else { - dict[userID] = UserProfileProxy(userID: userID) + dict[userID] = UserProfile(userID: userID) } } } diff --git a/ElementX/Sources/Screens/LocationSharing/View/LocationShareSheet.swift b/ElementX/Sources/Screens/LocationSharing/View/LocationShareSheet.swift index 5ae7b2f15..e0fac0ceb 100644 --- a/ElementX/Sources/Screens/LocationSharing/View/LocationShareSheet.swift +++ b/ElementX/Sources/Screens/LocationSharing/View/LocationShareSheet.swift @@ -16,7 +16,7 @@ struct LocationShareSheet: View { } private var senderName: String? { - annotation.kind.displayName ?? annotation.kind.userProfile?.userID + annotation.kind.displayName ?? annotation.kind.userProfile?.id } var body: some View { @@ -40,8 +40,8 @@ struct LocationShareSheet: View { // MARK: - Previews struct LocationShareSheet_Previews: PreviewProvider { - static let profile = UserProfileProxy(userID: "@alice:example.com", displayName: "Alice") - static let annotation = LocationAnnotation(id: profile.userID, + static let profile = UserProfile(userID: "@alice:example.com", displayName: "Alice") + static let annotation = LocationAnnotation(id: profile.id, coordinate: .init(latitude: 51.509865, longitude: -0.118092), kind: .liveUser(profile)) diff --git a/ElementX/Sources/Screens/LocationSharing/View/StaticLocationSheet.swift b/ElementX/Sources/Screens/LocationSharing/View/StaticLocationSheet.swift index fde8dacf3..5ab176af5 100644 --- a/ElementX/Sources/Screens/LocationSharing/View/StaticLocationSheet.swift +++ b/ElementX/Sources/Screens/LocationSharing/View/StaticLocationSheet.swift @@ -41,7 +41,7 @@ struct StaticLocationSheet: View { longitude: location.geoURI.longitude))) } label: { UserLocationCell(profile: profile, - isOwnUser: context.viewState.isOwnUser(profile.userID), + isOwnUser: context.viewState.isOwnUser(profile.id), kind: .static(isUserLocation: location.kind == .sender, timestamp: location.timestamp), mediaProvider: context.mediaProvider, diff --git a/ElementX/Sources/Screens/LocationSharing/View/UserLocationCell.swift b/ElementX/Sources/Screens/LocationSharing/View/UserLocationCell.swift index 447c9c35f..68142d11e 100644 --- a/ElementX/Sources/Screens/LocationSharing/View/UserLocationCell.swift +++ b/ElementX/Sources/Screens/LocationSharing/View/UserLocationCell.swift @@ -9,7 +9,7 @@ import Compound import SwiftUI struct UserLocationCell: View { - let profile: UserProfileProxy + let profile: UserProfile let isOwnUser: Bool let kind: Kind var mediaProvider: MediaProviderProtocol? @@ -23,7 +23,7 @@ struct UserLocationCell: View { } private var name: String { - isOwnUser ? L10n.commonYou : profile.displayName ?? profile.userID + isOwnUser ? L10n.commonYou : profile.displayName ?? profile.id } var body: some View { diff --git a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationRequestDetailsView.swift b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationRequestDetailsView.swift index fb22fd0e4..e619f1a33 100644 --- a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationRequestDetailsView.swift +++ b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationRequestDetailsView.swift @@ -30,18 +30,18 @@ struct SessionVerificationRequestDetailsView: View { HStack(spacing: 12) { LoadableAvatarImage(url: details.senderProfile.avatarURL, name: details.senderProfile.displayName, - contentID: details.senderProfile.userID, + contentID: details.senderProfile.id, avatarSize: .user(on: .sessionVerification), mediaProvider: mediaProvider) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 0) { - Text(details.senderProfile.displayName ?? details.senderProfile.userID) + Text(details.senderProfile.displayName ?? details.senderProfile.id) .font(.compound.bodySM) .foregroundColor(.compound.textSecondary) if details.senderProfile.displayName != nil { - Text(details.senderProfile.userID) + Text(details.senderProfile.id) .font(.compound.bodyMD) .foregroundColor(.compound.textPrimary) } @@ -66,7 +66,7 @@ struct SessionVerificationRequestDetailsView: View { .clipShape(RoundedRectangle(cornerRadius: 8)) let displayName = isUserVerification ? details.senderProfile.displayName : details.deviceDisplayName - Text(displayName ?? details.senderProfile.userID) + Text(displayName ?? details.senderProfile.id) .font(.compound.bodyMDSemibold) .foregroundColor(.compound.textPrimary) .frame(maxWidth: .infinity, alignment: .leading) @@ -110,9 +110,9 @@ struct SessionVerificationRequestDetailsView: View { } struct SessionVerificationRequestDetailsView_Previews: PreviewProvider, TestablePreview { - static let details = SessionVerificationRequestDetails(senderProfile: UserProfileProxy(userID: "@bob:matrix.org", - displayName: "Billy bob", - avatarURL: .mockMXCUserAvatar), + static let details = SessionVerificationRequestDetails(senderProfile: UserProfile(userID: "@bob:matrix.org", + displayName: "Billy bob", + avatarURL: .mockMXCUserAvatar), flowID: "123", deviceID: "CODEMISTAKE", deviceDisplayName: "Bob's Element X iOS", diff --git a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift index 40457dcc5..fc7675096 100644 --- a/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift +++ b/ElementX/Sources/Screens/Onboarding/SessionVerificationScreen/View/SessionVerificationScreen.swift @@ -232,9 +232,9 @@ struct SessionVerification_Previews: PreviewProvider, TestablePreview { sessionVerificationScreen(state: .initial, flow: .userInitiator(userID: "@bob:matrix.org")) .previewDisplayName("Initial - User Initiator") - let details = SessionVerificationRequestDetails(senderProfile: UserProfileProxy(userID: "@bob:matrix.org", - displayName: "Billy Bob", - avatarURL: .mockMXCUserAvatar), + let details = SessionVerificationRequestDetails(senderProfile: UserProfile(userID: "@bob:matrix.org", + displayName: "Billy Bob", + avatarURL: .mockMXCUserAvatar), flowID: "123", deviceID: "CODEMISTAKE", deviceDisplayName: "Bob's Element X iOS", diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift index a65e4384e..92e26f16a 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift @@ -26,7 +26,7 @@ enum RoomDetailsScreenCoordinatorAction { case presentRoomDetailsEditScreen case presentNotificationSettingsScreen case presentInviteUsersScreen - case presentInviteToNewRoom(invitee: UserProfileProxy) + case presentInviteToNewRoom(invitee: UserProfile) case presentPollsHistory case presentRolesAndPermissionsScreen case presentCall(isVoiceCall: Bool) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index 76f512619..28b5adac3 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -18,7 +18,7 @@ enum RoomDetailsScreenViewModelAction: Equatable { case requestMemberDetailsPresentation case requestRecipientDetailsPresentation(userID: String) case requestInvitePeoplePresentation - case requestInviteToNewRoomPresentation(selectedInvitee: UserProfileProxy) + case requestInviteToNewRoomPresentation(selectedInvitee: UserProfile) case leftRoom case requestEditDetailsPresentation case requestPollsHistoryPresentation diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift index 504ef0e3f..8b574a259 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/RoomMemberDetailsScreenViewModel.swift @@ -202,7 +202,7 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro } else if roomProxy.details.historySharingState != RoomHistorySharingState.hidden { Task { let identity = await self.userSession.clientProxy.userIdentity(for: roomMemberProxy.userID, fallBackToServer: false) - let user: UserProfileProxy = .init(userID: roomMemberProxy.userID, displayName: roomMemberProxy.displayName, avatarURL: roomMemberProxy.avatarURL) + let user: UserProfile = .init(userID: roomMemberProxy.userID, displayName: roomMemberProxy.displayName, avatarURL: roomMemberProxy.avatarURL) let isUnknown = if case .success(let identity) = identity { identity == nil } else { diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index a3fe7024d..3edce31c3 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -59,7 +59,7 @@ struct RoomMemberDetailsScreen: View { .padding(.top, 24) } } else { - AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID), + AvatarHeaderView(user: UserProfile(userID: context.viewState.userID), isVerified: context.viewState.showVerifiedBadge, avatarSize: .user(on: .memberDetails), mediaProvider: context.mediaProvider) { } diff --git a/ElementX/Sources/Screens/SearchScreen/SearchScreenViewModel.swift b/ElementX/Sources/Screens/SearchScreen/SearchScreenViewModel.swift index 52d219e86..8e902af95 100644 --- a/ElementX/Sources/Screens/SearchScreen/SearchScreenViewModel.swift +++ b/ElementX/Sources/Screens/SearchScreen/SearchScreenViewModel.swift @@ -85,7 +85,7 @@ class SearchScreenViewModel: SearchScreenViewModelType, SearchScreenViewModelPro // Show the matrix identifier as the subtitle: the other member's user ID for DMs, // otherwise the room's canonical alias. let identifier = if summary.isDirect { - summary.heroes.first?.userID ?? summary.canonicalAlias + summary.heroes.first?.id ?? summary.canonicalAlias } else { summary.canonicalAlias } diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift index 4819ea66b..39e3200e0 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenModels.swift @@ -50,8 +50,8 @@ struct StartChatScreenViewStateBindings { enum StartChatScreenViewAction { case close case createRoom - case createDM(user: UserProfileProxy) - case selectUser(UserProfileProxy) + case createDM(user: UserProfile) + case selectUser(UserProfile) case joinRoomByAddress case openRoomDirectorySearch } diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift index 42f698292..c43c6af37 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift @@ -19,7 +19,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie private let userDiscoveryService: UserDiscoveryServiceProtocol private let appSettings: AppSettings - private var suggestedUsers = [UserProfileProxy]() + private var suggestedUsers = [UserProfile]() private let actionsSubject: PassthroughSubject = .init() var actions: AnyPublisher { @@ -61,7 +61,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie case .selectUser(let user): showLoadingIndicator(delay: .milliseconds(200)) - let currentDirectRoom = userSession.clientProxy.directRoomForUserID(user.userID) + let currentDirectRoom = userSession.clientProxy.directRoomForUserID(user.id) switch currentDirectRoom { case .success(.some(let roomId)): hideLoadingIndicator() @@ -69,7 +69,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie case .success: Task { // If an error occured while fetching the identity, assume they are unknown. - let isUnknown = if case .success(let identity) = await self.userSession.clientProxy.userIdentity(for: user.userID, fallBackToServer: false) { + let isUnknown = if case .success(let identity) = await self.userSession.clientProxy.userIdentity(for: user.id, fallBackToServer: false) { identity == nil } else { true @@ -186,12 +186,12 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie } } - private func createDirectRoom(user: UserProfileProxy) async { + private func createDirectRoom(user: UserProfile) async { defer { hideLoadingIndicator() } showLoadingIndicator() - switch await userSession.clientProxy.createDirectRoom(with: user.userID, expectedRoomName: user.displayName) { + switch await userSession.clientProxy.createDirectRoom(with: user.id, expectedRoomName: user.displayName) { case .success(let roomId): analytics.trackCreatedRoom(isDM: true) actionsSubject.send(.showRoom(roomID: roomId)) diff --git a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift index 36b1de380..89fe04616 100644 --- a/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift +++ b/ElementX/Sources/Screens/StartChatScreen/View/StartChatScreen.swift @@ -112,7 +112,7 @@ struct StartChatScreen: View { private var usersSection: some View { if !context.viewState.usersSection.users.isEmpty { Section { - ForEach(context.viewState.usersSection.users, id: \.userID) { user in + ForEach(context.viewState.usersSection.users, id: \.id) { user in UserProfileListRow(user: user, membership: nil, mediaProvider: context.mediaProvider, diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift index 2c5657b9b..51fa6cb7b 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenModels.swift @@ -19,7 +19,7 @@ struct UserProfileScreenViewState: BindableState { let isOwnUser: Bool let isPresentedModally: Bool - var userProfile: UserProfileProxy? + var userProfile: UserProfile? var isIdentityKnown = false var isVerified: Bool? var permalink: URL? diff --git a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift index 9d2e8de5d..5ecd408da 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/UserProfileScreenViewModel.swift @@ -77,7 +77,7 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr // The proxies aren't Sendable, fetch through these helpers so that // they never leave the main actor when running calls in parallel. - private func fetchProfile() async -> Result { + private func fetchProfile() async -> Result { await userSession.clientProxy.profile(for: state.userID) } @@ -94,7 +94,7 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr state.userProfile = userProfile state.permalink = (try? matrixToUserPermalink(userId: state.userID)).flatMap(URL.init(string:)) - switch userSession.clientProxy.directRoomForUserID(userProfile.userID) { + switch userSession.clientProxy.directRoomForUserID(userProfile.id) { case .success(let roomID): state.dmRoomID = roomID case .failure: @@ -133,13 +133,13 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr showLoadingIndicator(allowsInteraction: false) defer { hideLoadingIndicator() } - switch userSession.clientProxy.directRoomForUserID(userProfile.userID) { + switch userSession.clientProxy.directRoomForUserID(userProfile.id) { case .success(let roomID): if let roomID { actionsSubject.send(.openDirectChat(roomID: roomID)) } else { Task { - let isUnknown = if case let .success(identity) = await userSession.clientProxy.userIdentity(for: userProfile.userID, fallBackToServer: false) { + let isUnknown = if case let .success(identity) = await userSession.clientProxy.userIdentity(for: userProfile.id, fallBackToServer: false) { identity == nil } else { true @@ -158,7 +158,7 @@ class UserProfileScreenViewModel: UserProfileScreenViewModelType, UserProfileScr showLoadingIndicator(allowsInteraction: false) defer { hideLoadingIndicator() } - switch await userSession.clientProxy.createDirectRoom(with: userProfile.userID, expectedRoomName: userProfile.displayName) { + switch await userSession.clientProxy.createDirectRoom(with: userProfile.id, expectedRoomName: userProfile.displayName) { case .success(let roomID): analytics.trackCreatedRoom(isDM: true) actionsSubject.send(.openDirectChat(roomID: roomID)) diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index 2e3af668b..70e1031a5 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -45,7 +45,7 @@ struct UserProfileScreen: View { otherUserFooter } } else { - AvatarHeaderView(user: UserProfileProxy(userID: context.viewState.userID), + AvatarHeaderView(user: UserProfile(userID: context.viewState.userID), isVerified: context.viewState.showVerifiedBadge, avatarSize: .user(on: .memberDetails), mediaProvider: context.mediaProvider) { } diff --git a/ElementX/Sources/Services/Client/ClientProxy.swift b/ElementX/Sources/Services/Client/ClientProxy.swift index 41b0288e2..6ec5c968a 100644 --- a/ElementX/Sources/Services/Client/ClientProxy.swift +++ b/ElementX/Sources/Services/Client/ClientProxy.swift @@ -786,7 +786,7 @@ class ClientProxy: ClientProxyProtocol { } } - func profile(for userID: String) async -> Result { + func profile(for userID: String) async -> Result { do { return try await .success(.init(sdkUserProfile: client.getProfile(userId: userID))) } catch { @@ -933,14 +933,14 @@ class ClientProxy: ClientProxyProtocol { return rooms } - func recentConversationCounterparts() async -> [UserProfileProxy] { + func recentConversationCounterparts() async -> [UserProfile] { let maxResultsToReturn = 5 guard case let .success(roomIdentifiers) = await recentlyVisitedRoomIDs() else { return [] } - var users: OrderedSet = [] + var users: OrderedSet = [] for roomID in roomIdentifiers { guard case let .joined(roomProxy) = await roomForIdentifier(roomID), diff --git a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift index f2023f2d5..cf4cd54a1 100644 --- a/ElementX/Sources/Services/Client/ClientProxyProtocol.swift +++ b/ElementX/Sources/Services/Client/ClientProxyProtocol.swift @@ -232,7 +232,7 @@ protocol ClientProxyProtocol: AnyObject { func searchUsers(searchTerm: String, limit: UInt) async -> Result - func profile(for userID: String) async -> Result + func profile(for userID: String) async -> Result func roomDirectorySearchProxy() -> RoomDirectorySearchProxyProtocol @@ -261,7 +261,7 @@ protocol ClientProxyProtocol: AnyObject { func trackRecentlyVisitedRoom(_ roomID: String) async -> Result func recentlyVisitedRooms(filter: @Sendable (JoinedRoomProxyProtocol) -> Bool) async -> [JoinedRoomProxyProtocol] - func recentConversationCounterparts() async -> [UserProfileProxy] + func recentConversationCounterparts() async -> [UserProfile] // MARK: - Crypto diff --git a/ElementX/Sources/Services/Room/RoomInfoProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomInfoProxyProtocol.swift index eb0f0043c..39f315be1 100644 --- a/ElementX/Sources/Services/Room/RoomInfoProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomInfoProxyProtocol.swift @@ -78,7 +78,7 @@ extension BaseRoomInfoProxyProtocol { } if isDirect, avatarURL == nil, heroes.count == 1 { - return .heroes(heroes.map(UserProfileProxy.init)) + return .heroes(heroes.map(UserProfile.init)) } return .room(id: id, name: displayName, avatarURL: avatarURL) diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift index e339504b5..dc5ae313f 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummary.swift @@ -43,7 +43,7 @@ nonisolated struct RoomSummary { let isSpace: Bool let avatarURL: URL? - let heroes: [UserProfileProxy] + let heroes: [UserProfile] let activeMembersCount: UInt let lastMessage: AttributedString? diff --git a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift index 2e5c3bbc9..582cfae0c 100644 --- a/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift +++ b/ElementX/Sources/Services/Room/RoomSummary/RoomSummaryProvider.swift @@ -354,7 +354,7 @@ class RoomSummaryProvider: RoomSummaryProviderProtocol { isDirect: roomInfo.isDirect, isSpace: roomInfo.isSpace, avatarURL: roomInfo.avatarUrl.flatMap(URL.init(string:)), - heroes: roomInfo.heroes.map(UserProfileProxy.init), + heroes: roomInfo.heroes.map(UserProfile.init), activeMembersCount: UInt(roomInfo.activeMembersCount), lastMessage: attributedLastMessage, lastMessageDate: lastMessageDate, diff --git a/ElementX/Sources/Services/Room/UserToInvite.swift b/ElementX/Sources/Services/Room/UserToInvite.swift index 9253a6a9a..9811beb54 100644 --- a/ElementX/Sources/Services/Room/UserToInvite.swift +++ b/ElementX/Sources/Services/Room/UserToInvite.swift @@ -9,7 +9,7 @@ import Foundation struct UserToInvite: Identifiable { /// The profile of the user being invited. - var user: UserProfileProxy + var user: UserProfile /// The ID of the user being invited. var id: String { diff --git a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift index 83caa0a8f..ea70b9c26 100644 --- a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift +++ b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxy.swift @@ -89,7 +89,7 @@ class SessionVerificationControllerProxy: SessionVerificationControllerProxyProt MXLog.info("Acknowledging verification request") do { - try await sessionVerificationController.acknowledgeVerificationRequest(senderId: details.senderProfile.userID, flowId: details.flowID) + try await sessionVerificationController.acknowledgeVerificationRequest(senderId: details.senderProfile.id, flowId: details.flowID) return .success(()) } catch { MXLog.error("Failed requesting session verification with error: \(error)") @@ -190,7 +190,7 @@ class SessionVerificationControllerProxy: SessionVerificationControllerProxyProt fileprivate func didReceiveVerificationRequest(details: MatrixRustSDK.SessionVerificationRequestDetails) { MXLog.info("Received verification request \(details)") - let details = SessionVerificationRequestDetails(senderProfile: UserProfileProxy(sdkUserProfile: details.senderProfile), + let details = SessionVerificationRequestDetails(senderProfile: UserProfile(sdkUserProfile: details.senderProfile), flowID: details.flowId, deviceID: details.deviceId, deviceDisplayName: details.deviceDisplayName, diff --git a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift index f277bb3ca..241ceb160 100644 --- a/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift +++ b/ElementX/Sources/Services/SessionVerification/SessionVerificationControllerProxyProtocol.swift @@ -31,7 +31,7 @@ enum SessionVerificationControllerProxyAction: Equatable { } struct SessionVerificationRequestDetails: Equatable { - let senderProfile: UserProfileProxy + let senderProfile: UserProfile let flowID: String let deviceID: String let deviceDisplayName: String? diff --git a/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift b/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift index 37618a739..72965c95c 100644 --- a/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift +++ b/ElementX/Sources/Services/Spaces/SpaceServiceRoom.swift @@ -28,7 +28,7 @@ struct SpaceServiceRoom { var childrenCount: Int var joinedMembersCount: Int - var heroes: [UserProfileProxy] + var heroes: [UserProfile] var topic: String? var canonicalAlias: String? @@ -75,7 +75,7 @@ extension SpaceServiceRoom { childrenCount = Int(spaceRoom.childrenCount) joinedMembersCount = Int(spaceRoom.numJoinedMembers) - heroes = (spaceRoom.heroes ?? []).map(UserProfileProxy.init) + heroes = (spaceRoom.heroes ?? []).map(UserProfile.init) topic = spaceRoom.topic canonicalAlias = spaceRoom.canonicalAlias @@ -97,7 +97,7 @@ extension SpaceServiceRoom { isDM: Bool? = nil, childrenCount: Int = 0, joinedMembersCount: Int = 0, - heroes: [UserProfileProxy] = [], + heroes: [UserProfile] = [], topic: String? = nil, canonicalAlias: String? = nil, joinRule: JoinRule? = nil, diff --git a/ElementX/Sources/Services/Users/UserDiscoverySection.swift b/ElementX/Sources/Services/Users/UserDiscoverySection.swift index 947c7e49a..cea153f90 100644 --- a/ElementX/Sources/Services/Users/UserDiscoverySection.swift +++ b/ElementX/Sources/Services/Users/UserDiscoverySection.swift @@ -10,7 +10,7 @@ import Foundation struct UserDiscoverySection { let type: UserDiscoverySectionType - let users: [UserProfileProxy] + let users: [UserProfile] var title: String? { switch type { diff --git a/ElementX/Sources/Services/Users/UserDiscoveryService.swift b/ElementX/Sources/Services/Users/UserDiscoveryService.swift index 52e0dfe85..844730e9b 100644 --- a/ElementX/Sources/Services/Users/UserDiscoveryService.swift +++ b/ElementX/Sources/Services/Users/UserDiscoveryService.swift @@ -15,7 +15,7 @@ final class UserDiscoveryService: UserDiscoveryServiceProtocol { self.clientProxy = clientProxy } - func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> { + func searchProfiles(with searchQuery: String) async -> Result<[UserProfile], UserDiscoveryErrorType> { async let queriedProfile = profileIfPossible(with: searchQuery) do { @@ -32,7 +32,7 @@ final class UserDiscoveryService: UserDiscoveryServiceProtocol { } } - private func merge(queriedProfile: UserProfileProxy?, searchResults: SearchUsersResultsProxy) -> [UserProfileProxy] { + private func merge(queriedProfile: UserProfile?, searchResults: SearchUsersResultsProxy) -> [UserProfile] { let searchResults = searchResults.results guard let queriedProfile else { @@ -40,13 +40,13 @@ final class UserDiscoveryService: UserDiscoveryServiceProtocol { } let filteredSearchResult = searchResults.filter { - $0.userID != queriedProfile.userID + $0.id != queriedProfile.id } return [queriedProfile] + filteredSearchResult } - private func profileIfPossible(with searchQuery: String) async -> UserProfileProxy? { + private func profileIfPossible(with searchQuery: String) async -> UserProfile? { guard searchQuery.isMatrixIdentifier, searchQuery != clientProxy.userID else { return nil } @@ -57,9 +57,9 @@ final class UserDiscoveryService: UserDiscoveryServiceProtocol { return getProfileResult ?? .init(userID: searchQuery) } - private func filterAccountOwner(_ profiles: [UserProfileProxy]) -> [UserProfileProxy] { + private func filterAccountOwner(_ profiles: [UserProfile]) -> [UserProfile] { let accountOwnerID = clientProxy.userID - return profiles.filter { $0.userID != accountOwnerID } + return profiles.filter { $0.id != accountOwnerID } } } diff --git a/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift b/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift index 3de6a428a..e03ed0c9c 100644 --- a/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift +++ b/ElementX/Sources/Services/Users/UserDiscoveryServiceProtocol.swift @@ -14,5 +14,5 @@ enum UserDiscoveryErrorType: Error { // sourcery: AutoMockable protocol UserDiscoveryServiceProtocol { - func searchProfiles(with searchQuery: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> + func searchProfiles(with searchQuery: String) async -> Result<[UserProfile], UserDiscoveryErrorType> } diff --git a/ElementX/Sources/Services/Users/UserProfileProxy.swift b/ElementX/Sources/Services/Users/UserProfile.swift similarity index 80% rename from ElementX/Sources/Services/Users/UserProfileProxy.swift rename to ElementX/Sources/Services/Users/UserProfile.swift index de126c3c4..43148a6d7 100644 --- a/ElementX/Sources/Services/Users/UserProfileProxy.swift +++ b/ElementX/Sources/Services/Users/UserProfile.swift @@ -9,37 +9,37 @@ import Foundation import MatrixRustSDK -nonisolated struct UserProfileProxy: Equatable, Hashable { - let userID: String +nonisolated struct UserProfile: Hashable, Identifiable { + let id: String let displayName: String? let avatarURL: URL? init(userID: String, displayName: String? = nil, avatarURL: URL? = nil) { - self.userID = userID + id = userID self.displayName = displayName self.avatarURL = avatarURL } init(member: RoomMemberDetails) { - userID = member.id + id = member.id displayName = member.isBanned ? nil : member.name avatarURL = member.isBanned ? nil : member.avatarURL } init(sender: TimelineItemSender) { - userID = sender.id + id = sender.id displayName = sender.displayName avatarURL = sender.avatarURL } init(sdkUserProfile: MatrixRustSDK.UserProfile) { - userID = sdkUserProfile.userId + id = sdkUserProfile.userId displayName = sdkUserProfile.displayName avatarURL = sdkUserProfile.avatarUrl.flatMap(URL.init(string:)) } init(sdkRoomHero: MatrixRustSDK.RoomHero) { - userID = sdkRoomHero.userId + id = sdkRoomHero.userId displayName = sdkRoomHero.displayName avatarURL = sdkRoomHero.avatarUrl.flatMap(URL.init(string:)) } @@ -56,19 +56,13 @@ nonisolated struct UserProfileProxy: Equatable, Hashable { } struct SearchUsersResultsProxy { - let results: [UserProfileProxy] + let results: [UserProfile] let limited: Bool } extension SearchUsersResultsProxy { init(sdkResults: MatrixRustSDK.SearchUsersResults) { - results = sdkResults.results.map(UserProfileProxy.init) + results = sdkResults.results.map(UserProfile.init) limited = sdkResults.limited } } - -extension UserProfileProxy: Identifiable { - var id: String { - userID - } -} diff --git a/UnitTests/Sources/CreateRoomViewModelTests.swift b/UnitTests/Sources/CreateRoomViewModelTests.swift index 87d45c306..5139da1b7 100644 --- a/UnitTests/Sources/CreateRoomViewModelTests.swift +++ b/UnitTests/Sources/CreateRoomViewModelTests.swift @@ -19,7 +19,7 @@ final class CreateRoomScreenViewModelTests { private let appSettings: AppSettings - private let usersSubject = CurrentValueSubject<[UserProfileProxy], Never>([]) + private let usersSubject = CurrentValueSubject<[UserProfile], Never>([]) var context: CreateRoomScreenViewModel.Context { viewModel.context diff --git a/UnitTests/Sources/InviteUsersViewModelTests.swift b/UnitTests/Sources/InviteUsersViewModelTests.swift index f8590d476..a956be1b2 100644 --- a/UnitTests/Sources/InviteUsersViewModelTests.swift +++ b/UnitTests/Sources/InviteUsersViewModelTests.swift @@ -29,7 +29,7 @@ final class InviteUsersScreenViewModelTests { #expect(context.viewState.selectedUsers.isEmpty) context.send(viewAction: .toggleUser(.mockAlice)) #expect(context.viewState.selectedUsers.count == 1) - #expect(context.viewState.selectedUsers.first?.userID == UserProfileProxy.mockAlice.userID) + #expect(context.viewState.selectedUsers.first?.id == UserProfile.mockAlice.id) } @Test @@ -41,7 +41,7 @@ final class InviteUsersScreenViewModelTests { #expect(context.viewState.selectedUsers.isEmpty) context.send(viewAction: .toggleUser(.mockAlice)) #expect(context.viewState.selectedUsers.count == 1) - #expect(context.viewState.selectedUsers.first?.userID == UserProfileProxy.mockAlice.userID) + #expect(context.viewState.selectedUsers.first?.id == UserProfile.mockAlice.id) context.send(viewAction: .toggleUser(.mockAlice)) #expect(context.viewState.selectedUsers.isEmpty) } @@ -55,7 +55,7 @@ final class InviteUsersScreenViewModelTests { #expect(context.viewState.selectedUsers.isEmpty) context.send(viewAction: .toggleUser(.mockAlice)) #expect(context.viewState.selectedUsers.count == 1) - #expect(context.viewState.selectedUsers.first?.userID == UserProfileProxy.mockAlice.userID) + #expect(context.viewState.selectedUsers.first?.id == UserProfile.mockAlice.id) context.send(viewAction: .toggleUser(.mockAlice)) #expect(context.viewState.selectedUsers.isEmpty) } @@ -174,7 +174,7 @@ final class InviteUsersScreenViewModelTests { appSettings: .volatile()) // The locked invitee starts pre-selected and locked. - #expect(context.viewState.selectedUsers.map(\.userID) == [UserProfileProxy.mockAlice.userID]) + #expect(context.viewState.selectedUsers.map(\.id) == [UserProfile.mockAlice.id]) #expect(context.viewState.isInviteeMandatory(.mockAlice)) // The proceed button is disabled while the only selected user is the locked invitee. #expect(!context.viewState.hasInvitableSelectedUsers) @@ -218,7 +218,7 @@ final class InviteUsersScreenViewModelTests { #expect(args.topic == nil) #expect(args.accessType == .private) #expect(args.isSpace == false) - #expect(args.userIDs == [UserProfileProxy.mockAlice.userID, UserProfileProxy.mockBob.userID]) + #expect(args.userIDs == [UserProfile.mockAlice.id, UserProfile.mockBob.id]) #expect(args.avatarURL == nil) #expect(args.aliasLocalPart == nil) } diff --git a/UnitTests/Sources/RoomSummaryTests.swift b/UnitTests/Sources/RoomSummaryTests.swift index e983d1185..1fb2da855 100644 --- a/UnitTests/Sources/RoomSummaryTests.swift +++ b/UnitTests/Sources/RoomSummaryTests.swift @@ -15,7 +15,7 @@ import Testing struct RoomSummaryTests { // swiftlint:disable:next large_tuple let roomDetails: (id: String, name: String, avatarURL: URL) = ("room_id", "Room Name", "mxc://hs.tld/room/avatar") - let heroes = [UserProfileProxy(userID: "hero_1", displayName: "Hero 1", avatarURL: "mxc://hs.tld/user/avatar")] + let heroes = [UserProfile(userID: "hero_1", displayName: "Hero 1", avatarURL: "mxc://hs.tld/user/avatar")] @Test func roomAvatar() { diff --git a/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift b/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift index f3acd2115..7a8019b04 100644 --- a/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift +++ b/UnitTests/Sources/UserDiscoveryService/UserDiscoveryServiceTest.swift @@ -14,7 +14,7 @@ struct UserDiscoveryServiceTest { private var service: UserDiscoveryService private var clientProxy: ClientProxyMock - private var searchResults: [UserProfileProxy] { + private var searchResults: [UserProfile] { [.mockAlice, .mockBob, .mockCharlie] } @@ -25,7 +25,7 @@ struct UserDiscoveryServiceTest { @Test func queryShowingResults() async { - clientProxy.searchUsersSearchTermLimitReturnValue = .success(.init(results: [UserProfileProxy.mockAlice], limited: true)) + clientProxy.searchUsersSearchTermLimitReturnValue = .success(.init(results: [UserProfile.mockAlice], limited: true)) let results = await (try? search(query: "AAA").get()) ?? [] assertSearchResults(results, toBe: 1) @@ -33,7 +33,7 @@ struct UserDiscoveryServiceTest { @Test func ownerIsFiltered() async { - clientProxy.searchUsersSearchTermLimitReturnValue = .success(.init(results: [UserProfileProxy(userID: "@foo:matrix.org")], limited: true)) + clientProxy.searchUsersSearchTermLimitReturnValue = .success(.init(results: [UserProfile(userID: "@foo:matrix.org")], limited: true)) let results = await (try? search(query: "AAA").get()) ?? [] assertSearchResults(results, toBe: 0) @@ -104,7 +104,7 @@ struct UserDiscoveryServiceTest { let results = await (try? search(query: "@a:b.com").get()) ?? [] assertSearchResults(results, toBe: 3) - let firstUserID = results.first?.userID + let firstUserID = results.first?.id #expect(firstUserID == "@bob:matrix.org") #expect(clientProxy.profileForCalled) } @@ -116,20 +116,20 @@ struct UserDiscoveryServiceTest { let results = await (try? search(query: "@a:b.com").get()) ?? [] - let firstUserID = results.first?.userID + let firstUserID = results.first?.id #expect(firstUserID == "@a:b.com") #expect(clientProxy.profileForCalled) } // MARK: - Private - private func assertSearchResults(_ results: [UserProfileProxy], toBe count: Int) { + private func assertSearchResults(_ results: [UserProfile], toBe count: Int) { #expect(count >= 0) #expect(results.count == count) #expect(results.isEmpty == (count == 0)) } - private func search(query: String) async -> Result<[UserProfileProxy], UserDiscoveryErrorType> { + private func search(query: String) async -> Result<[UserProfile], UserDiscoveryErrorType> { await service.searchProfiles(with: query) } } diff --git a/UnitTests/Sources/UserProfileScreenViewModelTests.swift b/UnitTests/Sources/UserProfileScreenViewModelTests.swift index 935488bf7..893814cf5 100644 --- a/UnitTests/Sources/UserProfileScreenViewModelTests.swift +++ b/UnitTests/Sources/UserProfileScreenViewModelTests.swift @@ -15,11 +15,11 @@ struct UserProfileScreenViewModelTests { func initialState() async throws { let userIndicatorController = UserIndicatorControllerMock() - let profile = UserProfileProxy(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: .mockMXCAvatar) + let profile = UserProfile(userID: "@alice:matrix.org", displayName: "Alice", avatarURL: .mockMXCAvatar) let clientProxy = ClientProxyMock(.init()) clientProxy.profileForReturnValue = .success(profile) - let viewModel = UserProfileScreenViewModel(userID: profile.userID, + let viewModel = UserProfileScreenViewModel(userID: profile.id, isPresentedModally: false, userSession: UserSessionMock(.init(clientProxy: clientProxy)), userIndicatorController: userIndicatorController, @@ -39,11 +39,11 @@ struct UserProfileScreenViewModelTests { func initialStateAccountOwner() async throws { let userIndicatorController = UserIndicatorControllerMock() - let profile = UserProfileProxy(userID: RoomMemberProxyMock.mockMe.userID, displayName: "Me", avatarURL: .mockMXCAvatar) + let profile = UserProfile(userID: RoomMemberProxyMock.mockMe.userID, displayName: "Me", avatarURL: .mockMXCAvatar) let clientProxy = ClientProxyMock(.init()) clientProxy.profileForReturnValue = .success(profile) - let viewModel = UserProfileScreenViewModel(userID: profile.userID, + let viewModel = UserProfileScreenViewModel(userID: profile.id, isPresentedModally: false, userSession: UserSessionMock(.init(clientProxy: clientProxy)), userIndicatorController: userIndicatorController, @@ -63,13 +63,13 @@ struct UserProfileScreenViewModelTests { func startingDmWithUnknownUserFetchesIdentity() async throws { let userIndicatorController = UserIndicatorControllerMock() - let profile = UserProfileProxy.mockAlice + let profile = UserProfile.mockAlice let clientProxy = ClientProxyMock(.init()) clientProxy.directRoomForUserIDReturnValue = .success(nil) clientProxy.userIdentityForFallBackToServerReturnValue = .success(nil) - let viewModel = UserProfileScreenViewModel(userID: profile.userID, + let viewModel = UserProfileScreenViewModel(userID: profile.id, isPresentedModally: false, userSession: UserSessionMock(.init(clientProxy: clientProxy)), userIndicatorController: userIndicatorController,