#66 - Rebuild the AppCoordinator on top of a SwiftState FSM
This commit is contained in:
@@ -123,6 +123,7 @@
|
||||
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
|
||||
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
|
||||
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
|
||||
9AC5F8142413862A9E3A2D98 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
||||
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; };
|
||||
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
|
||||
9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; };
|
||||
@@ -141,6 +142,8 @@
|
||||
AB34401E4E1CAD5D2EC3072B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9760103CF316DF68698BCFE6 /* LaunchScreen.storyboard */; };
|
||||
B0887A7B5AFEC88981626389 /* MXLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64839516BD56D1C81D84C5E0 /* MXLog.swift */; };
|
||||
B0EDAF55877DE19B67837C22 /* TemplateSimpleScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C29670CEC77346F31EE94C /* TemplateSimpleScreenModels.swift */; };
|
||||
B245583C63F8F90357B87FAE /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 3853B78FB8531B83936C5DA6 /* SwiftState */; };
|
||||
B3FDB1D9CF40777695DBBD1D /* AppCoordinatorStateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A9AB74614131D6706894E0C /* AppCoordinatorStateMachine.swift */; };
|
||||
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
|
||||
B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */; };
|
||||
B80C4FABB5529DF12436FFDA /* AppIcon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 16DC8C5B2991724903F1FA6A /* AppIcon.pdf */; };
|
||||
@@ -301,6 +304,7 @@
|
||||
56F01DD1BBD4450E18115916 /* LabelledActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelledActivityIndicatorView.swift; sourceTree = "<group>"; };
|
||||
5773C86AF04AEF26515AD00C /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModelTests.swift; sourceTree = "<group>"; };
|
||||
5A9AB74614131D6706894E0C /* AppCoordinatorStateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCoordinatorStateMachine.swift; sourceTree = "<group>"; };
|
||||
5B9D5F812E5AD6DC786DBC9B /* NavigationRouterStoreProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouterStoreProtocol.swift; sourceTree = "<group>"; };
|
||||
5CB7F9D6FC121204D59E18DF /* Presentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = "<group>"; };
|
||||
5D26A086A8278D39B5756D6F /* project.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = project.yml; sourceTree = "<group>"; };
|
||||
@@ -500,6 +504,7 @@
|
||||
CB498F4E27AA0545DCEF0F6F /* Kingfisher in Frameworks */,
|
||||
6832733838C57A7D3FE8FEB5 /* Introspect in Frameworks */,
|
||||
2BA59D0AEFB4B82A2EC2A326 /* SwiftyBeaver in Frameworks */,
|
||||
B245583C63F8F90357B87FAE /* SwiftState in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -513,6 +518,7 @@
|
||||
9D2E03DB175A6AB14589076D /* Kingfisher in Frameworks */,
|
||||
6F2AB43A1EFAD8A97AF41A15 /* Introspect in Frameworks */,
|
||||
93BA4A81B6D893271101F9F0 /* SwiftyBeaver in Frameworks */,
|
||||
9AC5F8142413862A9E3A2D98 /* SwiftState in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1038,6 +1044,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CF3EDF23226895776553F04A /* AppCoordinator.swift */,
|
||||
5A9AB74614131D6706894E0C /* AppCoordinatorStateMachine.swift */,
|
||||
EFFA5FD06AAAC4AF544B594E /* AppDelegate.swift */,
|
||||
967873B9E11828B67F64C89A /* UITestsAppCoordinator.swift */,
|
||||
CCA431E6EDD71F7067B5F9E7 /* UITestsRootView.swift */,
|
||||
@@ -1126,6 +1133,7 @@
|
||||
50009897F60FAE7D63EF5E5B /* Kingfisher */,
|
||||
04C28663564E008DB32B5972 /* Introspect */,
|
||||
A981A4CA233FB5C13B9CA690 /* SwiftyBeaver */,
|
||||
3853B78FB8531B83936C5DA6 /* SwiftState */,
|
||||
);
|
||||
productName = UITests;
|
||||
productReference = F506C6ADB1E1DA6638078E11 /* UITests.xctest */;
|
||||
@@ -1170,6 +1178,7 @@
|
||||
0DD568A494247444A4B56031 /* Kingfisher */,
|
||||
5986E300FC849DEAB2EE7AEB /* Introspect */,
|
||||
FD43A50D9B75C9D6D30F006B /* SwiftyBeaver */,
|
||||
9573B94B1C86C6DF751AF3FD /* SwiftState */,
|
||||
);
|
||||
productName = ElementX;
|
||||
productReference = 4CD6AC7546E8D7E5C73CEA48 /* ElementX.app */;
|
||||
@@ -1278,6 +1287,7 @@
|
||||
61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */,
|
||||
D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
||||
4FCDA8D25C7415C8FB33490D /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */,
|
||||
6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */,
|
||||
25B4484A6A20B9F1705DEEDA /* XCRemoteSwiftPackageReference "SwiftyBeaver" */,
|
||||
);
|
||||
projectDirPath = "";
|
||||
@@ -1391,6 +1401,7 @@
|
||||
4D23C56053013437C35E511E /* ActivityIndicatorPresenterType.swift in Sources */,
|
||||
FC6B7436C3A5B3D0565227D5 /* ActivityIndicatorView.swift in Sources */,
|
||||
A636D4900E0D98ED91536482 /* AppCoordinator.swift in Sources */,
|
||||
B3FDB1D9CF40777695DBBD1D /* AppCoordinatorStateMachine.swift in Sources */,
|
||||
2FE4EEF780553B25A446BBFB /* AppDelegate.swift in Sources */,
|
||||
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */,
|
||||
3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */,
|
||||
@@ -2024,6 +2035,14 @@
|
||||
minimumVersion = 4.2.2;
|
||||
};
|
||||
};
|
||||
6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/ReactKit/SwiftState";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 6.0.0;
|
||||
};
|
||||
};
|
||||
A24ABD6F9CEE4D0749A6173E /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/siteline/SwiftUI-Introspect.git";
|
||||
@@ -2071,6 +2090,11 @@
|
||||
package = C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */;
|
||||
productName = DTCoreText;
|
||||
};
|
||||
3853B78FB8531B83936C5DA6 /* SwiftState */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */;
|
||||
productName = SwiftState;
|
||||
};
|
||||
50009897F60FAE7D63EF5E5B /* Kingfisher */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D283517192CAC3E2E6920765 /* XCRemoteSwiftPackageReference "Kingfisher" */;
|
||||
@@ -2091,6 +2115,11 @@
|
||||
package = 61916C63E3F5BD900F08DA0C /* XCRemoteSwiftPackageReference "KeychainAccess" */;
|
||||
productName = KeychainAccess;
|
||||
};
|
||||
9573B94B1C86C6DF751AF3FD /* SwiftState */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 6582B5AF3F104B0F7E031E7D /* XCRemoteSwiftPackageReference "SwiftState" */;
|
||||
productName = SwiftState;
|
||||
};
|
||||
A678E40E917620059695F067 /* MatrixRustSDK */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 4FCDA8D25C7415C8FB33490D /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */;
|
||||
|
||||
@@ -45,6 +45,15 @@
|
||||
"revision" : "43c88a4b0912a1589c2a28cc9bb2df45c70cdcad"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftstate",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/ReactKit/SwiftState",
|
||||
"state" : {
|
||||
"revision" : "887e75b96da6be36a062e1b0ef832c32a803348b",
|
||||
"version" : "6.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftui-introspect",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
||||
@@ -12,6 +12,8 @@ import Kingfisher
|
||||
class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
private let window: UIWindow
|
||||
|
||||
private var stateMachine: AppCoordinatorStateMachine
|
||||
|
||||
private let mainNavigationController: UINavigationController
|
||||
private let splashViewController: UIViewController
|
||||
|
||||
@@ -31,6 +33,8 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
init() {
|
||||
stateMachine = AppCoordinatorStateMachine()
|
||||
|
||||
splashViewController = SplashViewController()
|
||||
mainNavigationController = UINavigationController(rootViewController: splashViewController)
|
||||
window = UIWindow(frame: UIScreen.main.bounds)
|
||||
@@ -51,6 +55,8 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
navigationRouter: navigationRouter)
|
||||
authenticationCoordinator.delegate = self
|
||||
|
||||
setupStateMachine()
|
||||
|
||||
let loggerConfiguration = MXLogConfiguration()
|
||||
loggerConfiguration.logLevel = .verbose
|
||||
MXLog.configure(loggerConfiguration)
|
||||
@@ -59,22 +65,70 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
}
|
||||
|
||||
func start() {
|
||||
window.makeKeyAndVisible()
|
||||
authenticationCoordinator.start()
|
||||
stateMachine.processEvent(.start)
|
||||
}
|
||||
|
||||
// MARK: - AuthenticationCoordinatorDelegate
|
||||
|
||||
func authenticationCoordinatorDidStartLoading(_ authenticationCoordinator: AuthenticationCoordinator) {
|
||||
showLoadingIndicator()
|
||||
stateMachine.processEvent(.attemptedSignIn)
|
||||
}
|
||||
|
||||
func authenticationCoordinator(_ authenticationCoordinator: AuthenticationCoordinator, didFailWithError error: AuthenticationCoordinatorError) {
|
||||
hideLoadingIndicator()
|
||||
showLoginErrorToast()
|
||||
stateMachine.processEvent(.failedSigningIn)
|
||||
}
|
||||
|
||||
func authenticationCoordinatorDidSetupClientProxy(_ authenticationCoordinator: AuthenticationCoordinator) {
|
||||
stateMachine.processEvent(.succeededSigningIn)
|
||||
}
|
||||
|
||||
func authenticationCoordinatorDidTearDownClientProxy(_ authenticationCoordinator: AuthenticationCoordinator) {
|
||||
stateMachine.processEvent(.succeededSigningOut)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
private func setupStateMachine() {
|
||||
stateMachine.addTransitionHandler { [weak self] context in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch (context.fromState, context.event, context.toState) {
|
||||
case (.initial, .start, .signedOut):
|
||||
self.window.makeKeyAndVisible()
|
||||
self.authenticationCoordinator.start()
|
||||
case (.signedOut, .attemptedSignIn, .signingIn):
|
||||
self.showLoadingIndicator()
|
||||
case (.signingIn, .failedSigningIn, .signedOut):
|
||||
self.hideLoadingIndicator()
|
||||
self.showLoginErrorToast()
|
||||
case (.signingIn, .succeededSigningIn, .signedIn):
|
||||
self.hideLoadingIndicator()
|
||||
self.setupUserSession()
|
||||
case (.signedIn, .showHomeScreen, .homeScreen):
|
||||
self.presentHomeScreen()
|
||||
case(_, _, .roomScreen(let roomId)):
|
||||
self.presentRoomWithIdentifier(roomId)
|
||||
case(.roomScreen, .dismissedRoomScreen, .homeScreen):
|
||||
self.tearDownDismissedRoomScreen()
|
||||
case (_, .attemptSignOut, .signingOut):
|
||||
self.authenticationCoordinator.logout()
|
||||
case (.signingOut, .succeededSigningOut, .signedOut):
|
||||
self.tearDownUserSession()
|
||||
case (.signingOut, .failedSigningOut, _):
|
||||
self.showLogoutErrorToast()
|
||||
default:
|
||||
fatalError("Unknown transition: \(context)")
|
||||
}
|
||||
}
|
||||
|
||||
stateMachine.addErrorHandler { context in
|
||||
fatalError("Failed transition with context: \(context)")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable cyclomatic_complexity
|
||||
|
||||
private func setupUserSession() {
|
||||
guard let clientProxy = authenticationCoordinator.clientProxy else {
|
||||
fatalError("User session should be setup at this point")
|
||||
}
|
||||
@@ -82,39 +136,34 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
userSession = .init(clientProxy: clientProxy,
|
||||
mediaProvider: MediaProvider(clientProxy: clientProxy, imageCache: ImageCache.default))
|
||||
|
||||
presentHomeScreen()
|
||||
stateMachine.processEvent(.showHomeScreen)
|
||||
}
|
||||
|
||||
func authenticationCoordinatorDidTearDownClientProxy(_ authenticationCoordinator: AuthenticationCoordinator) {
|
||||
private func tearDownUserSession() {
|
||||
if let presentedCoordinator = childCoordinators.first {
|
||||
remove(childCoordinator: presentedCoordinator)
|
||||
}
|
||||
|
||||
userSession = nil
|
||||
|
||||
mainNavigationController.setViewControllers([splashViewController], animated: false)
|
||||
authenticationCoordinator.start()
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func presentHomeScreen() {
|
||||
|
||||
hideLoadingIndicator()
|
||||
|
||||
guard let userSession = userSession else {
|
||||
fatalError("User session should be already setup at this point")
|
||||
}
|
||||
|
||||
let parameters = HomeScreenCoordinatorParameters(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(),
|
||||
memberDetailProviderManager: memberDetailProviderManager)
|
||||
let coordinator = HomeScreenCoordinator(parameters: parameters)
|
||||
|
||||
coordinator.callback = { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch action {
|
||||
case .logout:
|
||||
self?.authenticationCoordinator.logout()
|
||||
self.stateMachine.processEvent(.attemptSignOut)
|
||||
case .selectRoom(let roomIdentifier):
|
||||
self?.presentRoomWithIdentifier(roomIdentifier)
|
||||
self.stateMachine.processEvent(.showRoomScreen(roomId: roomIdentifier))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,10 +172,6 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
}
|
||||
|
||||
private func presentRoomWithIdentifier(_ roomIdentifier: String) {
|
||||
guard let userSession = userSession else {
|
||||
fatalError("User session should be already setup at this point")
|
||||
}
|
||||
|
||||
guard let roomProxy = userSession.clientProxy.rooms.first(where: { $0.id == roomIdentifier }) else {
|
||||
MXLog.error("Invalid room identifier: \(roomIdentifier)")
|
||||
return
|
||||
@@ -147,14 +192,21 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
roomName: roomProxy.displayName ?? roomProxy.name)
|
||||
let coordinator = RoomScreenCoordinator(parameters: parameters)
|
||||
|
||||
self.add(childCoordinator: coordinator)
|
||||
self.navigationRouter.push(coordinator) { [weak self] in
|
||||
add(childCoordinator: coordinator)
|
||||
navigationRouter.push(coordinator) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.remove(childCoordinator: coordinator)
|
||||
self.stateMachine.processEvent(.dismissedRoomScreen)
|
||||
}
|
||||
}
|
||||
|
||||
private func tearDownDismissedRoomScreen() {
|
||||
guard let coordinator = childCoordinators.last as? RoomScreenCoordinator else {
|
||||
fatalError("Invalid coordinator hierarchy: \(childCoordinators)")
|
||||
}
|
||||
|
||||
remove(childCoordinator: coordinator)
|
||||
}
|
||||
|
||||
private func showLoadingIndicator() {
|
||||
loadingIndicator = indicatorPresenter.present(.loading(label: "Loading", isInteractionBlocking: true))
|
||||
}
|
||||
@@ -166,4 +218,8 @@ class AppCoordinator: AuthenticationCoordinatorDelegate, Coordinator {
|
||||
private func showLoginErrorToast() {
|
||||
errorIndicator = indicatorPresenter.present(.success(label: "Failed logging in"))
|
||||
}
|
||||
|
||||
private func showLogoutErrorToast() {
|
||||
errorIndicator = indicatorPresenter.present(.success(label: "Failed logging out"))
|
||||
}
|
||||
}
|
||||
|
||||
104
ElementX/Sources/AppCoordinatorStateMachine.swift
Normal file
104
ElementX/Sources/AppCoordinatorStateMachine.swift
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// AppCoordinatorStateMachine.swift
|
||||
// ElementX
|
||||
//
|
||||
// Created by Stefan Ceriu on 30/05/2022.
|
||||
// Copyright © 2022 element.io. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftState
|
||||
|
||||
class AppCoordinatorStateMachine {
|
||||
/// States the AppCoordinator can find itself in
|
||||
enum State: StateType {
|
||||
/// The initial state, used before the AppCoordinator starts
|
||||
case initial
|
||||
/// Showing the login screen
|
||||
case signedOut
|
||||
/// Processing sign in request
|
||||
case signingIn
|
||||
/// Successfully signed in
|
||||
case signedIn
|
||||
/// Showing the home screen
|
||||
case homeScreen
|
||||
/// Showing a particular room's timeline
|
||||
/// - Parameter roomId: that room's identifier
|
||||
case roomScreen(roomId: String)
|
||||
/// Processing a sign out request
|
||||
case signingOut
|
||||
}
|
||||
|
||||
/// Events that can be triggered on the AppCoordinator state machine
|
||||
enum Event: EventType {
|
||||
/// Start AppCoordinator flows, move from initial
|
||||
case start
|
||||
/// A sign in request has been started
|
||||
case attemptedSignIn
|
||||
/// Signing it succeeded
|
||||
case succeededSigningIn
|
||||
/// Signing in failed
|
||||
case failedSigningIn
|
||||
/// Request home screen presentation
|
||||
case showHomeScreen
|
||||
/// Request sign out
|
||||
case attemptSignOut
|
||||
/// Signing out succeeded
|
||||
case succeededSigningOut
|
||||
/// Signing out failed
|
||||
case failedSigningOut
|
||||
/// Request presentation for a particular room
|
||||
/// - Parameter roomId:the room identifier
|
||||
case showRoomScreen(roomId: String)
|
||||
/// The room screen has been dismissed
|
||||
case dismissedRoomScreen
|
||||
}
|
||||
|
||||
private let stateMachine: StateMachine<State, Event>
|
||||
|
||||
init() {
|
||||
stateMachine = StateMachine(state: .initial) { machine in
|
||||
machine.addRoutes(event: .start, transitions: [ .initial => .signedOut ])
|
||||
|
||||
machine.addRoutes(event: .attemptedSignIn, transitions: [ .signedOut => .signingIn ])
|
||||
|
||||
machine.addRoutes(event: .succeededSigningIn, transitions: [ .signingIn => .signedIn ])
|
||||
machine.addRoutes(event: .failedSigningIn, transitions: [ .signingIn => .signedOut ])
|
||||
|
||||
machine.addRoutes(event: .showHomeScreen, transitions: [ .signedIn => .homeScreen ])
|
||||
|
||||
machine.addRoutes(event: .attemptSignOut, transitions: [ .homeScreen => .signingOut ])
|
||||
|
||||
machine.addRoutes(event: .succeededSigningOut, transitions: [ .signingOut => .signedOut ])
|
||||
machine.addRoutes(event: .failedSigningOut, transitions: [ .signingOut => .homeScreen ])
|
||||
|
||||
// Transitions with associated values need to be handled through `addRouteMapping`
|
||||
machine.addRouteMapping { event, fromState, _ in
|
||||
switch (event, fromState) {
|
||||
case (.showRoomScreen(let roomId), .homeScreen):
|
||||
return .roomScreen(roomId: roomId)
|
||||
case (.dismissedRoomScreen, .roomScreen):
|
||||
return .homeScreen
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,7 @@ targets:
|
||||
- package: Kingfisher
|
||||
- package: Introspect
|
||||
- package: SwiftyBeaver
|
||||
- package: SwiftState
|
||||
|
||||
sources:
|
||||
- path: ../Sources
|
||||
|
||||
@@ -19,6 +19,8 @@ targets:
|
||||
linkType: static
|
||||
- package: SwiftyBeaver
|
||||
linkType: static
|
||||
- package: SwiftState
|
||||
linkType: static
|
||||
|
||||
info:
|
||||
path: ../SupportingFiles/Info.plist
|
||||
|
||||
@@ -48,3 +48,6 @@ packages:
|
||||
SwiftyBeaver:
|
||||
url: https://github.com/SwiftyBeaver/SwiftyBeaver
|
||||
majorVersion: 1.9.5
|
||||
SwiftState:
|
||||
url: https://github.com/ReactKit/SwiftState
|
||||
majorVersion: 6.0.0
|
||||
|
||||
Reference in New Issue
Block a user