Skip to content

Commit

Permalink
Move the core logic in LoginScreenCoordinator into the ViewModel. (#3348
Browse files Browse the repository at this point in the history
)
  • Loading branch information
pixlwave authored Oct 1, 2024
1 parent 5f4c289 commit 268d9f7
Show file tree
Hide file tree
Showing 29 changed files with 382 additions and 388 deletions.
16 changes: 8 additions & 8 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@
1D623953F970D11F6F38499C /* AppLockService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 851B95BB98649B8E773D6790 /* AppLockService.swift */; };
1D69E31913DF66426985909B /* EmojiPickerScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11151E78D6BB2B04A8FBD389 /* EmojiPickerScreenViewModelProtocol.swift */; };
1DC227816777A2F3A19657E5 /* RoomDirectorySearchScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF71646898A2F720C5BFDF5 /* RoomDirectorySearchScreenViewModel.swift */; };
1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05707BF550D770168A406DB /* LoginViewModelTests.swift */; };
1F3232BD368DF430AB433907 /* Compound in Frameworks */ = {isa = PBXBuildFile; productRef = 07FEEEDB11543A7DED420F04 /* Compound */; };
1FE593ECEC40A43789105D80 /* KeychainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */; };
1FEC0A4EC6E6DF693C16B32A /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CEBCB9676FCD1D0F13188DD /* StringTests.swift */; };
Expand Down Expand Up @@ -463,6 +462,7 @@
67C05C50AD734283374605E3 /* MatrixEntityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1A853D605C2146B0DC028 /* MatrixEntityRegex.swift */; };
67D6E0700A9C1E676F6231F8 /* Collections in Frameworks */ = {isa = PBXBuildFile; productRef = AD544C0FA48DFFB080920061 /* Collections */; };
67E9926C4572C54F59FCA91A /* AuthenticationFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */; };
67ECD32538F6DAFE38A623F9 /* ServerSelectionScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E45EBAFF1A83538D54ABDF92 /* ServerSelectionScreenViewModelTests.swift */; };
67EFF46180B939CBF389AECD /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C713D124FE915ABF47A6B7 /* TimelineView.swift */; };
6817EAD73DC1FFD8B943B5B9 /* HomeScreenRoomTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B73587C2E3CF5998361AE516 /* HomeScreenRoomTests.swift */; };
68184EF36396424FE19A727D /* MediaLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AFCE895ECFFA53FEE64D62B /* MediaLoader.swift */; };
Expand Down Expand Up @@ -513,6 +513,7 @@
73F33E9776B7A50B65A031D2 /* AppLockSettingsScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0BA67B3E4EF9D29D14A78CE /* AppLockSettingsScreenViewModelTests.swift */; };
73F547BEB41D3DAFAAF6E0AF /* UserProfileScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2E5103702D13361D09100 /* UserProfileScreenViewModelTests.swift */; };
7405B4824D45BA7C3D943E76 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0CBC76C80E04345E11F2DB /* Application.swift */; };
7434A7F02D587A920B376A9A /* LoginScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */; };
743790BF6A5B0577EA74AF14 /* ReadMarkerRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF3D25B3EDB283B5807EADCF /* ReadMarkerRoomTimelineItem.swift */; };
748F482FEF4E04D61C39AAD7 /* EmojiPickerScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = F174A5627CDB3CAF280D1880 /* EmojiPickerScreenModels.swift */; };
7501442D52A65F73DF79FFD4 /* PaginationIndicatorRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B987FC3FDBAA0E1C5AA235C /* PaginationIndicatorRoomTimelineItem.swift */; };
Expand Down Expand Up @@ -668,7 +669,6 @@
92D9088B901CEBB1A99ECA4E /* RoomMemberProxyMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FD673E24FBFCFDF398716A /* RoomMemberProxyMock.swift */; };
934051B17A884AB0635DF81B /* BlockedUsersScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */; };
937985546F708339711ECDFC /* ComposerToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85666E40F7E817809B4FD787 /* ComposerToolbar.swift */; };
93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */; };
93A549135E6C027A0D823BFE /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 593FBBF394712F2963E98A0B /* DTCoreText */; };
93AC1E8418D8C827671FB3A9 /* IdentityConfirmedScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 595EC503DA5517BBE6D39406 /* IdentityConfirmedScreenCoordinator.swift */; };
93BA4A81B6D893271101F9F0 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = A7CA6F33C553805035C3B114 /* DeviceKit */; };
Expand Down Expand Up @@ -1607,6 +1607,7 @@
5A1119E9C63AE530252640D2 /* SecureBackupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupController.swift; sourceTree = "<group>"; };
5A2FCA3D0F239B9E911B966B /* SecureBackupRecoveryKeyScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureBackupRecoveryKeyScreen.swift; sourceTree = "<group>"; };
5A37E2FACFD041CE466223CD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScreenViewModelTests.swift; sourceTree = "<group>"; };
5AEA0B743847CFA5B3C38EE4 /* RoomMembersListScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenCoordinator.swift; sourceTree = "<group>"; };
5B8F0ED874DF8C9A51B0AB6F /* SettingsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenCoordinator.swift; sourceTree = "<group>"; };
5C7C7CFA6B2A62A685FF6CE3 /* DeveloperOptionsScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperOptionsScreenCoordinator.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1888,7 +1889,6 @@
A010B8EAD1A9F6B4686DF2F4 /* BlockedUsersScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreenViewModel.swift; sourceTree = "<group>"; };
A019A12C866D64CF072024B9 /* AppLockSetupPINScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLockSetupPINScreenViewModel.swift; sourceTree = "<group>"; };
A02D1A490944BF01A37586E1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SAS.strings; sourceTree = "<group>"; };
A05707BF550D770168A406DB /* LoginViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModelTests.swift; sourceTree = "<group>"; };
A057F2FDC14866C3026A89A4 /* NotificationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManagerProtocol.swift; sourceTree = "<group>"; };
A12D3B1BCF920880CA8BBB6B /* UserIndicatorControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorControllerProtocol.swift; sourceTree = "<group>"; };
A130A2251A15A7AACC84FD37 /* RoomPollsHistoryScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollsHistoryScreenViewModelProtocol.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2186,6 +2186,7 @@
E413F4CBD7BF0588F394A9DD /* RoomDetailsEditScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDetailsEditScreenViewModel.swift; sourceTree = "<group>"; };
E43005941B3A2C9671E23C85 /* UserIndicatorModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserIndicatorModalView.swift; sourceTree = "<group>"; };
E44E35AA87F49503E7B3BF6E /* AudioConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioConverter.swift; sourceTree = "<group>"; };
E45EBAFF1A83538D54ABDF92 /* ServerSelectionScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModelTests.swift; sourceTree = "<group>"; };
E461B3C8BBBFCA400B268D14 /* AppRouteURLParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteURLParserTests.swift; sourceTree = "<group>"; };
E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlurHashDecode.swift; sourceTree = "<group>"; };
E53BFB7E4F329621C844E8C3 /* AnalyticsPromptScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreen.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2233,7 +2234,6 @@
ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = "<group>"; };
ED49073BB1C1FC649DAC2CCD /* LocationRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationRoomTimelineView.swift; sourceTree = "<group>"; };
ED60E4D2CD678E1EBF16F77A /* BlockedUsersScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedUsersScreen.swift; sourceTree = "<group>"; };
EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = "<group>"; };
EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = "<group>"; };
EE6BFF453838CF6C3982C5A3 /* RoomDirectorySearchScreenScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreenScreenViewModelTests.swift; sourceTree = "<group>"; };
EEAA2832D93EC7D2608703FB /* NSEUserSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEUserSession.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3828,7 +3828,7 @@
6E5725BC6C63604CB769145B /* LegalInformationScreenViewModelTests.swift */,
C070FD43DC6BF4E50217965A /* LocalizationTests.swift */,
3DC1943ADE6A62ED5129D7C8 /* LoggingTests.swift */,
A05707BF550D770168A406DB /* LoginViewModelTests.swift */,
5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */,
376D941BF8BB294389C0DE24 /* MapTilerURLBuildersTests.swift */,
F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */,
2D7A2C4A3A74F0D2FFE9356A /* MediaPlayerProviderTests.swift */,
Expand Down Expand Up @@ -3870,7 +3870,7 @@
40316EFFEAC7B206EE9A55AE /* SecureBackupScreenViewModelTests.swift */,
277C20CDD5B64510401B6D0D /* ServerConfigurationScreenViewStateTests.swift */,
F08776C48FFB47CACF64ED10 /* ServerConfirmationScreenViewModelTests.swift */,
EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */,
E45EBAFF1A83538D54ABDF92 /* ServerSelectionScreenViewModelTests.swift */,
0825EAFD47332DD459DE893F /* SessionDirectoriesTests.swift */,
A1C22B1B5FA3A765EADB2CC9 /* SessionVerificationStateMachineTests.swift */,
DF05DA24F71B455E8EFEBC3B /* SessionVerificationViewModelTests.swift */,
Expand Down Expand Up @@ -6122,7 +6122,7 @@
8AC256AF0EC54658321C9241 /* LegalInformationScreenViewModelTests.swift in Sources */,
0033481EE363E4914295F188 /* LocalizationTests.swift in Sources */,
149D1942DC005D0485FB8D93 /* LoggingTests.swift in Sources */,
1E59B77A0B2CE83DCC1B203C /* LoginViewModelTests.swift in Sources */,
7434A7F02D587A920B376A9A /* LoginScreenViewModelTests.swift in Sources */,
77C1A2F49CD90D3EFDF376E5 /* MapTilerURLBuildersTests.swift in Sources */,
2E43A3D221BE9587BC19C3F1 /* MatrixEntityRegexTests.swift in Sources */,
4B978C09567387EF4366BD7A /* MediaLoaderTests.swift in Sources */,
Expand Down Expand Up @@ -6171,7 +6171,7 @@
1B8E30B35BF8F541C1318F19 /* SecureBackupScreenViewModelTests.swift in Sources */,
53A55748D5F587C9061F98BF /* ServerConfigurationScreenViewStateTests.swift in Sources */,
89658A44C9FC19B58FD1C226 /* ServerConfirmationScreenViewModelTests.swift in Sources */,
93875ADD456142D20823ED24 /* ServerSelectionViewModelTests.swift in Sources */,
67ECD32538F6DAFE38A623F9 /* ServerSelectionScreenViewModelTests.swift in Sources */,
CC1C948F67A5510A340FD7F0 /* SessionDirectoriesTests.swift in Sources */,
86675910612A12409262DFBD /* SessionVerificationStateMachineTests.swift in Sources */,
755727E0B756430DFFEC4732 /* SessionVerificationViewModelTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ class AuthenticationFlowCoordinator: FlowCoordinatorProtocol {

private func showLoginScreen() {
let parameters = LoginScreenCoordinatorParameters(authenticationService: authenticationService,
analytics: analytics,
userIndicatorController: userIndicatorController)
slidingSyncLearnMoreURL: appSettings.slidingSyncLearnMoreURL,
userIndicatorController: userIndicatorController,
analytics: analytics)
let coordinator = LoginScreenCoordinator(parameters: parameters)

coordinator.actions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ enum LoginMode: Equatable {

var supportsOIDCFlow: Bool {
switch self {
case .oidc:
return true
default:
return false
case .oidc: true
default: false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import SwiftUI
struct LoginScreenCoordinatorParameters {
/// The service used to authenticate the user.
let authenticationService: AuthenticationServiceProtocol

let analytics: AnalyticsService
let slidingSyncLearnMoreURL: URL
let userIndicatorController: UserIndicatorControllerProtocol
let analytics: AnalyticsService
}

enum LoginScreenCoordinatorAction {
Expand Down Expand Up @@ -42,8 +42,10 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
init(parameters: LoginScreenCoordinatorParameters) {
self.parameters = parameters

viewModel = LoginScreenViewModel(homeserver: parameters.authenticationService.homeserver.value,
slidingSyncLearnMoreURL: ServiceLocator.shared.settings.slidingSyncLearnMoreURL)
viewModel = LoginScreenViewModel(authenticationService: parameters.authenticationService,
slidingSyncLearnMoreURL: parameters.slidingSyncLearnMoreURL,
userIndicatorController: parameters.userIndicatorController,
analytics: parameters.analytics)
}

// MARK: - Public
Expand All @@ -54,119 +56,20 @@ final class LoginScreenCoordinator: CoordinatorProtocol {
guard let self else { return }

switch action {
case .parseUsername(let username):
parseUsername(username)
case .forgotPassword:
showForgotPasswordScreen()
case .login(let username, let password):
login(username: username, password: password)
case .configuredForOIDC:
actionsSubject.send(.configuredForOIDC)
case .signedIn(let userSession):
actionsSubject.send(.signedIn(userSession))
}
}
.store(in: &cancellables)
}

func stop() {
stopLoading()
viewModel.stopLoading()
}

func toPresentable() -> AnyView {
AnyView(LoginScreen(context: viewModel.context))
}

// MARK: - Private

private static let loadingIndicatorIdentifier = "\(LoginScreenCoordinatorAction.self)-Loading"

private func startLoading(isInteractionBlocking: Bool) {
if isInteractionBlocking {
parameters.userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier,
type: .modal,
title: L10n.commonLoading,
persistent: true))
} else {
viewModel.update(isLoading: true)
}
}

private func stopLoading() {
viewModel.update(isLoading: false)
parameters.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier)
}

/// Processes an error to either update the flow or display it to the user.
private func handleError(_ error: AuthenticationServiceError) {
MXLog.info("Error occurred: \(error)")

switch error {
case .invalidCredentials:
viewModel.displayError(.alert(L10n.screenLoginErrorInvalidCredentials))
case .accountDeactivated:
viewModel.displayError(.alert(L10n.screenLoginErrorDeactivatedAccount))
case .invalidWellKnown(let error):
viewModel.displayError(.invalidWellKnownAlert(error))
case .slidingSyncNotAvailable:
viewModel.displayError(.slidingSyncAlert)
case .sessionTokenRefreshNotSupported:
viewModel.displayError(.refreshTokenAlert)
default:
viewModel.displayError(.alert(L10n.errorUnknown))
}
}

/// Requests the authentication coordinator to log in using the specified credentials.
private func login(username: String, password: String) {
MXLog.info("Starting login with password.")
startLoading(isInteractionBlocking: true)

Task {
parameters.analytics.signpost.beginLogin()
switch await authenticationService.login(username: username,
password: password,
initialDeviceName: UIDevice.current.initialDeviceName,
deviceID: nil) {
case .success(let userSession):
actionsSubject.send(.signedIn(userSession))
parameters.analytics.signpost.endLogin()
stopLoading()
case .failure(let error):
stopLoading()
parameters.analytics.signpost.endLogin()
handleError(error)
}
}
}

/// Parses the specified username and looks up the homeserver when a Matrix ID is entered.
private func parseUsername(_ username: String) {
guard MatrixEntityRegex.isMatrixUserIdentifier(username) else { return }

let homeserverDomain = String(username.split(separator: ":")[1])

startLoading(isInteractionBlocking: false)

Task {
switch await authenticationService.configure(for: homeserverDomain, flow: .login) {
case .success:
stopLoading()
if authenticationService.homeserver.value.loginMode == .oidc {
actionsSubject.send(.configuredForOIDC)
} else {
updateViewModel()
}
case .failure(let error):
stopLoading()
handleError(error)
}
}
}

/// Updates the view model with a different homeserver.
private func updateViewModel() {
viewModel.update(homeserver: authenticationService.homeserver.value)
}

/// Shows the forgot password screen.
private func showForgotPasswordScreen() {
viewModel.displayError(.alert("Not implemented."))
}
}
Loading

0 comments on commit 268d9f7

Please sign in to comment.