Make sure we pass the via parameters with all the routes.

Put the event ID first.

Fix tests.

Bump the SDK.
This commit is contained in:
Doug
2024-05-09 12:25:54 +01:00
committed by Stefan Ceriu
parent 52b6c25bd8
commit 1e0a6d76ae
23 changed files with 293 additions and 199 deletions
@@ -21,14 +21,11 @@ import UserNotifications
// swiftlint:disable file_length
enum RoomFlowCoordinatorAction: Equatable {
case presentRoom(roomID: String)
case presentCallScreen(roomProxy: RoomProxyProtocol)
case finished
static func == (lhs: RoomFlowCoordinatorAction, rhs: RoomFlowCoordinatorAction) -> Bool {
switch (lhs, rhs) {
case (.presentRoom(let lhsRoomID), .presentRoom(let rhsRoomID)):
lhsRoomID == rhsRoomID
case (.presentCallScreen(let lhsRoomProxy), .presentCallScreen(let rhsRoomProxy)):
lhsRoomProxy.id == rhsRoomProxy.id
case (.finished, .finished):
@@ -126,15 +123,15 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
}
switch appRoute {
case .room(let roomID):
case .room(let roomID, let via):
Task {
await handleRoomRoute(roomID: roomID, animated: animated)
await handleRoomRoute(roomID: roomID, via: via, animated: animated)
}
case .childRoom(let roomID):
case .childRoom(let roomID, let via):
if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator {
childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
} else if roomID != roomProxy.id {
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room), userInfo: EventUserInfo(animated: animated))
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: via, entryPoint: .room), userInfo: EventUserInfo(animated: animated))
} else {
MXLog.info("Ignoring presentation of the same room as a child of this one.")
}
@@ -159,13 +156,13 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
} else {
stateMachine.tryEvent(.presentRoomMemberDetails(userID: userID), userInfo: EventUserInfo(animated: animated))
}
case .event(let roomID, let eventID):
Task { await handleRoomRoute(roomID: roomID, focussedEventID: eventID, animated: animated) }
case .childEvent(let roomID, let eventID):
case .event(let eventID, let roomID, let via):
Task { await handleRoomRoute(roomID: roomID, via: via, focussedEventID: eventID, animated: animated) }
case .childEvent(let eventID, let roomID, let via):
if case .presentingChild = stateMachine.state, let childRoomFlowCoordinator {
childRoomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
} else if roomID != roomProxy.id {
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .eventID(eventID)), userInfo: EventUserInfo(animated: animated))
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: via, entryPoint: .eventID(eventID)), userInfo: EventUserInfo(animated: animated))
} else {
roomScreenCoordinator?.focusOnEvent(eventID: eventID)
}
@@ -184,11 +181,11 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
}
private func handleRoomRoute(roomID: String, focussedEventID: String? = nil, animated: Bool) async {
private func handleRoomRoute(roomID: String, via: [String], focussedEventID: String? = nil, 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))
stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated))
return
}
@@ -197,7 +194,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
await storeAndSubscribeToRoomProxy(roomProxy)
stateMachine.tryEvent(.presentRoom(focussedEventID: focussedEventID), userInfo: EventUserInfo(animated: animated))
default:
stateMachine.tryEvent(.presentJoinRoomScreen, userInfo: EventUserInfo(animated: animated))
stateMachine.tryEvent(.presentJoinRoomScreen(via: via), userInfo: EventUserInfo(animated: animated))
}
}
@@ -343,7 +340,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
// Child flow
case (_, .startChildFlow(let roomID, _)):
case (_, .startChildFlow(let roomID, _, _)):
return .presentingChild(childRoomID: roomID, previousState: fromState)
case (.presentingChild(_, let previousState), .dismissChildFlow):
return previousState
@@ -359,8 +356,8 @@ 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 (_, .presentJoinRoomScreen(let via), .joinRoomScreen):
presentJoinRoomScreen(via: via, animated: true)
case (_, .dismissJoinRoomScreen, .complete):
dismissFlow(animated: animated)
@@ -474,8 +471,8 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
rolesAndPermissionsFlowCoordinator = nil
// Child flow
case (_, .startChildFlow(let roomID, let entryPoint), .presentingChild):
Task { await self.startChildFlow(for: roomID, entryPoint: entryPoint) }
case (_, .startChildFlow(let roomID, let via, let entryPoint), .presentingChild):
Task { await self.startChildFlow(for: roomID, via: via, entryPoint: entryPoint) }
case (.presentingChild, .dismissChildFlow, _):
childRoomFlowCoordinator = nil
@@ -612,8 +609,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
}
}
private func presentJoinRoomScreen(animated: Bool) {
private func presentJoinRoomScreen(via: [String], animated: Bool) {
let coordinator = JoinRoomScreenCoordinator(parameters: .init(roomID: roomID,
via: via,
clientProxy: userSession.clientProxy,
mediaProvider: userSession.mediaProvider,
userIndicatorController: userIndicatorController))
@@ -1073,7 +1071,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
case .openUserProfile:
stateMachine.tryEvent(.presentUserProfile(userID: userID))
case .openDirectChat(let roomID):
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room))
case .startCall(let roomID):
Task { await self.presentCallScreen(roomID: roomID) }
}
@@ -1098,7 +1096,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .openDirectChat(let roomID):
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room))
case .startCall(let roomID):
Task { await self.presentCallScreen(roomID: roomID) }
case .dismiss:
@@ -1140,7 +1138,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
case .sent(let roomID):
navigationStackCoordinator.setSheetCoordinator(nil)
// Timelines are cached - the local echo will be visible when fetching the room by its ID.
stateMachine.tryEvent(.startChildFlow(roomID: roomID, entryPoint: .room))
stateMachine.tryEvent(.startChildFlow(roomID: roomID, via: [], entryPoint: .room))
}
}
.store(in: &cancellables)
@@ -1283,7 +1281,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
// MARK: - Child Flow
private func startChildFlow(for roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint) async {
private func startChildFlow(for roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint) async {
let coordinator = await RoomFlowCoordinator(roomID: roomID,
userSession: userSession,
isChildFlow: true,
@@ -1298,8 +1296,6 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
guard let self else { return }
switch action {
case .presentRoom(let roomID):
actionsSubject.send(.presentRoom(roomID: roomID))
case .presentCallScreen(let roomProxy):
actionsSubject.send(.presentCallScreen(roomProxy: roomProxy))
case .finished:
@@ -1311,9 +1307,9 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
childRoomFlowCoordinator = coordinator
switch entryPoint {
case .room:
coordinator.handleAppRoute(.room(roomID: roomID), animated: true)
coordinator.handleAppRoute(.room(roomID: roomID, via: via), animated: true)
case .eventID(let eventID):
coordinator.handleAppRoute(.event(roomID: roomID, eventID: eventID), animated: true)
coordinator.handleAppRoute(.event(eventID: eventID, roomID: roomID, via: via), animated: true)
case .roomDetails:
coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: true)
}
@@ -1367,7 +1363,7 @@ private extension RoomFlowCoordinator {
}
enum Event: EventType {
case presentJoinRoomScreen
case presentJoinRoomScreen(via: [String])
case dismissJoinRoomScreen
case presentRoom(focussedEventID: String?)
@@ -1425,7 +1421,7 @@ private extension RoomFlowCoordinator {
case dismissRolesAndPermissionsScreen
// Child room flow events
case startChildFlow(roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint)
case startChildFlow(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint)
case dismissChildFlow
}
}
@@ -200,40 +200,40 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
await clearPresentedSheets(animated: animated)
switch appRoute {
case .room(let roomID):
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room), userInfo: .init(animated: animated))
case .room(let roomID, let via):
stateMachine.processEvent(.selectRoom(roomID: roomID, via: via, entryPoint: .room), userInfo: .init(animated: animated))
case .roomAlias(let alias):
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.room(roomID: roomID), animated: animated)
case .childRoom(let roomID):
guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.room(roomID: resolved.roomId, via: resolved.servers), animated: animated)
case .childRoom(let roomID, let via):
if let roomFlowCoordinator {
roomFlowCoordinator.handleAppRoute(appRoute, animated: animated)
} else {
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room), userInfo: .init(animated: animated))
stateMachine.processEvent(.selectRoom(roomID: roomID, via: via, entryPoint: .room), userInfo: .init(animated: animated))
}
case .childRoomAlias(let alias):
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.childRoom(roomID: roomID), animated: animated)
guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.childRoom(roomID: resolved.roomId, via: resolved.servers), animated: animated)
case .roomDetails(let roomID):
if stateMachine.state.selectedRoomID == roomID {
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
} else {
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .roomDetails), userInfo: .init(animated: animated))
stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .roomDetails), userInfo: .init(animated: animated))
}
case .roomList:
roomFlowCoordinator?.clearRoute(animated: animated)
case .roomMemberDetails:
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
case .event(let roomID, let eventID):
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .eventID(eventID)), userInfo: .init(animated: animated))
case .eventOnRoomAlias(let alias, let eventID):
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.event(roomID: roomID, eventID: eventID), animated: animated)
case .event(let eventID, let roomID, let via):
stateMachine.processEvent(.selectRoom(roomID: roomID, via: via, entryPoint: .eventID(eventID)), userInfo: .init(animated: animated))
case .eventOnRoomAlias(let eventID, let alias):
guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.event(eventID: eventID, roomID: resolved.roomId, via: resolved.servers), animated: animated)
case .childEvent:
roomFlowCoordinator?.handleAppRoute(appRoute, animated: animated)
case .childEventOnRoomAlias(let alias, let eventID):
guard let roomID = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.childEvent(roomID: roomID, eventID: eventID), animated: animated)
case .childEventOnRoomAlias(let eventID, let alias):
guard let resolved = await userSession.clientProxy.resolveRoomAlias(alias) else { return }
await asyncHandleAppRoute(.childEvent(eventID: eventID, roomID: resolved.roomId, via: resolved.servers), animated: animated)
case .userProfile(let userID):
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
case .genericCallLink(let url):
@@ -271,18 +271,18 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
case (.initial, .start, .roomList):
presentHomeScreen()
attemptStartingOnboarding()
case(.roomList(let selectedRoomID), .selectRoom(let roomID, let entryPoint), .roomList):
case(.roomList(let selectedRoomID), .selectRoom(let roomID, let via, let entryPoint), .roomList):
if selectedRoomID == roomID,
!entryPoint.isEventID, // Don't reuse the existing room so the live timeline is hidden while the detached timeline is loading.
let roomFlowCoordinator {
let route: AppRoute = switch entryPoint {
case .room: .room(roomID: roomID)
case .room: .room(roomID: roomID, via: via)
case .roomDetails: .roomDetails(roomID: roomID)
case .eventID(let eventID): .event(roomID: roomID, eventID: eventID) // ignored.
case .eventID(let eventID): .event(eventID: eventID, roomID: roomID, via: via) // ignored.
}
roomFlowCoordinator.handleAppRoute(route, animated: animated)
} else {
Task { await self.startRoomFlow(roomID: roomID, entryPoint: entryPoint, animated: animated) }
Task { await self.startRoomFlow(roomID: roomID, via: via, entryPoint: entryPoint, animated: animated) }
}
case(.roomList, .deselectRoom, .roomList):
dismissRoomFlow(animated: animated)
@@ -359,7 +359,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .presentRoom(let roomID):
handleAppRoute(.room(roomID: roomID), animated: true)
handleAppRoute(.room(roomID: roomID, via: []), animated: true)
case .presentRoomDetails(let roomID):
handleAppRoute(.roomDetails(roomID: roomID), animated: true)
case .roomLeft(let roomID):
@@ -438,6 +438,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
// MARK: Room Flow
private func startRoomFlow(roomID: String,
via: [String],
entryPoint: RoomFlowCoordinatorEntryPoint,
animated: Bool) async {
let coordinator = await RoomFlowCoordinator(roomID: roomID,
@@ -455,12 +456,10 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
guard let self else { return }
switch action {
case .finished:
stateMachine.processEvent(.deselectRoom)
case .presentRoom(let roomID):
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
case .presentCallScreen(let roomProxy):
presentCallScreen(roomProxy: roomProxy)
case .finished:
stateMachine.processEvent(.deselectRoom)
}
}
.store(in: &cancellables)
@@ -473,9 +472,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
switch entryPoint {
case .room:
coordinator.handleAppRoute(.room(roomID: roomID), animated: animated)
coordinator.handleAppRoute(.room(roomID: roomID, via: via), animated: animated)
case .eventID(let eventID):
coordinator.handleAppRoute(.event(roomID: roomID, eventID: eventID), animated: animated)
coordinator.handleAppRoute(.event(eventID: eventID, roomID: roomID, via: via), animated: animated)
case .roomDetails:
coordinator.handleAppRoute(.roomDetails(roomID: roomID), animated: animated)
}
@@ -513,7 +512,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
self.navigationSplitCoordinator.setSheetCoordinator(nil)
case .openRoom(let roomID):
self.navigationSplitCoordinator.setSheetCoordinator(nil)
self.stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
self.stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room))
}
}
.store(in: &cancellables)
@@ -597,7 +596,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
dismissGlobalSearch()
case .select(let roomID):
dismissGlobalSearch()
handleAppRoute(.room(roomID: roomID), animated: true)
handleAppRoute(.room(roomID: roomID, via: []), animated: true)
}
}
.store(in: &cancellables)
@@ -627,9 +626,12 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
guard let self else { return }
switch action {
case .select(let roomID):
case .selectAlias(let alias):
stateMachine.processEvent(.dismissedRoomDirectorySearchScreen)
handleAppRoute(.room(roomID: roomID), animated: true)
handleAppRoute(.roomAlias(alias), animated: true)
case .selectRoomID(let roomID):
stateMachine.processEvent(.dismissedRoomDirectorySearchScreen)
handleAppRoute(.room(roomID: roomID, via: []), animated: true)
case .dismiss:
stateMachine.processEvent(.dismissedRoomDirectorySearchScreen)
}
@@ -662,7 +664,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
switch action {
case .openDirectChat(let roomID):
navigationSplitCoordinator.setSheetCoordinator(nil)
stateMachine.processEvent(.selectRoom(roomID: roomID, entryPoint: .room))
stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room))
case .startCall(let roomID):
Task { await self.presentCallScreen(roomID: roomID) }
case .dismiss:
@@ -70,10 +70,11 @@ class UserSessionFlowCoordinatorStateMachine {
/// Start the user session flows.
case start
/// Request presentation for a particular room
/// - Parameter roomID: The room identifier
/// Request presentation for a particular room.
/// - Parameter roomID: The room identifier.
/// - Parameter via: Any servers necessary to discover the room.
/// - Parameter entryPoint: The starting point for the presented room.
case selectRoom(roomID: String, entryPoint: RoomFlowCoordinatorEntryPoint)
case selectRoom(roomID: String, via: [String], entryPoint: RoomFlowCoordinatorEntryPoint)
/// The room screen has been dismissed
case deselectRoom
@@ -129,7 +130,7 @@ class UserSessionFlowCoordinatorStateMachine {
stateMachine.addRouteMapping { event, fromState, _ in
switch (fromState, event) {
case (.roomList, .selectRoom(let roomID, _)):
case (.roomList, .selectRoom(let roomID, _, _)):
return .roomList(selectedRoomID: roomID)
case (.roomList, .deselectRoom):
return .roomList(selectedRoomID: nil)