User verification state indicators (#3793)

* Introduce a `UserIdentityProxy` and have it combine upstream methods into an easy to digest  `UserIdentityVerificationState`. Use it in a dedicated `VerificationBadge` UI component

* Show a DMs counterpart verification state in the room header

* Show a warning on the room details `People` entry when there are identity verification state violations on any of the members.

* Show verification badges in the room member list

* Show a withdraw verification section on the room member details for users that have pinning violations.

* Remove the verification section from the profile screen as there's no reliable way to keep it up to date
- the underlying Rust SDK Olm Machine can be rebuilt without notice which would break any existing user identity change streams.

* Update preview test snapshots
This commit is contained in:
Stefan Ceriu
2025-02-18 08:37:34 +02:00
committed by GitHub
parent b71c93dfaa
commit f77faee981
101 changed files with 722 additions and 305 deletions
@@ -42,10 +42,20 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
super.init(initialViewState: initialViewState, mediaProvider: mediaProvider)
showMemberLoadingIndicator()
Task {
await loadMember()
hideMemberLoadingIndicator()
}
roomProxy.identityStatusChangesPublisher
.receive(on: DispatchQueue.main)
.sink { changes in
if changes.map(\.userId).contains(userID) {
Task { await self.loadMember() }
}
}
.store(in: &cancellables)
}
// MARK: - Public
@@ -77,16 +87,15 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
actionsSubject.send(.startCall(roomID: roomID))
case .verifyUser:
actionsSubject.send(.verifyUser(userID: state.userID))
case .withdrawVerification:
Task { await clientProxy.withdrawUserIdentityVerification(state.userID) }
}
}
// MARK: - Private
private func loadMember() async {
async let memberResult = roomProxy.getMember(userID: state.userID)
async let identityResult = clientProxy.userIdentity(for: state.userID)
switch await memberResult {
switch await roomProxy.getMember(userID: state.userID) {
case .success(let member):
roomMemberProxy = member
state.memberDetails = RoomMemberDetails(withProxy: member)
@@ -105,8 +114,8 @@ class RoomMemberDetailsScreenViewModel: RoomMemberDetailsScreenViewModelType, Ro
actionsSubject.send(.openUserProfile)
}
if case let .success(.some(identity)) = await identityResult {
state.isVerified = identity.isVerified()
if case let .success(.some(identity)) = await clientProxy.userIdentity(for: state.userID) {
state.verificationState = identity.verificationState
} else {
MXLog.error("Failed to find the member's identity.")
}