diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderEvents.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderEvent.kt similarity index 81% rename from features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderEvents.kt rename to features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderEvent.kt index 9093a8121f..24b6fdfcda 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderEvents.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderEvent.kt @@ -8,11 +8,11 @@ package io.element.android.features.login.impl.screens.confirmaccountprovider -sealed interface ConfirmAccountProviderEvents { - data class UserInputChanged(val accountProvider: String) : ConfirmAccountProviderEvents +sealed interface ConfirmAccountProviderEvent { + data class UserInputChanged(val accountProvider: String) : ConfirmAccountProviderEvent // Carries the account provider to submit (the current field text, or the accepted autocomplete suggestion), // captured from the view at click time so it can't lag behind fast input (e.g. keyboard autofill). - data class Continue(val accountProvider: String) : ConfirmAccountProviderEvents - data object ClearError : ConfirmAccountProviderEvents + data class Continue(val accountProvider: String) : ConfirmAccountProviderEvent + data object ClearError : ConfirmAccountProviderEvent } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt index 9fae52ab0b..627620ff31 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenter.kt @@ -110,14 +110,14 @@ class ConfirmAccountProviderPresenter( } } - fun handleEvent(event: ConfirmAccountProviderEvents) { + fun handleEvent(event: ConfirmAccountProviderEvent) { when (event) { - is ConfirmAccountProviderEvents.UserInputChanged -> { + is ConfirmAccountProviderEvent.UserInputChanged -> { userInput = event.accountProvider } // Validate (and persist) the chosen account provider before proceeding. This also enforces the // account-provider access control, which the login submit does not run on its own. - is ConfirmAccountProviderEvents.Continue -> { + is ConfirmAccountProviderEvent.Continue -> { // Apply the accepted account provider (any accepted completion) back into the field so it // renders the full server rather than the typed prefix, and survives the OAuth round-trip. val accountProvider = event.accountProvider.trim() @@ -137,7 +137,7 @@ class ConfirmAccountProviderPresenter( ChangeServerEvent.ChangeServer(AccountProvider(url = accountProviderUrl)) ) } - ConfirmAccountProviderEvents.ClearError -> { + ConfirmAccountProviderEvent.ClearError -> { loginModeState.eventSink(LoginModeEvent.ClearError) changeServerState.eventSink(ChangeServerEvent.ClearError) } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt index bf6b0cb0e7..eec082d886 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderState.kt @@ -19,7 +19,7 @@ data class ConfirmAccountProviderState( val isAccountCreation: Boolean, val loginModeState: LoginModeState, val changeServerState: ChangeServerState, - val eventSink: (ConfirmAccountProviderEvents) -> Unit + val eventSink: (ConfirmAccountProviderEvent) -> Unit ) { val submitEnabled: Boolean get() = accountProviderInput.isNotBlank() && diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStatePreviewParam.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStatePreviewParam.kt index ab6350bb4d..be85a306ba 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStatePreviewParam.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderStatePreviewParam.kt @@ -40,7 +40,7 @@ private fun aConfirmAccountProviderState( isAccountCreation: Boolean = false, loginModeState: LoginModeState = aLoginModeState(), changeServerState: ChangeServerState = aChangeServerState(), - eventSink: (ConfirmAccountProviderEvents) -> Unit = {}, + eventSink: (ConfirmAccountProviderEvent) -> Unit = {}, ) = ConfirmAccountProviderState( accountProviderInput = accountProviderInput, accountProviderSuggestion = accountProviderSuggestion, diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt index 1dab5cd31c..446b969f12 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt @@ -99,7 +99,7 @@ fun ConfirmAccountProviderView( // Dismiss the keyboard and release focus while the account provider is being validated. focusManager.clearFocus(force = true) // Submit the exact field text (plus any accepted suggestion). - eventSink(ConfirmAccountProviderEvents.Continue(accountProviderToSubmit)) + eventSink(ConfirmAccountProviderEvent.Continue(accountProviderToSubmit)) } // Once a validation / login error has been dismissed, return focus and the keyboard to the field so @@ -151,7 +151,7 @@ fun ConfirmAccountProviderView( value = input, onValueChange = { input = it - eventSink(ConfirmAccountProviderEvents.UserInputChanged(it)) + eventSink(ConfirmAccountProviderEvent.UserInputChanged(it)) }, modifier = Modifier .fillMaxWidth() @@ -181,7 +181,7 @@ fun ConfirmAccountProviderView( // showing, Done submits directly. val accepted = input + suggestionSuffix input = accepted - eventSink(ConfirmAccountProviderEvents.UserInputChanged(accepted)) + eventSink(ConfirmAccountProviderEvent.UserInputChanged(accepted)) focusManager.clearFocus(force = true) } else { submit() @@ -197,7 +197,7 @@ fun ConfirmAccountProviderView( role = Role.Button, ) { input = "" - eventSink(ConfirmAccountProviderEvents.UserInputChanged("")) + eventSink(ConfirmAccountProviderEvent.UserInputChanged("")) } ) { Icon( @@ -222,7 +222,7 @@ fun ConfirmAccountProviderView( LoginModeView( loginMode = state.loginModeState.loginMode, - onClearError = { eventSink(ConfirmAccountProviderEvents.ClearError) }, + onClearError = { eventSink(ConfirmAccountProviderEvent.ClearError) }, onLearnMoreClick = onLearnMoreClick, onOAuthDetails = onOAuthDetails, onNeedLoginPassword = onNeedLoginPassword, diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt index 641eea1563..19afbe0f28 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt @@ -68,7 +68,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val successState = awaitLoginMode { it is AsyncData.Success } assertThat(successState.loginModeState.loginMode.dataOrNull()).isEqualTo(LoginMode.PasswordLogin) cancelAndIgnoreRemainingEvents() @@ -87,7 +87,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val successState = awaitLoginMode { it is AsyncData.Success } assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) cancelAndIgnoreRemainingEvents() @@ -108,7 +108,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val successState = awaitLoginMode { it is AsyncData.Success } assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) authenticationService.givenOAuthCancelError(AN_EXCEPTION) @@ -133,7 +133,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val successState = awaitLoginMode { it is AsyncData.Success } assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) defaultOAuthActionFlow.post(OAuthAction.GoBack()) @@ -157,7 +157,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) awaitLoginMode { it is AsyncData.Loading } defaultOAuthActionFlow.post(OAuthAction.GoBack(toUnblock = true)) val cancelFinalState = awaitLoginMode { it is AsyncData.Uninitialized } @@ -180,7 +180,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val successState = awaitLoginMode { it is AsyncData.Success } assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) authenticationService.givenLoginError(AN_EXCEPTION) @@ -205,7 +205,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val successState = awaitLoginMode { it is AsyncData.Success } assertThat(successState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) defaultOidcActionFlow.post(OAuthAction.Success("aUrl")) @@ -227,7 +227,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink.invoke(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) // The account provider validation fails, so the login is never attempted. val failureState = awaitState { it.changeServerState.changeServerAction is AsyncData.Failure } assertThat(failureState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) @@ -249,13 +249,13 @@ class ConfirmAccountProviderPresenterTest { val initialState = awaitItem() // Submit will return an error while validating the account provider - initialState.eventSink(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) // Check an error was returned val submittedState = awaitState { it.changeServerState.changeServerAction is AsyncData.Failure } // Assert the error is then cleared - submittedState.eventSink(ConfirmAccountProviderEvents.ClearError) + submittedState.eventSink(ConfirmAccountProviderEvent.ClearError) val clearedState = awaitState { it.changeServerState.changeServerAction is AsyncData.Uninitialized } assertThat(clearedState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) } @@ -274,12 +274,12 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) // Check an error was returned val submittedState = awaitLoginMode { it is AsyncData.Failure } assertThat(submittedState.loginModeState.loginMode.errorOrNull()).isInstanceOf(AccountCreationNotSupported::class.java) // Assert the error is then cleared - submittedState.eventSink(ConfirmAccountProviderEvents.ClearError) + submittedState.eventSink(ConfirmAccountProviderEvent.ClearError) val clearedState = awaitLoginMode { it is AsyncData.Uninitialized } assertThat(clearedState.loginModeState.loginMode).isEqualTo(AsyncData.Uninitialized) cancelAndIgnoreRemainingEvents() @@ -299,7 +299,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) val submittedState = awaitLoginMode { it is AsyncData.Success } assertThat(submittedState.loginModeState.loginMode.dataOrNull()).isInstanceOf(LoginMode.OAuth::class.java) cancelAndIgnoreRemainingEvents() @@ -316,7 +316,7 @@ class ConfirmAccountProviderPresenterTest { presenter.test { val initialState = awaitItem() assertThat(initialState.accountProviderSuggestion).isNull() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("random")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("random")) val suggestionState = awaitState { it.accountProviderInput == "random" } // Completion is offered without the https:// scheme, even though history stores the full URL. assertThat(suggestionState.accountProviderSuggestion).isEqualTo("randomcommunity.org") @@ -340,9 +340,9 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("random")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("random")) val suggestionState = awaitState { it.accountProviderSuggestion != null } - suggestionState.eventSink(ConfirmAccountProviderEvents.Continue("randomcommunity.org")) + suggestionState.eventSink(ConfirmAccountProviderEvent.Continue("randomcommunity.org")) awaitLoginMode { it is AsyncData.Success } assertThat(submittedUrls.first()).isEqualTo("https://randomcommunity.org") cancelAndIgnoreRemainingEvents() @@ -360,9 +360,9 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("random")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("random")) val suggestionState = awaitState { it.accountProviderSuggestion != null } - suggestionState.eventSink(ConfirmAccountProviderEvents.Continue("randomcommunity.org")) + suggestionState.eventSink(ConfirmAccountProviderEvent.Continue("randomcommunity.org")) // The field now renders the full accepted server rather than the typed prefix. val appliedState = awaitState { it.accountProviderInput == "randomcommunity.org" } assertThat(appliedState.accountProviderInput).isEqualTo("randomcommunity.org") @@ -381,7 +381,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("ele")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("ele")) val suggestionState = awaitState { it.accountProviderInput == "ele" } assertThat(suggestionState.accountProviderSuggestion).isEqualTo("element.io") } @@ -394,7 +394,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("matr")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("matr")) val suggestionState = awaitState { it.accountProviderInput == "matr" } assertThat(suggestionState.accountProviderSuggestion).isEqualTo("matrix.org") } @@ -409,9 +409,9 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("https://mat")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("https://mat")) assertThat(awaitState { it.accountProviderInput == "https://mat" }.accountProviderSuggestion).isNull() - initialState.eventSink(ConfirmAccountProviderEvents.UserInputChanged("http://mat")) + initialState.eventSink(ConfirmAccountProviderEvent.UserInputChanged("http://mat")) assertThat(awaitState { it.accountProviderInput == "http://mat" }.accountProviderSuggestion).isNull() } } @@ -430,7 +430,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue("matrix.org")) + initialState.eventSink(ConfirmAccountProviderEvent.Continue("matrix.org")) awaitLoginMode { it is AsyncData.Success } assertThat(submittedUrls.first()).isEqualTo(AuthenticationConfig.MATRIX_ORG_URL) cancelAndIgnoreRemainingEvents() @@ -453,7 +453,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue(AuthenticationConfig.MATRIX_ORG_URL)) + initialState.eventSink(ConfirmAccountProviderEvent.Continue(AuthenticationConfig.MATRIX_ORG_URL)) awaitLoginMode { it is AsyncData.Success } assertThat(submittedUrls).containsExactly(AuthenticationConfig.MATRIX_ORG_URL) cancelAndIgnoreRemainingEvents() @@ -472,7 +472,7 @@ class ConfirmAccountProviderPresenterTest { val presenter = createConfirmAccountProviderPresenter(matrixAuthenticationService = authenticationService) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue("@alice:example.org")) + initialState.eventSink(ConfirmAccountProviderEvent.Continue("@alice:example.org")) awaitLoginMode { it is AsyncData.Success } assertThat(submittedUrls.first()).isEqualTo("https://example.org") assertThat(authenticationService.getOAuthUrlLoginHint).isEqualTo("mxid:@alice:example.org") @@ -492,7 +492,7 @@ class ConfirmAccountProviderPresenterTest { val presenter = createConfirmAccountProviderPresenter(matrixAuthenticationService = authenticationService) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue("@alice:example.org:8448")) + initialState.eventSink(ConfirmAccountProviderEvent.Continue("@alice:example.org:8448")) awaitLoginMode { it is AsyncData.Success } assertThat(submittedUrls.first()).isEqualTo("https://example.org:8448") cancelAndIgnoreRemainingEvents() @@ -507,7 +507,7 @@ class ConfirmAccountProviderPresenterTest { val presenter = createConfirmAccountProviderPresenter(matrixAuthenticationService = authenticationService) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue("matrix.org")) + initialState.eventSink(ConfirmAccountProviderEvent.Continue("matrix.org")) awaitLoginMode { it is AsyncData.Success } assertThat(authenticationService.getOAuthUrlLoginHint).isNull() cancelAndIgnoreRemainingEvents() @@ -525,7 +525,7 @@ class ConfirmAccountProviderPresenterTest { ) presenter.test { val initialState = awaitItem() - initialState.eventSink(ConfirmAccountProviderEvents.Continue("@alice:example.org")) + initialState.eventSink(ConfirmAccountProviderEvent.Continue("@alice:example.org")) awaitLoginMode { it is AsyncData.Success } assertThat(authenticationService.getOAuthUrlLoginHint).isNull() cancelAndIgnoreRemainingEvents()