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
@@ -60,6 +60,13 @@ struct FocusEvent: Hashable {
let shouldSetPin: Bool
}
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)
}
// swiftlint:disable:next type_body_length
class RoomFlowCoordinator: FlowCoordinatorProtocol {
private let roomID: String
@@ -537,8 +544,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
presentMediaUploadPreviewScreen(for: mediaURLs, timelineController: timelineController, animated: animated)
case (_, .presentInviteUsersScreen, .inviteUsersScreen):
presentInviteUsersScreen()
case (_, .presentInviteUsersScreen(let flow), .inviteUsersScreen):
presentInviteUsersScreen(flow: flow)
case (_, .presentTransferOwnershipScreen, .transferOwnershipScreen):
presentTransferOwnershipScreen()
@@ -955,7 +962,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
case .presentNotificationSettingsScreen:
stateMachine.tryEvent(.presentNotificationSettingsScreen)
case .presentInviteUsersScreen:
stateMachine.tryEvent(.presentInviteUsersScreen)
stateMachine.tryEvent(.presentInviteUsersScreen(flow: .existingRoom))
case .presentInviteToNewRoom(let mandatoryInvitee):
stateMachine.tryEvent(.presentInviteUsersScreen(flow: .newRoom(mandatoryInvitee: mandatoryInvitee)))
case .presentPollsHistory:
stateMachine.tryEvent(.presentPollsHistory)
case .presentRolesAndPermissionsScreen:
@@ -1326,10 +1335,16 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
}
}
private func presentInviteUsersScreen() {
private func presentInviteUsersScreen(flow: InviteUsersFlow = .existingRoom) {
let stackCoordinator = NavigationStackCoordinator()
let roomType: InviteUsersScreenRoomType = switch flow {
case .existingRoom: .existingRoom(roomProxy: roomProxy)
case .newRoom(let mandatoryInvitee): .draft(mandatoryInvitees: [mandatoryInvitee])
}
let inviteParameters = InviteUsersScreenCoordinatorParameters(userSession: userSession,
roomProxy: roomProxy,
roomType: roomType,
isSkippable: false,
userDiscoveryService: UserDiscoveryService(clientProxy: userSession.clientProxy),
userIndicatorController: flowParameters.userIndicatorController,
@@ -1344,6 +1359,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .dismiss:
navigationStackCoordinator.setSheetCoordinator(nil)
case .openRoom(let roomID):
guard case .newRoom = flow else { return }
navigationStackCoordinator.setSheetCoordinator(nil)
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room))
}
}
.store(in: &cancellables)
@@ -65,7 +65,7 @@ extension RoomFlowCoordinator {
case roomDetailsEditScreen
case notificationSettings
case globalNotificationSettings
case inviteUsersScreen(previousState: State)
case inviteUsersScreen(flow: InviteUsersFlow, previousState: State)
case mediaUploadPicker(mode: MediaPickerScreenMode, previousState: State)
case mediaUploadPreview(mediaURLs: [URL], previousState: State)
case emojiPicker(itemID: TimelineItemIdentifier, selectedEmojis: Set<String>, previousState: State)
@@ -136,7 +136,7 @@ extension RoomFlowCoordinator {
case presentGlobalNotificationSettingsScreen
case dismissGlobalNotificationSettingsScreen
case presentInviteUsersScreen
case presentInviteUsersScreen(flow: InviteUsersFlow)
case dismissInviteUsersScreen
case presentMediaUploadPicker(mode: MediaPickerScreenMode)
@@ -404,9 +404,9 @@ extension RoomFlowCoordinator {
case (.mediaUploadPicker(_, let previousMediaUploadPickerState), .presentMediaUploadPreview(let mediaURLs)):
return .mediaUploadPreview(mediaURLs: mediaURLs, previousState: previousMediaUploadPickerState)
case (_, .presentInviteUsersScreen):
return .inviteUsersScreen(previousState: fromState)
case (.inviteUsersScreen(let previousState), .dismissInviteUsersScreen):
case (_, .presentInviteUsersScreen(let flow)):
return .inviteUsersScreen(flow: flow, previousState: fromState)
case (.inviteUsersScreen(_, let previousState), .dismissInviteUsersScreen):
return previousState
case (_, .presentTransferOwnershipScreen):
@@ -261,7 +261,7 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol {
private func presentInviteUsersScreen() {
let stackCoordinator = NavigationStackCoordinator()
let inviteParameters = InviteUsersScreenCoordinatorParameters(userSession: flowParameters.userSession,
roomProxy: roomProxy,
roomType: .existingRoom(roomProxy: roomProxy),
isSkippable: false,
userDiscoveryService: UserDiscoveryService(clientProxy: flowParameters.userSession.clientProxy),
userIndicatorController: flowParameters.userIndicatorController,
@@ -276,6 +276,8 @@ final class RoomMembersFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .dismiss:
navigationStackCoordinator.setSheetCoordinator(nil)
case .openRoom:
break
}
}
.store(in: &cancellables)
@@ -240,7 +240,7 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol {
case .transferOwnership:
stateMachine.tryEvent(.presentTransferOwnership)
case .presentRecipientDetails, .presentNotificationSettingsScreen, .presentReportRoomScreen,
.presentInviteUsersScreen, .presentPollsHistory, .presentCall,
.presentInviteUsersScreen, .presentInviteToNewRoom, .presentPollsHistory, .presentCall,
.presentPinnedEventsTimeline, .presentMediaEventsTimeline, .presentKnockingRequestsListScreen:
fatalError("Not handled in the space context")
}
@@ -270,7 +270,7 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol {
private func presentInviteUsersScreen(roomProxy: JoinedRoomProxyProtocol, spaceRoomListProxy: SpaceRoomListProxyProtocol?) {
let inviteParameters = InviteUsersScreenCoordinatorParameters(userSession: flowParameters.userSession,
roomProxy: roomProxy,
roomType: .existingRoom(roomProxy: roomProxy),
isSkippable: true,
userDiscoveryService: userDiscoveryService,
userIndicatorController: flowParameters.userIndicatorController,
@@ -285,6 +285,8 @@ class StartChatFlowCoordinator: FlowCoordinatorProtocol {
} else {
actionsSubject.send(.finished(.room(id: roomProxy.id)))
}
case .openRoom:
break
}
}
.store(in: &cancellables)