Allow joined rooms to be pushed within a space. (#4460)

* Allow joined rooms to be pushed within a space.

* Push a room in the space flow tests.

Also fixes some snapshots stale snapshots.

* Show the selected space/room within a space and set a custom title view.
This commit is contained in:
Doug
2025-09-03 17:48:49 +01:00
committed by GitHub
parent 927aea4bfe
commit 53eb1c1718
28 changed files with 170 additions and 44 deletions
@@ -9,8 +9,10 @@ import Combine
import Foundation
import SwiftState
enum SpaceExplorerFlowCoordinatorAction: Equatable {
enum SpaceExplorerFlowCoordinatorAction {
case showSettings
case presentCallScreen(roomProxy: JoinedRoomProxyProtocol)
case verifyUser(userID: String)
}
class SpaceExplorerFlowCoordinator: FlowCoordinatorProtocol {
@@ -113,7 +115,7 @@ class SpaceExplorerFlowCoordinator: FlowCoordinatorProtocol {
private func presentSpaceList() {
let parameters = SpaceListScreenCoordinatorParameters(userSession: userSession,
selectedSpaceSubject: selectedSpaceSubject.asCurrentValuePublisher(),
selectedSpacePublisher: selectedSpaceSubject.asCurrentValuePublisher(),
userIndicatorController: flowParameters.userIndicatorController)
let coordinator = SpaceListScreenCoordinator(parameters: parameters)
coordinator.actionsPublisher
@@ -143,6 +145,10 @@ class SpaceExplorerFlowCoordinator: FlowCoordinatorProtocol {
guard let self else { return }
switch action {
case .presentCallScreen(let roomProxy):
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
case .verifyUser(let userID):
actionsSubject.send(.verifyUser(userID: userID))
case .finished:
stateMachine.tryEvent(.deselectSpace)
}
@@ -9,7 +9,9 @@ import Combine
import Foundation
import SwiftState
enum SpaceFlowCoordinatorAction: Equatable {
enum SpaceFlowCoordinatorAction {
case presentCallScreen(roomProxy: JoinedRoomProxyProtocol)
case verifyUser(userID: String)
case finished
}
@@ -20,17 +22,22 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
private let navigationStackCoordinator: NavigationStackCoordinator
private var childSpaceFlowCoordinator: SpaceFlowCoordinator?
private let flowParameters: CommonFlowParameters
private let selectedSpaceRoomSubject: CurrentValueSubject<String?, Never> = .init(nil)
private var childSpaceFlowCoordinator: SpaceFlowCoordinator?
private var roomFlowCoordinator: RoomFlowCoordinator?
indirect enum State: StateType {
/// The state machine hasn't started.
case initial
/// The root screen for this flow.
case space
/// A child flow is in progress.
/// A child (space) flow is in progress.
case presentingChild(childSpaceID: String, previousState: State)
/// A room flow is in progress
case roomFlow(previousState: State)
}
enum Event: EventType {
@@ -43,6 +50,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
case startChildFlow
/// Tidy-up the child flow after it has dismissed itself.
case stopChildFlow
case startRoomFlow(roomID: String)
case stopRoomFlow
}
private let stateMachine: StateMachine<State, Event>
@@ -91,6 +101,9 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
case .presentingChild:
childSpaceFlowCoordinator?.clearRoute(animated: animated)
clearRoute(animated: animated) // Re-run with the state machine back in the .space state.
case .roomFlow:
roomFlowCoordinator?.clearRoute(animated: animated)
clearRoute(animated: animated) // Re-run with the state machine back in the .space state.
}
}
@@ -116,6 +129,24 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
} handler: { [weak self] _ in
guard let self else { return }
childSpaceFlowCoordinator = nil
selectedSpaceRoomSubject.send(nil)
}
stateMachine.addRouteMapping { event, fromState, _ in
guard case .startRoomFlow = event, case .space = fromState else { return nil }
return .roomFlow(previousState: fromState)
} handler: { [weak self] context in
guard let self, case let .startRoomFlow(roomID) = context.event else { return }
startRoomFlow(roomID: roomID)
}
stateMachine.addRouteMapping { event, fromState, _ in
guard event == .stopRoomFlow, case let .roomFlow(previousState) = fromState else { return nil }
return previousState
} handler: { [weak self] _ in
guard let self else { return }
roomFlowCoordinator = nil
selectedSpaceRoomSubject.send(nil)
}
stateMachine.addErrorHandler { context in
@@ -126,6 +157,7 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
private func presentSpace() {
let parameters = SpaceScreenCoordinatorParameters(spaceRoomListProxy: spaceRoomListProxy,
spaceServiceProxy: spaceServiceProxy,
selectedSpaceRoomPublisher: selectedSpaceRoomSubject.asCurrentValuePublisher(),
mediaProvider: flowParameters.userSession.mediaProvider,
userIndicatorController: flowParameters.userIndicatorController)
let coordinator = SpaceScreenCoordinator(parameters: parameters)
@@ -135,6 +167,8 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .selectSpace(let spaceRoomListProxy):
stateMachine.tryEvent(.startChildFlow, userInfo: spaceRoomListProxy)
case .selectRoom(let roomID):
stateMachine.tryEvent(.startRoomFlow(roomID: roomID))
}
}
.store(in: &cancellables)
@@ -164,6 +198,10 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
guard let self else { return }
switch action {
case .presentCallScreen(let roomProxy):
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
case .verifyUser(let userID):
actionsSubject.send(.verifyUser(userID: userID))
case .finished:
stateMachine.tryEvent(.stopChildFlow)
}
@@ -172,5 +210,31 @@ class SpaceFlowCoordinator: FlowCoordinatorProtocol {
childSpaceFlowCoordinator = coordinator
coordinator.start()
selectedSpaceRoomSubject.send(spaceRoomListProxy.spaceRoomProxy.id)
}
private func startRoomFlow(roomID: String) {
let coordinator = RoomFlowCoordinator(roomID: roomID,
isChildFlow: true,
navigationStackCoordinator: navigationStackCoordinator,
flowParameters: flowParameters)
coordinator.actions
.sink { [weak self] action in
guard let self else { return }
switch action {
case .presentCallScreen(let roomProxy):
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
case .verifyUser(let userID):
actionsSubject.send(.verifyUser(userID: userID))
case .finished:
stateMachine.tryEvent(.stopRoomFlow)
}
}
.store(in: &cancellables)
roomFlowCoordinator = coordinator
coordinator.handleAppRoute(.room(roomID: roomID, via: []), animated: true)
selectedSpaceRoomSubject.send(roomID)
}
}
@@ -217,6 +217,10 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
.sink { [weak self] action in
guard let self else { return }
switch action {
case .presentCallScreen(let roomProxy):
presentCallScreen(roomProxy: roomProxy)
case .verifyUser(let userID):
presentSessionVerificationScreen(flow: .userInitiator(userID: userID))
case .showSettings:
stateMachine.tryEvent(.showSettingsScreen)
}