mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Membership aware room routes (#2709)
* Remove the invites button when room list invites are enabled * element-hq/element-x-ios/issues/2632 - Handle room permalinks based on their membership state and show the according room joining screens: - modify the room flow coordinator to only take a roomID and be able to decide its own room flows (especially for unjoined rooms) - add support for the new room preview API - have RoomDirectorySearch go through the same paths
This commit is contained in:
@@ -40,7 +40,7 @@ enum RoomFlowCoordinatorAction: Equatable {
|
||||
|
||||
// swiftlint:disable file_length
|
||||
class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private let roomID: String
|
||||
private let userSession: UserSessionProtocol
|
||||
private let isChildFlow: Bool
|
||||
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol
|
||||
@@ -52,6 +52,10 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let orientationManager: OrientationManagerProtocol
|
||||
|
||||
private var roomProxy: RoomProxyProtocol!
|
||||
|
||||
private weak var joinRoomScreenCoordinator: JoinRoomScreenCoordinator?
|
||||
|
||||
// periphery:ignore - used to avoid deallocation
|
||||
private var rolesAndPermissionsFlowCoordinator: RoomRolesAndPermissionsFlowCoordinator?
|
||||
// periphery:ignore - used to avoid deallocation
|
||||
@@ -68,7 +72,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
private var timelineController: RoomTimelineControllerProtocol?
|
||||
|
||||
init(roomProxy: RoomProxyProtocol,
|
||||
init(roomID: String,
|
||||
userSession: UserSessionProtocol,
|
||||
isChildFlow: Bool,
|
||||
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol,
|
||||
@@ -79,7 +83,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
analytics: AnalyticsService,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
orientationManager: OrientationManagerProtocol) async {
|
||||
self.roomProxy = roomProxy
|
||||
self.roomID = roomID
|
||||
self.userSession = userSession
|
||||
self.isChildFlow = isChildFlow
|
||||
self.roomTimelineControllerFactory = roomTimelineControllerFactory
|
||||
@@ -91,14 +95,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.orientationManager = orientationManager
|
||||
|
||||
// The SDK needs to handle multiple subscription calls before we can start adding child room flows.
|
||||
let subscriptionTask = Task { await roomProxy.subscribeForUpdates() }
|
||||
|
||||
setupStateMachine()
|
||||
|
||||
analytics.signpost.beginRoomFlow(roomProxy.id)
|
||||
|
||||
_ = await subscriptionTask.result
|
||||
analytics.signpost.beginRoomFlow(roomID)
|
||||
}
|
||||
|
||||
// MARK: - FlowCoordinatorProtocol
|
||||
@@ -110,21 +109,31 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
func handleAppRoute(_ appRoute: AppRoute, animated: Bool) {
|
||||
switch appRoute {
|
||||
case .room(let roomID):
|
||||
guard roomID == roomProxy.id else { fatalError("Navigation route doesn't belong to this room flow.") }
|
||||
stateMachine.tryEvent(.presentRoom, userInfo: EventUserInfo(animated: animated))
|
||||
Task {
|
||||
await handleRoomRoute(roomID: roomID, animated: animated)
|
||||
}
|
||||
case .childRoom(let roomID):
|
||||
if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator {
|
||||
childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
|
||||
} else if roomID != roomProxy.id {
|
||||
stateMachine.tryEvent(.presentChildRoom(roomID: roomID), userInfo: EventUserInfo(animated: animated))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID), userInfo: EventUserInfo(animated: animated))
|
||||
} else {
|
||||
MXLog.info("Ignoring presentation of the same room as a child of this one.")
|
||||
}
|
||||
case .roomDetails(let roomID):
|
||||
guard roomID == roomProxy.id else { fatalError("Navigation route doesn't belong to this room flow.") }
|
||||
stateMachine.tryEvent(.presentRoomDetails, userInfo: EventUserInfo(animated: animated))
|
||||
case .roomList:
|
||||
stateMachine.tryEvent(.dismissRoom, userInfo: EventUserInfo(animated: animated))
|
||||
guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") }
|
||||
|
||||
Task {
|
||||
if roomProxy == nil {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
return
|
||||
}
|
||||
|
||||
await storeAndSubscribeToRoomProxy(roomProxy)
|
||||
}
|
||||
|
||||
stateMachine.tryEvent(.presentRoomDetails, userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
case .roomMemberDetails(let userID):
|
||||
// Always assume this will be presented on the child, external permalinks to a user aren't for a room member.
|
||||
if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator {
|
||||
@@ -132,27 +141,68 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
} else {
|
||||
stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID), userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
case .userProfile, .genericCallLink, .oidcCallback, .settings, .chatBackupSettings:
|
||||
case .roomList, .userProfile, .genericCallLink, .oidcCallback, .settings, .chatBackupSettings:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRoomRoute(roomID: String, animated: Bool) async {
|
||||
guard roomID == self.roomID else { fatalError("Navigation route doesn't belong to this room flow.") }
|
||||
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
stateMachine.tryEvent(.presentJoinRoomScreen, userInfo: EventUserInfo(animated: animated))
|
||||
return
|
||||
}
|
||||
|
||||
switch roomProxy.membership {
|
||||
case .joined:
|
||||
await storeAndSubscribeToRoomProxy(roomProxy)
|
||||
stateMachine.tryEvent(.presentRoom, userInfo: EventUserInfo(animated: animated))
|
||||
default:
|
||||
stateMachine.tryEvent(.presentJoinRoomScreen, userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
}
|
||||
|
||||
func clearRoute(animated: Bool) {
|
||||
guard stateMachine.state != .initial else {
|
||||
return
|
||||
}
|
||||
stateMachine.tryEvent(.dismissRoom, userInfo: EventUserInfo(animated: animated))
|
||||
|
||||
stateMachine.tryEvent(.dismissFlow, userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func storeAndSubscribeToRoomProxy(_ roomProxy: RoomProxyProtocol) async {
|
||||
if let oldRoomProxy = self.roomProxy {
|
||||
if oldRoomProxy.id != roomProxy.id {
|
||||
fatalError("Trying to create different room proxies for the same flow coordinator")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
guard roomProxy.membership == .joined else {
|
||||
fatalError("Requesting room details for an unjoined room")
|
||||
}
|
||||
|
||||
self.roomProxy = roomProxy
|
||||
|
||||
await roomProxy.subscribeForUpdates()
|
||||
}
|
||||
|
||||
// swiftlint:disable:next function_body_length
|
||||
private func setupStateMachine() {
|
||||
stateMachine.addRouteMapping { event, fromState, _ in
|
||||
switch (fromState, event) {
|
||||
case (_, .presentJoinRoomScreen):
|
||||
return .joinRoomScreen
|
||||
case (_, .dismissJoinRoomScreen):
|
||||
return .complete
|
||||
|
||||
case (_, .presentRoom):
|
||||
return .room
|
||||
case (_, .dismissRoom):
|
||||
case (_, .dismissFlow):
|
||||
return .complete
|
||||
|
||||
case (.initial, .presentRoomDetails):
|
||||
@@ -255,9 +305,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// Child flow
|
||||
|
||||
case (_, .presentChildRoom(let roomID)):
|
||||
case (_, .startChildFlow(let roomID)):
|
||||
return .presentingChild(childRoomID: roomID, previousState: fromState)
|
||||
case (.presentingChild(_, let previousState), .dismissChildRoom):
|
||||
case (.presentingChild(_, let previousState), .dismissChildFlow):
|
||||
return previousState
|
||||
|
||||
default:
|
||||
@@ -271,9 +321,14 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
let animated = (context.userInfo as? EventUserInfo)?.animated ?? true
|
||||
|
||||
switch (context.fromState, context.event, context.toState) {
|
||||
case (_, .presentJoinRoomScreen, .joinRoomScreen):
|
||||
presentJoinRoomScreen(animated: true)
|
||||
case (_, .dismissJoinRoomScreen, .complete):
|
||||
dismissFlow(animated: animated)
|
||||
|
||||
case (_, .presentRoom, .room):
|
||||
Task { await self.presentRoom(animated: animated) }
|
||||
case (_, .dismissRoom, .complete):
|
||||
case (_, .dismissFlow, .complete):
|
||||
dismissFlow(animated: animated)
|
||||
|
||||
case (.initial, .presentRoomDetails, .roomDetails(let isRoot)),
|
||||
@@ -381,9 +436,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
rolesAndPermissionsFlowCoordinator = nil
|
||||
|
||||
// Child flow
|
||||
case (_, .presentChildRoom(let roomID), .presentingChild):
|
||||
Task { await self.presentChildFlow(for: roomID) }
|
||||
case (.presentingChild, .dismissChildRoom, _):
|
||||
case (_, .startChildFlow(let roomID), .presentingChild):
|
||||
Task { await self.startChildFlow(for: roomID) }
|
||||
case (.presentingChild, .dismissChildFlow, _):
|
||||
childRoomFlowCoordinator = nil
|
||||
|
||||
default:
|
||||
@@ -479,27 +534,84 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
if !isChildFlow {
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator, animated: animated) { [weak self] in
|
||||
self?.stateMachine.tryEvent(.dismissRoom)
|
||||
self?.stateMachine.tryEvent(.dismissFlow)
|
||||
}
|
||||
} else {
|
||||
if joinRoomScreenCoordinator != nil {
|
||||
navigationStackCoordinator.pop()
|
||||
}
|
||||
|
||||
navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in
|
||||
self?.stateMachine.tryEvent(.dismissFlow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func presentJoinRoomScreen(animated: Bool) {
|
||||
let coordinator = JoinRoomScreenCoordinator(parameters: .init(roomID: roomID,
|
||||
clientProxy: userSession.clientProxy,
|
||||
mediaProvider: userSession.mediaProvider,
|
||||
userIndicatorController: userIndicatorController))
|
||||
|
||||
joinRoomScreenCoordinator = coordinator
|
||||
|
||||
coordinator.actionsPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .joined:
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
if let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) {
|
||||
await storeAndSubscribeToRoomProxy(roomProxy)
|
||||
stateMachine.tryEvent(.presentRoom, userInfo: EventUserInfo(animated: animated))
|
||||
|
||||
analytics.trackJoinedRoom(isDM: roomProxy.isDirect, isSpace: roomProxy.isSpace, activeMemberCount: UInt(roomProxy.activeMembersCount))
|
||||
} else {
|
||||
stateMachine.tryEvent(.dismissFlow, userInfo: EventUserInfo(animated: animated))
|
||||
}
|
||||
}
|
||||
case .cancelled:
|
||||
stateMachine.tryEvent(.dismissJoinRoomScreen)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
if !isChildFlow {
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator, animated: animated) { [weak self] in
|
||||
if self?.stateMachine.state == .joinRoomScreen {
|
||||
self?.stateMachine.tryEvent(.dismissJoinRoomScreen)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in
|
||||
self?.stateMachine.tryEvent(.dismissRoom)
|
||||
if self?.stateMachine.state == .joinRoomScreen {
|
||||
self?.stateMachine.tryEvent(.dismissJoinRoomScreen)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func dismissFlow(animated: Bool) {
|
||||
childRoomFlowCoordinator?.handleAppRoute(.roomList, animated: animated)
|
||||
childRoomFlowCoordinator?.clearRoute(animated: animated)
|
||||
|
||||
if isChildFlow {
|
||||
// We don't support dismissing a child flow by itself, only the entire chain.
|
||||
MXLog.info("Leaving navigation clean-up to the parent flow.")
|
||||
MXLog.info("Leaving the rest of the navigation clean-up to the parent flow.")
|
||||
|
||||
if joinRoomScreenCoordinator != nil {
|
||||
navigationStackCoordinator.pop()
|
||||
}
|
||||
} else {
|
||||
navigationStackCoordinator.popToRoot(animated: false)
|
||||
navigationStackCoordinator.setRootCoordinator(nil, animated: false)
|
||||
}
|
||||
|
||||
roomProxy.unsubscribeFromUpdates()
|
||||
roomProxy?.unsubscribeFromUpdates()
|
||||
|
||||
timelineController = nil
|
||||
|
||||
actionsSubject.send(.finished)
|
||||
@@ -520,7 +632,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch action {
|
||||
case .leftRoom:
|
||||
stateMachine.tryEvent(.dismissRoom)
|
||||
stateMachine.tryEvent(.dismissFlow)
|
||||
case .presentRoomMembersList:
|
||||
stateMachine.tryEvent(.presentRoomMembersList)
|
||||
case .presentRoomDetailsEditScreen:
|
||||
@@ -539,7 +651,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
if isRoot {
|
||||
navigationStackCoordinator.setRootCoordinator(coordinator, animated: animated) { [weak self] in
|
||||
self?.stateMachine.tryEvent(.dismissRoom) // This seems wrong but it isn't, Maybe the event should be called dismissFlow?
|
||||
self?.stateMachine.tryEvent(.dismissFlow)
|
||||
}
|
||||
} else {
|
||||
navigationStackCoordinator.push(coordinator, animated: animated) { [weak self] in
|
||||
@@ -890,7 +1002,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case .openUserProfile:
|
||||
stateMachine.tryEvent(.presentUserProfile(userID: userID))
|
||||
case .openDirectChat(let roomID):
|
||||
stateMachine.tryEvent(.presentChildRoom(roomID: roomID))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID))
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -913,7 +1025,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch action {
|
||||
case .openDirectChat(let roomID):
|
||||
stateMachine.tryEvent(.presentChildRoom(roomID: roomID))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID))
|
||||
case .dismiss:
|
||||
break // Not supported when pushed.
|
||||
}
|
||||
@@ -983,7 +1095,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// We don't need to worry about passing in the room proxy as timelines are
|
||||
// cached. The local echo will be visible when fetching the room by its ID.
|
||||
stateMachine.tryEvent(.presentChildRoom(roomID: roomID))
|
||||
stateMachine.tryEvent(.startChildFlow(roomID: roomID))
|
||||
}
|
||||
|
||||
private func presentNotificationSettingsScreen() {
|
||||
@@ -1117,15 +1229,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// MARK: - Child Flow
|
||||
|
||||
private func presentChildFlow(for roomID: String) async {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
MXLog.error("Child flow requested for missing room.")
|
||||
userIndicatorController.submitIndicator(UserIndicator(title: L10n.errorUnknown))
|
||||
stateMachine.tryEvent(.dismissChildRoom)
|
||||
return
|
||||
}
|
||||
|
||||
let coordinator = await RoomFlowCoordinator(roomProxy: roomProxy,
|
||||
private func startChildFlow(for roomID: String) async {
|
||||
let coordinator = await RoomFlowCoordinator(roomID: roomID,
|
||||
userSession: userSession,
|
||||
isChildFlow: true,
|
||||
roomTimelineControllerFactory: roomTimelineControllerFactory,
|
||||
@@ -1145,7 +1250,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
case .presentCallScreen(let roomProxy):
|
||||
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
|
||||
case .finished:
|
||||
stateMachine.tryEvent(.dismissChildRoom)
|
||||
stateMachine.tryEvent(.dismissChildFlow)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -1170,6 +1275,7 @@ private extension RoomFlowCoordinator {
|
||||
|
||||
indirect enum State: StateType {
|
||||
case initial
|
||||
case joinRoomScreen
|
||||
case room
|
||||
case roomDetails(isRoot: Bool)
|
||||
case roomDetailsEditScreen
|
||||
@@ -1201,8 +1307,11 @@ private extension RoomFlowCoordinator {
|
||||
}
|
||||
|
||||
enum Event: EventType {
|
||||
case presentJoinRoomScreen
|
||||
case dismissJoinRoomScreen
|
||||
|
||||
case presentRoom
|
||||
case dismissRoom
|
||||
case dismissFlow
|
||||
|
||||
case presentReportContent(itemID: TimelineItemIdentifier, senderID: String)
|
||||
case dismissReportContent
|
||||
@@ -1256,8 +1365,8 @@ private extension RoomFlowCoordinator {
|
||||
case dismissRolesAndPermissionsScreen
|
||||
|
||||
// Child room flow events
|
||||
case presentChildRoom(roomID: String)
|
||||
case dismissChildRoom
|
||||
case startChildFlow(roomID: String)
|
||||
case dismissChildFlow
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,12 +183,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch appRoute {
|
||||
case .room(let roomID):
|
||||
Task { await self.handleRoomRoute(roomID: roomID, animated: animated) }
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
case .childRoom(let roomID):
|
||||
if let roomFlowCoordinator {
|
||||
roomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
|
||||
} else {
|
||||
Task { await self.handleRoomRoute(roomID: roomID, animated: animated) }
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
}
|
||||
case .roomDetails(let roomID):
|
||||
if stateMachine.state.selectedRoomID == roomID {
|
||||
@@ -196,12 +196,14 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
} else {
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: true), userInfo: .init(animated: animated))
|
||||
}
|
||||
case .roomList, .roomMemberDetails:
|
||||
self.roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
case .roomList:
|
||||
roomFlowCoordinator?.clearRoute(animated: animated)
|
||||
case .roomMemberDetails:
|
||||
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
|
||||
case .userProfile(let userID):
|
||||
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
|
||||
case .genericCallLink(let url):
|
||||
self.navigationSplitCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url)), animated: animated)
|
||||
navigationSplitCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url)), animated: animated)
|
||||
case .oidcCallback:
|
||||
break
|
||||
case .settings, .chatBackupSettings:
|
||||
@@ -210,23 +212,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRoomRoute(roomID: String, animated: Bool) async {
|
||||
switch await userSession.clientProxy.roomForIdentifier(roomID)?.membership {
|
||||
case .invited:
|
||||
if UIDevice.current.isPhone {
|
||||
roomFlowCoordinator?.clearRoute(animated: animated)
|
||||
}
|
||||
stateMachine.processEvent(.showInvitesScreen, userInfo: .init(animated: animated))
|
||||
case .joined:
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false), userInfo: .init(animated: animated))
|
||||
case .left, .none:
|
||||
// Do nothing but maybe we should ask design to have some kind of error state
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func clearRoute(animated: Bool) {
|
||||
roomFlowCoordinator?.handleAppRoute(.roomList, animated: animated)
|
||||
roomFlowCoordinator?.clearRoute(animated: animated)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
@@ -262,14 +249,14 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
attemptStartingOnboarding()
|
||||
|
||||
case(.roomList, .selectRoom(let roomID, let showingRoomDetails), .roomList):
|
||||
Task { await self.presentRoomFlow(roomID: roomID, showingRoomDetails: showingRoomDetails, animated: animated) }
|
||||
Task { await self.startRoomFlow(roomID: roomID, showingRoomDetails: showingRoomDetails, animated: animated) }
|
||||
case(.roomList, .deselectRoom, .roomList):
|
||||
tearDownRoomFlow(animated: animated)
|
||||
dismissRoomFlow(animated: animated)
|
||||
|
||||
case (.invitesScreen, .selectRoom, .invitesScreen):
|
||||
break
|
||||
case (.invitesScreen, .deselectRoom, .invitesScreen):
|
||||
tearDownRoomFlow(animated: animated)
|
||||
dismissRoomFlow(animated: animated)
|
||||
|
||||
case (.roomList, .showSettingsScreen, .settingsScreen):
|
||||
break
|
||||
@@ -350,9 +337,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
switch action {
|
||||
case .presentRoom(let roomID):
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: false))
|
||||
handleAppRoute(.room(roomID: roomID), animated: true)
|
||||
case .presentRoomDetails(let roomID):
|
||||
stateMachine.processEvent(.selectRoom(roomID: roomID, showingRoomDetails: true))
|
||||
handleAppRoute(.roomDetails(roomID: roomID), animated: true)
|
||||
case .roomLeft(let roomID):
|
||||
if case .roomList(selectedRoomID: let selectedRoomID) = stateMachine.state,
|
||||
selectedRoomID == roomID {
|
||||
@@ -430,13 +417,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
// MARK: Room Flow
|
||||
|
||||
private func presentRoomFlow(roomID: String, showingRoomDetails: Bool, animated: Bool) async {
|
||||
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||
MXLog.error("Invalid room ID: \(roomID)")
|
||||
return
|
||||
}
|
||||
|
||||
let coordinator = await RoomFlowCoordinator(roomProxy: roomProxy,
|
||||
private func startRoomFlow(roomID: String, showingRoomDetails: Bool, animated: Bool) async {
|
||||
let coordinator = await RoomFlowCoordinator(roomID: roomID,
|
||||
userSession: userSession,
|
||||
isChildFlow: false,
|
||||
roomTimelineControllerFactory: roomTimelineControllerFactory,
|
||||
@@ -486,7 +468,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private func tearDownRoomFlow(animated: Bool) {
|
||||
private func dismissRoomFlow(animated: Bool) {
|
||||
// THIS MUST BE CALLED *AFTER* THE FLOW HAS TIDIED UP THE STACK OR IT CAN CAUSE A CRASH.
|
||||
navigationSplitCoordinator.setDetailCoordinator(nil, animated: animated)
|
||||
roomFlowCoordinator = nil
|
||||
@@ -650,7 +632,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .joined(let roomID):
|
||||
case .select(let roomID):
|
||||
stateMachine.processEvent(.dismissedRoomDirectorySearchScreen)
|
||||
handleAppRoute(.room(roomID: roomID), animated: true)
|
||||
case .dismiss:
|
||||
|
||||
Reference in New Issue
Block a user