Files
letro-ios/ElementX/Sources/Services/UserSession/UserSessionFlowCoordinatorStateMachine.swift
Gil Eluard 49159c4ac1 430 - Design review for first public TestFlight Part2 (#496)
* 430 - Design review for first public TestFlight Part2

---------

Co-authored-by: Doug <douglase@element.io>
2023-01-30 11:51:07 +00:00

142 lines
5.3 KiB
Swift

//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
import SwiftState
class UserSessionFlowCoordinatorStateMachine {
/// States the AppCoordinator can find itself in
enum State: StateType {
/// The initial state, used before the coordinator starts
case initial
/// Showing the home screen
case roomList(selectedRoomId: String?)
/// Showing the session verification flows
case sessionVerificationScreen(selectedRoomId: String?)
/// Showing the session verification flows
case feedbackScreen(selectedRoomId: String?)
/// Showing the settings screen
case settingsScreen(selectedRoomId: String?)
}
/// Events that can be triggered on the AppCoordinator state machine
enum Event: EventType {
/// Start the user session flows
case start
/// Request presentation for a particular room
/// - Parameter roomId:the room identifier
case selectRoom(roomId: String)
/// The room screen has been dismissed
case deselectRoom
/// Request presentation of the settings screen
case showSettingsScreen
/// The settings screen has been dismissed
case dismissedSettingsScreen
/// Request presentation of the feedback screen
case feedbackScreen
/// The feedback screen has been dismissed
case dismissedFeedbackScreen
/// Request the start of the session verification flow
case showSessionVerificationScreen
/// Session verification has finished
case dismissedSessionVerificationScreen
}
private let stateMachine: StateMachine<State, Event>
var state: UserSessionFlowCoordinatorStateMachine.State {
stateMachine.state
}
init() {
stateMachine = StateMachine(state: .initial)
configure()
}
private func configure() {
stateMachine.addRoutes(event: .start, transitions: [.initial => .roomList(selectedRoomId: nil)])
stateMachine.addRouteMapping { event, fromState, _ in
switch (event, fromState) {
case (.selectRoom(let roomId), .roomList):
return .roomList(selectedRoomId: roomId)
case (.deselectRoom, .roomList):
return .roomList(selectedRoomId: nil)
case (.showSettingsScreen, .roomList(let selectedRoomId)):
return .settingsScreen(selectedRoomId: selectedRoomId)
case (.dismissedSettingsScreen, .settingsScreen(let selectedRoomId)):
return .roomList(selectedRoomId: selectedRoomId)
case (.feedbackScreen, .roomList(let selectedRoomId)):
return .feedbackScreen(selectedRoomId: selectedRoomId)
case (.dismissedFeedbackScreen, .feedbackScreen(let selectedRoomId)):
return .roomList(selectedRoomId: selectedRoomId)
case (.showSessionVerificationScreen, .roomList(let selectedRoomId)):
return .sessionVerificationScreen(selectedRoomId: selectedRoomId)
case (.dismissedSessionVerificationScreen, .sessionVerificationScreen(let selectedRoomId)):
return .roomList(selectedRoomId: selectedRoomId)
default:
return nil
}
}
addTransitionHandler { context in
if let event = context.event {
MXLog.info("Transitioning from `\(context.fromState)` to `\(context.toState)` with event `\(event)`")
} else {
MXLog.info("Transitioning from \(context.fromState)` to `\(context.toState)`")
}
}
}
/// Attempt to move the state machine to another state through an event
/// It will either invoke the `transitionHandler` or the `errorHandler` depending on its current state
func processEvent(_ event: Event) {
stateMachine.tryEvent(event)
}
/// Registers a callback for processing state machine transitions
func addTransitionHandler(_ handler: @escaping StateMachine<State, Event>.Handler) {
stateMachine.addAnyHandler(.any => .any, handler: handler)
}
/// Registers a callback for processing state machine errors
func addErrorHandler(_ handler: @escaping StateMachine<State, Event>.Handler) {
stateMachine.addErrorHandler(handler: handler)
}
/// Flag indicating the machine is displaying room screen with given room identifier
func isDisplayingRoomScreen(withRoomId roomId: String) -> Bool {
switch stateMachine.state {
case .roomList(let selectedRoomId):
return roomId == selectedRoomId
default:
return false
}
}
}