Invite the DM recipient to a new room (#5588)

* handle the details to invite users flow.

* implemented the room creation in the invite screen, and its dismissal + navigaton to the newly created room

* updated preview and unit tests

* pr suggestions
This commit is contained in:
Mauro
2026-05-18 10:08:07 +02:00
committed by GitHub
parent 9ed47c61b7
commit 6c0aaa7a58
39 changed files with 297 additions and 100 deletions
@@ -14,7 +14,7 @@ typealias InviteUsersScreenViewModelType = StateStoreViewModel<InviteUsersScreen
class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScreenViewModelProtocol {
private let clientProxy: ClientProxyProtocol
private let roomProxy: JoinedRoomProxyProtocol
private let roomType: InviteUsersScreenRoomType
private let userDiscoveryService: UserDiscoveryServiceProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let appSettings: AppSettings
@@ -27,21 +27,24 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
}
init(userSession: UserSessionProtocol,
roomProxy: JoinedRoomProxyProtocol,
roomType: InviteUsersScreenRoomType,
isSkippable: Bool,
userDiscoveryService: UserDiscoveryServiceProtocol,
userIndicatorController: UserIndicatorControllerProtocol,
appSettings: AppSettings) {
clientProxy = userSession.clientProxy
self.roomProxy = roomProxy
self.roomType = roomType
self.userDiscoveryService = userDiscoveryService
self.userIndicatorController = userIndicatorController
self.appSettings = appSettings
super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: [],
let mandatoryInvitees: [UserProfileProxy] = if case .draft(let invitees) = roomType { invitees } else { [] }
super.init(initialViewState: InviteUsersScreenViewState(selectedUsers: mandatoryInvitees,
mandatoryInvitees: mandatoryInvitees,
isSkippable: isSkippable),
mediaProvider: userSession.mediaProvider)
setupSubscriptions()
fetchMembersIfNeeded()
@@ -61,13 +64,18 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
case .cancel:
actionsSubject.send(.dismiss)
case .proceed:
guard roomProxy.details.historySharingState != RoomHistorySharingState.hidden,
!state.usersToConfirm.isEmpty,
!state.isSkippable else {
inviteUsers(state.selectedUsers.map(\.userID), roomProxy: roomProxy)
return
switch roomType {
case .draft:
createDraftRoom(mandatoryUserIDs: state.selectedUsers.map(\.userID))
case .existingRoom(let roomProxy):
guard roomProxy.details.historySharingState != RoomHistorySharingState.hidden,
!state.usersToConfirm.isEmpty,
!state.isSkippable else {
inviteUsers(state.selectedUsers.map(\.userID), roomProxy: roomProxy)
return
}
state.bindings.presentConfirmationDialog = true
}
state.bindings.presentConfirmationDialog = true
case .removeUnknownUsers:
state.bindings.presentConfirmationDialog = false
state.selectedUsers.removeAll { user in
@@ -77,7 +85,9 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
case .confirmUnknownUsers:
state.bindings.presentConfirmationDialog = false
state.usersToConfirm = []
inviteUsers(state.selectedUsers.map(\.userID), roomProxy: roomProxy)
if case .existingRoom(let roomProxy) = roomType {
inviteUsers(state.selectedUsers.map(\.userID), roomProxy: roomProxy)
}
case .toggleUser(let user):
toggleUser(user)
}
@@ -86,6 +96,8 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
// MARK: - Private
private func toggleUser(_ user: UserProfileProxy) {
guard !state.isInviteeMandatory(user) else { return }
if state.selectedUsers.contains(user) {
state.selectedUsers.removeAll { $0.userID == user.userID }
} else {
@@ -105,6 +117,29 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
}
}
private func createDraftRoom(mandatoryUserIDs: [String]) {
showLoadingIndicator(title: L10n.commonCreatingRoom)
Task {
defer { hideLoadingIndicator() }
switch await clientProxy.createRoom(name: nil,
topic: nil,
accessType: .private,
isSpace: false,
userIDs: mandatoryUserIDs,
avatarURL: nil,
aliasLocalPart: nil) {
case .success(let roomID):
actionsSubject.send(.openRoom(roomID: roomID))
case .failure:
state.bindings.alertInfo = .init(id: .unknown,
title: L10n.commonError,
message: L10n.screenStartChatErrorStartingChat)
}
}
}
private func inviteUsers(_ users: [String], roomProxy: JoinedRoomProxyProtocol) {
showLoadingIndicator(title: L10n.screenRoomDetailsInvitePeoplePreparing, message: L10n.screenRoomDetailsInvitePeopleDontClose)
@@ -168,6 +203,8 @@ class InviteUsersScreenViewModel: InviteUsersScreenViewModelType, InviteUsersScr
}
private func fetchMembersIfNeeded() {
guard case .existingRoom(let roomProxy) = roomType else { return }
Task {
showLoadingIndicator()
await roomProxy.updateMembers()