Move presentation and coordination logic from the RoomDetailsScreenCoordinator and into the RoomFlowCoordinator

This commit is contained in:
Stefan Ceriu
2023-11-29 10:13:49 +02:00
committed by Stefan Ceriu
parent 9a8c4d4ae5
commit 742a924037
5 changed files with 286 additions and 216 deletions
@@ -19,26 +19,23 @@ import SwiftUI
struct RoomDetailsScreenCoordinatorParameters {
let accountUserID: String
weak var navigationStackCoordinator: NavigationStackCoordinator?
let roomProxy: RoomProxyProtocol
let mediaProvider: MediaProviderProtocol
let userDiscoveryService: UserDiscoveryServiceProtocol
let userIndicatorController: UserIndicatorControllerProtocol
let notificationSettings: NotificationSettingsProxyProtocol
}
enum RoomDetailsScreenCoordinatorAction {
case leftRoom
case presentRoomMembersList
case presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol)
case presentNotificationSettingsScreen
case presentInviteUsersScreen
}
final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
private let parameters: RoomDetailsScreenCoordinatorParameters
private var viewModel: RoomDetailsScreenViewModelProtocol
private let selectedUsers: CurrentValueSubject<[UserProfileProxy], Never> = .init([])
private var navigationStackCoordinator: NavigationStackCoordinator? {
parameters.navigationStackCoordinator
}
private let actionsSubject: PassthroughSubject<RoomDetailsScreenCoordinatorAction, Never> = .init()
private var cancellables = Set<AnyCancellable>()
@@ -66,15 +63,15 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
switch action {
case .requestMemberDetailsPresentation:
presentRoomMembersList()
actionsSubject.send(.presentRoomMembersList)
case .requestInvitePeoplePresentation:
presentInviteUsersScreen()
actionsSubject.send(.presentInviteUsersScreen)
case .leftRoom:
actionsSubject.send(.leftRoom)
case .requestEditDetailsPresentation(let accountOwner):
presentRoomDetailsEditScreen(accountOwner: accountOwner)
actionsSubject.send(.presentRoomDetailsEditScreen(accountOwner: accountOwner))
case .requestNotificationSettingsPresentation:
presentNotificationSettings()
actionsSubject.send(.presentNotificationSettingsScreen)
}
}
.store(in: &cancellables)
@@ -87,144 +84,4 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
func toPresentable() -> AnyView {
AnyView(RoomDetailsScreen(context: viewModel.context))
}
// MARK: - Private
private func presentRoomMembersList() {
let params = RoomMembersListScreenCoordinatorParameters(navigationStackCoordinator: navigationStackCoordinator,
mediaProvider: parameters.mediaProvider,
roomProxy: parameters.roomProxy)
let coordinator = RoomMembersListScreenCoordinator(parameters: params)
coordinator.actions
.sink { [weak self] action in
guard let self else { return }
switch action {
case .invite:
presentInviteUsersScreen()
}
}
.store(in: &cancellables)
navigationStackCoordinator?.push(coordinator)
}
private func presentInviteUsersScreen() {
let inviteUsersStackCoordinator = NavigationStackCoordinator()
let inviteParameters = InviteUsersScreenCoordinatorParameters(selectedUsers: .init(selectedUsers),
roomType: .room(roomProxy: parameters.roomProxy),
mediaProvider: parameters.mediaProvider,
userDiscoveryService: parameters.userDiscoveryService,
userIndicatorController: parameters.userIndicatorController)
let coordinator = InviteUsersScreenCoordinator(parameters: inviteParameters)
inviteUsersStackCoordinator.setRootCoordinator(coordinator)
coordinator.actions.sink { [weak self] action in
guard let self else { return }
switch action {
case .cancel:
navigationStackCoordinator?.setSheetCoordinator(nil)
case .proceed:
break
case .invite(let users):
self.inviteUsers(users, in: parameters.roomProxy)
case .toggleUser(let user):
self.toggleUser(user)
}
}
.store(in: &cancellables)
navigationStackCoordinator?.setSheetCoordinator(inviteUsersStackCoordinator) { [weak self] in
self?.selectedUsers.value = []
}
}
private func presentRoomDetailsEditScreen(accountOwner: RoomMemberProxyProtocol) {
let navigationStackCoordinator = NavigationStackCoordinator()
let roomDetailsEditParameters = RoomDetailsEditScreenCoordinatorParameters(accountOwner: accountOwner,
mediaProvider: parameters.mediaProvider,
navigationStackCoordinator: navigationStackCoordinator,
roomProxy: parameters.roomProxy,
userIndicatorController: parameters.userIndicatorController)
let roomDetailsEditCoordinator = RoomDetailsEditScreenCoordinator(parameters: roomDetailsEditParameters)
roomDetailsEditCoordinator.actions.sink { [weak self] action in
switch action {
case .dismiss:
self?.navigationStackCoordinator?.setSheetCoordinator(nil)
}
}
.store(in: &cancellables)
navigationStackCoordinator.setRootCoordinator(roomDetailsEditCoordinator)
self.navigationStackCoordinator?.setSheetCoordinator(navigationStackCoordinator)
}
private func toggleUser(_ user: UserProfileProxy) {
var selectedUsers = selectedUsers.value
if let index = selectedUsers.firstIndex(where: { $0.userID == user.userID }) {
selectedUsers.remove(at: index)
} else {
selectedUsers.append(user)
}
self.selectedUsers.send(selectedUsers)
}
private func inviteUsers(_ users: [String], in room: RoomProxyProtocol) {
navigationStackCoordinator?.setSheetCoordinator(nil)
Task {
let result: Result<Void, RoomProxyError> = await withTaskGroup(of: Result<Void, RoomProxyError>.self) { group in
for user in users {
group.addTask {
await room.invite(userID: user)
}
}
return await group.first { inviteResult in
inviteResult.isFailure
} ?? .success(())
}
guard case .failure = result else {
return
}
parameters.userIndicatorController.alertInfo = .init(id: .init(),
title: L10n.commonUnableToInviteTitle,
message: L10n.commonUnableToInviteMessage)
}
}
private func presentNotificationSettings() {
let roomNotificationSettingsParameters = RoomNotificationSettingsScreenCoordinatorParameters(navigationStackCoordinator: parameters.navigationStackCoordinator,
notificationSettingsProxy: parameters.notificationSettings,
roomProxy: parameters.roomProxy,
displayAsUserDefinedRoomSettings: false)
let roomNotificationSettingsCoordinator = RoomNotificationSettingsScreenCoordinator(parameters: roomNotificationSettingsParameters)
roomNotificationSettingsCoordinator.actions.sink { [weak self] actions in
switch actions {
case .presentNotificationSettingsScreen:
self?.actionsSubject.send(.presentNotificationSettingsScreen)
}
}
.store(in: &cancellables)
navigationStackCoordinator?.push(roomNotificationSettingsCoordinator)
}
}
private extension Result {
var isFailure: Bool {
switch self {
case .success:
return false
case .failure:
return true
}
}
}