diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt index b14dd75b10..58983a84ed 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt @@ -21,28 +21,34 @@ import kotlinx.coroutines.flow.asStateFlow class AccountProviderDataSource( enterpriseService: EnterpriseService, ) { - private val defaultAccountProvider = - (enterpriseService.defaultHomeserverList().firstOrNull { it != EnterpriseService.ANY_ACCOUNT_PROVIDER } ?: AuthenticationConfig.MATRIX_ORG_URL) - .let { url -> - AccountProvider( - url = url, - subtitle = null, - isPublic = url == AuthenticationConfig.MATRIX_ORG_URL, - isMatrixOrg = url == AuthenticationConfig.MATRIX_ORG_URL, - ) - } - - private val accountProvider: MutableStateFlow = MutableStateFlow( - defaultAccountProvider + private val defaultAccountProvider = createAccountProvider( + url = enterpriseService.defaultHomeserverList() + .firstOrNull { it != EnterpriseService.ANY_ACCOUNT_PROVIDER } + ?: AuthenticationConfig.MATRIX_ORG_URL ) + private val accountProvider: MutableStateFlow = MutableStateFlow(defaultAccountProvider) + val flow: StateFlow = accountProvider.asStateFlow() fun reset() { accountProvider.tryEmit(defaultAccountProvider) } + fun setUrl(url: String) { + userSelection(createAccountProvider(url)) + } + fun userSelection(data: AccountProvider) { accountProvider.tryEmit(data) } + + private fun createAccountProvider(url: String): AccountProvider { + return AccountProvider( + url = url, + subtitle = null, + isPublic = url == AuthenticationConfig.MATRIX_ORG_URL, + isMatrixOrg = url == AuthenticationConfig.MATRIX_ORG_URL, + ) + } } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt index 44d8095fa3..28d542a92e 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenter.kt @@ -23,6 +23,7 @@ import io.element.android.appconfig.OnBoardingConfig import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.enterprise.api.canConnectToAnyHomeserver import io.element.android.features.login.impl.accesscontrol.DefaultAccountProviderAccessControl +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.login.LoginHelper import io.element.android.features.rageshake.api.RageshakeFeatureAvailability import io.element.android.libraries.architecture.Presenter @@ -40,6 +41,7 @@ class OnBoardingPresenter( private val loginHelper: LoginHelper, private val onBoardingLogoResIdProvider: OnBoardingLogoResIdProvider, private val sessionStore: SessionStore, + private val accountProviderDataSource: AccountProviderDataSource, ) : Presenter { @AssistedFactory interface Factory { @@ -97,12 +99,16 @@ class OnBoardingPresenter( fun handleEvent(event: OnBoardingEvents) { when (event) { - is OnBoardingEvents.OnSignIn -> loginHelper.submit( - coroutineScope = localCoroutineScope, - isAccountCreation = false, - homeserverUrl = event.defaultAccountProvider, - loginHint = params.loginHint?.takeIf { forcedAccountProvider == null }, - ) + is OnBoardingEvents.OnSignIn -> { + // Ensure that the current account provider is set + accountProviderDataSource.setUrl(event.defaultAccountProvider) + loginHelper.submit( + coroutineScope = localCoroutineScope, + isAccountCreation = false, + homeserverUrl = event.defaultAccountProvider, + loginHint = params.loginHint?.takeIf { forcedAccountProvider == null }, + ) + } OnBoardingEvents.ClearError -> loginHelper.clearError() OnBoardingEvents.OnVersionClick -> { if (canReportBug) { diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSourceTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSourceTest.kt index 8a8f6864cf..4b0392dae9 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSourceTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSourceTest.kt @@ -102,4 +102,27 @@ class AccountProviderDataSourceTest { assertThat(resetState.url).isEqualTo(AuthenticationConfig.MATRIX_ORG_URL) } } + + @Test + fun `present - set url and reset`() = runTest { + val sut = AccountProviderDataSource(FakeEnterpriseService()) + sut.flow.test { + val initialState = awaitItem() + assertThat(initialState.url).isEqualTo(AuthenticationConfig.MATRIX_ORG_URL) + sut.setUrl(url = "https://example.com") + val changedState = awaitItem() + assertThat(changedState).isEqualTo( + AccountProvider( + url = "https://example.com", + title = "example.com", + subtitle = null, + isPublic = false, + isMatrixOrg = false, + ) + ) + sut.reset() + val resetState = awaitItem() + assertThat(resetState.url).isEqualTo(AuthenticationConfig.MATRIX_ORG_URL) + } + } } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt index 1cbbda450b..fc4bbf093b 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnBoardingPresenterTest.kt @@ -8,10 +8,12 @@ package io.element.android.features.login.impl.screens.onboarding import com.google.common.truth.Truth.assertThat +import io.element.android.appconfig.AuthenticationConfig import io.element.android.appconfig.OnBoardingConfig import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.accesscontrol.DefaultAccountProviderAccessControl +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.login.LoginHelper import io.element.android.features.login.impl.web.FakeWebClientUrlForAuthenticationRetriever import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever @@ -24,6 +26,7 @@ import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2 import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_3 import io.element.android.libraries.matrix.test.AN_EXCEPTION import io.element.android.libraries.matrix.test.A_HOMESERVER_URL +import io.element.android.libraries.matrix.test.A_HOMESERVER_URL_2 import io.element.android.libraries.matrix.test.A_LOGIN_HINT import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.core.aBuildMeta @@ -36,6 +39,7 @@ import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.test import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.junit.Rule @@ -219,6 +223,7 @@ class OnBoardingPresenterTest { Result.failure(AN_EXCEPTION) }, ) + val accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()) val presenter = createPresenter( params = OnBoardingNode.Params( accountProvider = A_HOMESERVER_URL, @@ -230,14 +235,17 @@ class OnBoardingPresenterTest { loginHelper = createLoginHelper( authenticationService = authenticationService, ), + accountProviderDataSource = accountProviderDataSource, ) presenter.test { skipItems(3) awaitItem().also { assertThat(it.defaultAccountProvider).isEqualTo(A_HOMESERVER_URL) - it.eventSink(OnBoardingEvents.OnSignIn(A_HOMESERVER_URL)) + assertThat(accountProviderDataSource.flow.first().url).isEqualTo(AuthenticationConfig.MATRIX_ORG_URL) + it.eventSink(OnBoardingEvents.OnSignIn(A_HOMESERVER_URL_2)) skipItems(1) // Loading - + // Account data source has been updated + assertThat(accountProviderDataSource.flow.first().url).isEqualTo(A_HOMESERVER_URL_2) // Check an error was returned val submittedState = awaitItem() assertThat(submittedState.loginMode).isInstanceOf(AsyncData.Failure::class.java) @@ -260,6 +268,7 @@ private fun createPresenter( loginHelper: LoginHelper = createLoginHelper(), onBoardingLogoResIdProvider: OnBoardingLogoResIdProvider = OnBoardingLogoResIdProvider { null }, sessionStore: SessionStore = InMemorySessionStore(), + accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), ) = OnBoardingPresenter( params = params, buildMeta = buildMeta, @@ -272,6 +281,7 @@ private fun createPresenter( loginHelper = loginHelper, onBoardingLogoResIdProvider = onBoardingLogoResIdProvider, sessionStore = sessionStore, + accountProviderDataSource = accountProviderDataSource, ) fun createLoginHelper(