diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift index 110e995ee..9479780bd 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenModels.swift @@ -34,7 +34,7 @@ nonisolated struct RoomMemberListScreenEntry: Equatable { let member: RoomMemberDetails let verificationState: UserIdentityVerificationState /// Whether the member is currently joined to the room's active MatrixRTC call (e.g. Element Call). - var isInCall = false + var isActiveRoomCallParticipant = false } struct RoomMembersListScreenViewState: BindableState { diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift index 8a6ae00aa..69098e656 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/RoomMembersListScreenViewModel.swift @@ -99,7 +99,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe hideLoadingIndicator(Self.updateStateLoadingIndicatorIdentifier) } - let members = members.sorted() + let members = members.sorted(prioritisingRoomCallParticipants: roomProxy.infoPublisher.value.activeRoomCallParticipants) let roomMembersDetails = await buildMembersDetails(members: members) self.members = members self.currentUserProxy = members.first { $0.userID == roomProxy.ownUserID } @@ -127,7 +127,7 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe let isEncrypted = roomProxy.infoPublisher.value.isEncrypted let activeRoomCallParticipants = Set(roomProxy.infoPublisher.value.activeRoomCallParticipants) - let membersDetails: RoomMembersDetails = await Task.detached { [weak self] in + return await Task.detached { [weak self] in // accessing RoomMember's properties is very slow. We need to do it in a background thread. var invitedMembers: [RoomMemberListScreenEntry] = .init() var joinedMembers: [RoomMemberListScreenEntry] = .init() @@ -138,15 +138,15 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe if isEncrypted, let fetchedState = await self?.userIdentityVerificationState(for: member.userID) { verificationState = fetchedState } - let isInCall = activeRoomCallParticipants.contains(member.userID) + let isActiveRoomCallParticipant = activeRoomCallParticipants.contains(member.userID) switch member.membership { case .invite: - invitedMembers.append(.init(member: .init(withProxy: member), verificationState: verificationState, isInCall: isInCall)) + invitedMembers.append(.init(member: .init(withProxy: member), verificationState: verificationState, isActiveRoomCallParticipant: isActiveRoomCallParticipant)) case .join: - joinedMembers.append(.init(member: .init(withProxy: member), verificationState: verificationState, isInCall: isInCall)) + joinedMembers.append(.init(member: .init(withProxy: member), verificationState: verificationState, isActiveRoomCallParticipant: isActiveRoomCallParticipant)) case .ban: - bannedMembers.append(.init(member: .init(withProxy: member), verificationState: verificationState, isInCall: isInCall)) + bannedMembers.append(.init(member: .init(withProxy: member), verificationState: verificationState, isActiveRoomCallParticipant: isActiveRoomCallParticipant)) default: continue } @@ -157,10 +157,6 @@ class RoomMembersListScreenViewModel: RoomMembersListScreenViewModelType, RoomMe bannedMembers: bannedMembers.sorted { $0.member.id.localizedStandardCompare($1.member.id) == .orderedAscending }) // Re-sort ignoring display name. } .value - - return .init(invitedMembers: membersDetails.invitedMembers, - joinedMembers: membersDetails.joinedMembers.filter(\.isInCall) + membersDetails.joinedMembers.filter { !$0.isInCall }, - bannedMembers: membersDetails.bannedMembers) } /// The client proxy isn't Sendable, fetch identities through this helper so diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift index 65ad51c93..7b55b7652 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreen.swift @@ -171,7 +171,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { static let adminViewModel = makeViewModel(isAdmin: true, initialMode: .members) static let bannedViewModel = makeViewModel(isAdmin: true, initialMode: .banned) static let emptyBannedViewModel = makeViewModel(withBanned: false, isAdmin: false, initialMode: .members) - static let adminInCallViewModel = makeViewModel(withInCall: true, isAdmin: true) + static let activeRoomCallViewModel = makeViewModel(hasActiveRoomCall: true, isAdmin: true) static var previews: some View { ElementNavigationStack { @@ -207,12 +207,12 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { .previewDisplayName("Admin: Banned") ElementNavigationStack { - RoomMembersListScreen(context: adminInCallViewModel.context) + RoomMembersListScreen(context: activeRoomCallViewModel.context) } - .snapshotPreferences(expect: adminInCallViewModel.context.$viewState.map { state in + .snapshotPreferences(expect: activeRoomCallViewModel.context.$viewState.map { state in state.canBanUsers == true }) - .previewDisplayName("Admin: In-Call") + .previewDisplayName("Active Room Call") ElementNavigationStack { RoomMembersListScreen(context: emptyBannedViewModel.context) @@ -224,7 +224,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { static func makeViewModel(withInvites: Bool = false, withBanned: Bool = true, - withInCall: Bool = false, + hasActiveRoomCall: Bool = false, isAdmin: Bool = false, initialMode: RoomMembersListScreenMode = .members) -> RoomMembersListScreenViewModel { let mockAdmin = RoomMemberProxyMock.mockAdmin @@ -238,8 +238,7 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { mockAdmin, .mockCreator, .mockOwner, - .mockModerator, - .mockFrank + .mockModerator ] if withBanned { @@ -250,9 +249,11 @@ struct RoomMembersListScreen_Previews: PreviewProvider, TestablePreview { members.append(.mockInvited) } - let activeRoomCallParticipants = withInCall ? [RoomMemberProxyMock.mockAlice.userID, - RoomMemberProxyMock.mockOwner.userID, - mockAdmin.userID] : [] + let activeRoomCallParticipants: [String] = if hasActiveRoomCall { + [RoomMemberProxyMock.mockAlice.userID, RoomMemberProxyMock.mockOwner.userID, mockAdmin.userID] + } else { + [] + } let clientProxyMock = ClientProxyMock(.init()) clientProxyMock.userIdentityForFallBackToServerClosure = { userID, _ in diff --git a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift index 76c390064..847293705 100644 --- a/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift +++ b/ElementX/Sources/Screens/RoomMemberListScreen/View/RoomMembersListScreenMemberCell.swift @@ -56,7 +56,7 @@ struct RoomMembersListScreenMemberCell: View { .foregroundStyle(.compound.textSecondary) } - if listEntry.isInCall { + if listEntry.isActiveRoomCallParticipant { CompoundIcon(\.videoCallSolid, size: .small, relativeTo: .compound.bodyLG) .foregroundStyle(.compound.iconAccentPrimary) .accessibilityLabel(L10n.commonOnACall) @@ -125,7 +125,7 @@ struct RoomMembersListMemberCell_Previews: PreviewProvider, TestablePreview { verificationState: .verificationViolation), .init(member: .init(withProxy: RoomMemberProxyMock.mockFrank), verificationState: .notVerified, - isInCall: true), + isActiveRoomCallParticipant: true), .init(member: .init(withProxy: RoomMemberProxyMock(with: .init(userID: "@nodisplayname:matrix.org", membership: .join))), verificationState: .notVerified), diff --git a/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift b/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift index a3e855d4f..3bbdac518 100644 --- a/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift +++ b/ElementX/Sources/Services/Room/RoomMember/RoomMemberProxyProtocol.swift @@ -49,10 +49,15 @@ nonisolated extension RoomMemberProxyProtocol { } nonisolated extension [RoomMemberProxyProtocol] { - /// The members, sorted first by power-level, and then alphabetically within each power-level. - func sorted() -> Self { + /// The members, sorted first by call participation, then by power-level, and then alphabetically within each power-level. + func sorted(prioritisingRoomCallParticipants roomCallParticipants: [String] = []) -> Self { sorted { lhs, rhs in - if lhs.powerLevel != rhs.powerLevel { + let lhsIsRoomCallParticipant = roomCallParticipants.contains(lhs.userID) + let rhsIsRoomCallParticipant = roomCallParticipants.contains(rhs.userID) + + return if lhsIsRoomCallParticipant != rhsIsRoomCallParticipant { + lhsIsRoomCallParticipant + } else if lhs.powerLevel != rhs.powerLevel { lhs.powerLevel > rhs.powerLevel } else { lhs.sortingName.localizedStandardCompare(rhs.sortingName) == .orderedAscending diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-en-GB-0.png index 92be35769..6de2a11c2 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0335c7aa8a403021b86780212554d28f04dc8caba12c56018a2edbbb53b6d373 -size 172243 +oid sha256:77ae08f13c5ea29c3854bb2b8a6ddbcc8bc82980559c9f50168d5101a5400f83 +size 181974 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-pseudo-0.png index 0c7cfbef4..630869df9 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPad-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1cd812d91a85f54bdd9da4cdefd2ed605a999195bd3be68f9726fdd37fbeda96 -size 174277 +oid sha256:448beb21d2a8ddbd0e7d0f25b7d0cdd211752ed146fb15bdd7985aa0b6f7b723 +size 183929 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-en-GB-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-en-GB-0.png index 517a207d8..963b0f8ea 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-en-GB-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-en-GB-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c52cb2c0a60e202b872c89f6ffb24ded4abc3f63c47794e9ee7bfecb05001d7 -size 116931 +oid sha256:7e9558139bb02e1a7570e05375e5481ae4de4f6ac3648c8c8a64cd2566543bea +size 125566 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-pseudo-0.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-pseudo-0.png index c83358427..c8bd94909 100644 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-pseudo-0.png +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListMemberCell.iPhone-pseudo-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba230c28ad61dd3fa5e27e2e5e715e64c399fed072e8a10cb41a1feb06b5edca -size 122379 +oid sha256:8662f774ad0e927e88fba3034b2b11f180b8a1e54e5142644bccdd4757d1156b +size 131231 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPad-en-GB.png new file mode 100644 index 000000000..adfeef718 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPad-en-GB.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca9c0c8e12a42f3c4ee76dd530e4fb46ef787dbaa15536c234e5694cbe3ddb4b +size 160033 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPad-pseudo.png new file mode 100644 index 000000000..f2a172ada --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPad-pseudo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7a33ca9f604b6590b0a8478e9e45ae01bb50869a25aecef2652e9da51b71bd7 +size 168357 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPhone-en-GB.png new file mode 100644 index 000000000..75cc0fe2a --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPhone-en-GB.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f64664d2c9f8aaa22bfa6f40fe7c2ff7d7e4b435bbb959e5e0b64ff22fad4385 +size 105723 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPhone-pseudo.png new file mode 100644 index 000000000..88bb8401b --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Active-Room-Call-iPhone-pseudo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8c95e5f31573e3070bebb6f0b4d4b08595a7b89e4761d0fc7a3b9646c5c105f +size 117769 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPad-en-GB.png deleted file mode 100644 index 03cd3978b..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPad-en-GB.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:18395ebf158fcb6a95c2cb872dfe10c46524c1da11e1dde7606d641d3595dbec -size 168947 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPad-pseudo.png deleted file mode 100644 index 12e61ac17..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPad-pseudo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8baf2a6430be90309622852137282670f80acb65c134b954be2f15a68c26db72 -size 176958 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPhone-en-GB.png deleted file mode 100644 index baf3986b4..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPhone-en-GB.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bf46ae15f2852960aed8d453219b03082bcc655c076946e66471e16c55b474fd -size 113640 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPhone-pseudo.png deleted file mode 100644 index e517faf75..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/roomMembersListScreen.Admin-In-Call-iPhone-pseudo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a83fb0e73446c7f567cf320974677ca744b101bdd0d18854d963f4f970329bfd -size 124639 diff --git a/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift b/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift index 5c854fadd..88a00a76a 100644 --- a/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomMembersListScreenViewModelTests.swift @@ -68,7 +68,7 @@ struct RoomMembersListScreenViewModelTests { let sortedMembers: [RoomMemberListScreenEntry] = [ .init(member: .init(withProxy: RoomMemberProxyMock.mockFrank), verificationState: .notVerified, - isInCall: true), + isActiveRoomCallParticipant: true), .init(member: .init(withProxy: RoomMemberProxyMock.mockAdmin), verificationState: .notVerified), .init(member: .init(withProxy: RoomMemberProxyMock.mockAlice),