Adds error throw for LoginActivity LoginMode Unknown

This commit is contained in:
ericdecanini 2022-03-15 15:05:33 +01:00
parent a173accfa5
commit ef59faf160
2 changed files with 165 additions and 163 deletions

View file

@ -35,9 +35,9 @@ import org.matrix.android.sdk.internal.auth.login.LoginType
* This class execute the registration request and is responsible to keep the session of interactive authentication * This class execute the registration request and is responsible to keep the session of interactive authentication
*/ */
internal class DefaultRegistrationWizard( internal class DefaultRegistrationWizard(
authAPI: AuthAPI, authAPI: AuthAPI,
private val sessionCreator: SessionCreator, private val sessionCreator: SessionCreator,
private val pendingSessionStore: PendingSessionStore private val pendingSessionStore: PendingSessionStore
) : RegistrationWizard { ) : RegistrationWizard {
private var pendingSessionData: PendingSessionData = pendingSessionStore.getPendingSessionData() ?: error("Pending session data should exist here") private var pendingSessionData: PendingSessionData = pendingSessionStore.getPendingSessionData() ?: error("Pending session data should exist here")
@ -50,12 +50,12 @@ internal class DefaultRegistrationWizard(
override val currentThreePid: String? override val currentThreePid: String?
get() { get() {
return when (val threePid = pendingSessionData.currentThreePidData?.threePid) { return when (val threePid = pendingSessionData.currentThreePidData?.threePid) {
is RegisterThreePid.Email -> threePid.email is RegisterThreePid.Email -> threePid.email
is RegisterThreePid.Msisdn -> { is RegisterThreePid.Msisdn -> {
// Take formatted msisdn if provided by the server // Take formatted msisdn if provided by the server
pendingSessionData.currentThreePidData?.addThreePidRegistrationResponse?.formattedMsisdn?.takeIf { it.isNotBlank() } ?: threePid.msisdn pendingSessionData.currentThreePidData?.addThreePidRegistrationResponse?.formattedMsisdn?.takeIf { it.isNotBlank() } ?: threePid.msisdn
} }
null -> null null -> null
} }
} }
@ -67,24 +67,26 @@ internal class DefaultRegistrationWizard(
return performRegistrationRequest(params, LoginType.PASSWORD) return performRegistrationRequest(params, LoginType.PASSWORD)
} }
override suspend fun createAccount(userName: String?, override suspend fun createAccount(
password: String?, userName: String?,
initialDeviceDisplayName: String?): RegistrationResult { password: String?,
initialDeviceDisplayName: String?
): RegistrationResult {
val params = RegistrationParams( val params = RegistrationParams(
username = userName, username = userName,
password = password, password = password,
initialDeviceDisplayName = initialDeviceDisplayName initialDeviceDisplayName = initialDeviceDisplayName
) )
return performRegistrationRequest(params, LoginType.PASSWORD) return performRegistrationRequest(params, LoginType.PASSWORD)
.also { .also {
pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true) pendingSessionData = pendingSessionData.copy(isRegistrationStarted = true)
.also { pendingSessionStore.savePendingSessionData(it) } .also { pendingSessionStore.savePendingSessionData(it) }
} }
} }
override suspend fun performReCaptcha(response: String): RegistrationResult { override suspend fun performReCaptcha(response: String): RegistrationResult {
val safeSession = pendingSessionData.currentSession val safeSession = pendingSessionData.currentSession
?: throw IllegalStateException("developer error, call createAccount() method first") ?: throw IllegalStateException("developer error, call createAccount() method first")
val params = RegistrationParams(auth = AuthParams.createForCaptcha(safeSession, response)) val params = RegistrationParams(auth = AuthParams.createForCaptcha(safeSession, response))
return performRegistrationRequest(params, LoginType.PASSWORD) return performRegistrationRequest(params, LoginType.PASSWORD)
@ -92,7 +94,7 @@ internal class DefaultRegistrationWizard(
override suspend fun acceptTerms(): RegistrationResult { override suspend fun acceptTerms(): RegistrationResult {
val safeSession = pendingSessionData.currentSession val safeSession = pendingSessionData.currentSession
?: throw IllegalStateException("developer error, call createAccount() method first") ?: throw IllegalStateException("developer error, call createAccount() method first")
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.TERMS, session = safeSession)) val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.TERMS, session = safeSession))
return performRegistrationRequest(params, LoginType.PASSWORD) return performRegistrationRequest(params, LoginType.PASSWORD)
@ -100,14 +102,14 @@ internal class DefaultRegistrationWizard(
override suspend fun addThreePid(threePid: RegisterThreePid): RegistrationResult { override suspend fun addThreePid(threePid: RegisterThreePid): RegistrationResult {
pendingSessionData = pendingSessionData.copy(currentThreePidData = null) pendingSessionData = pendingSessionData.copy(currentThreePidData = null)
.also { pendingSessionStore.savePendingSessionData(it) } .also { pendingSessionStore.savePendingSessionData(it) }
return sendThreePid(threePid) return sendThreePid(threePid)
} }
override suspend fun sendAgainThreePid(): RegistrationResult { override suspend fun sendAgainThreePid(): RegistrationResult {
val safeCurrentThreePid = pendingSessionData.currentThreePidData?.threePid val safeCurrentThreePid = pendingSessionData.currentThreePidData?.threePid
?: throw IllegalStateException("developer error, call createAccount() method first") ?: throw IllegalStateException("developer error, call createAccount() method first")
return sendThreePid(safeCurrentThreePid) return sendThreePid(safeCurrentThreePid)
} }
@ -115,34 +117,34 @@ internal class DefaultRegistrationWizard(
private suspend fun sendThreePid(threePid: RegisterThreePid): RegistrationResult { private suspend fun sendThreePid(threePid: RegisterThreePid): RegistrationResult {
val safeSession = pendingSessionData.currentSession ?: throw IllegalStateException("developer error, call createAccount() method first") val safeSession = pendingSessionData.currentSession ?: throw IllegalStateException("developer error, call createAccount() method first")
val response = registerAddThreePidTask.execute( val response = registerAddThreePidTask.execute(
RegisterAddThreePidTask.Params( RegisterAddThreePidTask.Params(
threePid, threePid,
pendingSessionData.clientSecret, pendingSessionData.clientSecret,
pendingSessionData.sendAttempt)) pendingSessionData.sendAttempt))
pendingSessionData = pendingSessionData.copy(sendAttempt = pendingSessionData.sendAttempt + 1) pendingSessionData = pendingSessionData.copy(sendAttempt = pendingSessionData.sendAttempt + 1)
.also { pendingSessionStore.savePendingSessionData(it) } .also { pendingSessionStore.savePendingSessionData(it) }
val params = RegistrationParams( val params = RegistrationParams(
auth = if (threePid is RegisterThreePid.Email) { auth = if (threePid is RegisterThreePid.Email) {
AuthParams.createForEmailIdentity(safeSession, AuthParams.createForEmailIdentity(safeSession,
ThreePidCredentials( ThreePidCredentials(
clientSecret = pendingSessionData.clientSecret, clientSecret = pendingSessionData.clientSecret,
sid = response.sid sid = response.sid
)
) )
} else { )
AuthParams.createForMsisdnIdentity(safeSession, } else {
ThreePidCredentials( AuthParams.createForMsisdnIdentity(safeSession,
clientSecret = pendingSessionData.clientSecret, ThreePidCredentials(
sid = response.sid clientSecret = pendingSessionData.clientSecret,
) sid = response.sid
) )
} )
}
) )
// Store data // Store data
pendingSessionData = pendingSessionData.copy(currentThreePidData = ThreePidData.from(threePid, response, params)) pendingSessionData = pendingSessionData.copy(currentThreePidData = ThreePidData.from(threePid, response, params))
.also { pendingSessionStore.savePendingSessionData(it) } .also { pendingSessionStore.savePendingSessionData(it) }
// and send the sid a first time // and send the sid a first time
return performRegistrationRequest(params, LoginType.PASSWORD) return performRegistrationRequest(params, LoginType.PASSWORD)
@ -150,7 +152,7 @@ internal class DefaultRegistrationWizard(
override suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult { override suspend fun checkIfEmailHasBeenValidated(delayMillis: Long): RegistrationResult {
val safeParam = pendingSessionData.currentThreePidData?.registrationParams val safeParam = pendingSessionData.currentThreePidData?.registrationParams
?: throw IllegalStateException("developer error, no pending three pid") ?: throw IllegalStateException("developer error, no pending three pid")
return performRegistrationRequest(safeParam, LoginType.PASSWORD, delayMillis) return performRegistrationRequest(safeParam, LoginType.PASSWORD, delayMillis)
} }
@ -161,13 +163,13 @@ internal class DefaultRegistrationWizard(
private suspend fun validateThreePid(code: String): RegistrationResult { private suspend fun validateThreePid(code: String): RegistrationResult {
val registrationParams = pendingSessionData.currentThreePidData?.registrationParams val registrationParams = pendingSessionData.currentThreePidData?.registrationParams
?: throw IllegalStateException("developer error, no pending three pid") ?: throw IllegalStateException("developer error, no pending three pid")
val safeCurrentData = pendingSessionData.currentThreePidData ?: throw IllegalStateException("developer error, call createAccount() method first") val safeCurrentData = pendingSessionData.currentThreePidData ?: throw IllegalStateException("developer error, call createAccount() method first")
val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url to send the code") val url = safeCurrentData.addThreePidRegistrationResponse.submitUrl ?: throw IllegalStateException("Missing url to send the code")
val validationBody = ValidationCodeBody( val validationBody = ValidationCodeBody(
clientSecret = pendingSessionData.clientSecret, clientSecret = pendingSessionData.clientSecret,
sid = safeCurrentData.addThreePidRegistrationResponse.sid, sid = safeCurrentData.addThreePidRegistrationResponse.sid,
code = code code = code
) )
val validationResponse = validateCodeTask.execute(ValidateCodeTask.Params(url, validationBody)) val validationResponse = validateCodeTask.execute(ValidateCodeTask.Params(url, validationBody))
if (validationResponse.isSuccess()) { if (validationResponse.isSuccess()) {
@ -182,16 +184,16 @@ internal class DefaultRegistrationWizard(
override suspend fun dummy(): RegistrationResult { override suspend fun dummy(): RegistrationResult {
val safeSession = pendingSessionData.currentSession val safeSession = pendingSessionData.currentSession
?: throw IllegalStateException("developer error, call createAccount() method first") ?: throw IllegalStateException("developer error, call createAccount() method first")
val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.DUMMY, session = safeSession)) val params = RegistrationParams(auth = AuthParams(type = LoginFlowTypes.DUMMY, session = safeSession))
return performRegistrationRequest(params, LoginType.PASSWORD) return performRegistrationRequest(params, LoginType.PASSWORD)
} }
private suspend fun performRegistrationRequest( private suspend fun performRegistrationRequest(
registrationParams: RegistrationParams, registrationParams: RegistrationParams,
loginType: LoginType, loginType: LoginType,
delayMillis: Long = 0, delayMillis: Long = 0,
): RegistrationResult { ): RegistrationResult {
delay(delayMillis) delay(delayMillis)
val credentials = try { val credentials = try {
@ -199,7 +201,7 @@ internal class DefaultRegistrationWizard(
} catch (exception: Throwable) { } catch (exception: Throwable) {
if (exception is RegistrationFlowError) { if (exception is RegistrationFlowError) {
pendingSessionData = pendingSessionData.copy(currentSession = exception.registrationFlowResponse.session) pendingSessionData = pendingSessionData.copy(currentSession = exception.registrationFlowResponse.session)
.also { pendingSessionStore.savePendingSessionData(it) } .also { pendingSessionStore.savePendingSessionData(it) }
return RegistrationResult.FlowResponse(exception.registrationFlowResponse.toFlowResult()) return RegistrationResult.FlowResponse(exception.registrationFlowResponse.toFlowResult())
} else { } else {
throw exception throw exception

View file

@ -69,11 +69,11 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
private val commonOption: (FragmentTransaction) -> Unit = { ft -> private val commonOption: (FragmentTransaction) -> Unit = { ft ->
// Find the loginLogo on the current Fragment, this should not return null // Find the loginLogo on the current Fragment, this should not return null
(topFragment?.view as? ViewGroup) (topFragment?.view as? ViewGroup)
// Find findViewById does not work, I do not know why // Find findViewById does not work, I do not know why
// findViewById<View?>(R.id.loginLogo) // findViewById<View?>(R.id.loginLogo)
?.children ?.children
?.firstOrNull { it.id == R.id.loginLogo } ?.firstOrNull { it.id == R.id.loginLogo }
?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } ?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim) ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
} }
@ -107,7 +107,7 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
private fun handleLoginViewEvents(loginViewEvents: LoginViewEvents) { private fun handleLoginViewEvents(loginViewEvents: LoginViewEvents) {
when (loginViewEvents) { when (loginViewEvents) {
is LoginViewEvents.RegistrationFlowResult -> { is LoginViewEvents.RegistrationFlowResult -> {
// Check that all flows are supported by the application // Check that all flows are supported by the application
if (loginViewEvents.flowResult.missingStages.any { !it.isSupported() }) { if (loginViewEvents.flowResult.missingStages.any { !it.isSupported() }) {
// Display a popup to propose use web fallback // Display a popup to propose use web fallback
@ -121,80 +121,80 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
// I add a tag to indicate that this fragment is a registration stage. // I add a tag to indicate that this fragment is a registration stage.
// This way it will be automatically popped in when starting the next registration stage // This way it will be automatically popped in when starting the next registration stage
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginFragment::class.java, LoginFragment::class.java,
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption option = commonOption
) )
} }
} }
} }
is LoginViewEvents.OutdatedHomeserver -> { is LoginViewEvents.OutdatedHomeserver -> {
MaterialAlertDialogBuilder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.login_error_outdated_homeserver_title) .setTitle(R.string.login_error_outdated_homeserver_title)
.setMessage(R.string.login_error_outdated_homeserver_warning_content) .setMessage(R.string.login_error_outdated_homeserver_warning_content)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show() .show()
Unit Unit
} }
is LoginViewEvents.OpenServerSelection -> is LoginViewEvents.OpenServerSelection ->
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginServerSelectionFragment::class.java, LoginServerSelectionFragment::class.java,
option = { ft -> option = { ft ->
findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } findViewById<View?>(R.id.loginSplashLogo)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
// Disable transition of text // Disable transition of text
// findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } // findViewById<View?>(R.id.loginSplashTitle)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
// No transition here now actually // No transition here now actually
// findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") } // findViewById<View?>(R.id.loginSplashSubmit)?.let { ft.addSharedElement(it, ViewCompat.getTransitionName(it) ?: "") }
// TODO Disabled because it provokes a flickering // TODO Disabled because it provokes a flickering
// ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim) // ft.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim)
}) })
is LoginViewEvents.OnServerSelectionDone -> onServerSelectionDone(loginViewEvents) is LoginViewEvents.OnServerSelectionDone -> onServerSelectionDone(loginViewEvents)
is LoginViewEvents.OnSignModeSelected -> onSignModeSelected(loginViewEvents) is LoginViewEvents.OnSignModeSelected -> onSignModeSelected(loginViewEvents)
is LoginViewEvents.OnLoginFlowRetrieved -> is LoginViewEvents.OnLoginFlowRetrieved ->
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginSignUpSignInSelectionFragment::class.java, LoginSignUpSignInSelectionFragment::class.java,
option = commonOption) option = commonOption)
is LoginViewEvents.OnWebLoginError -> onWebLoginError(loginViewEvents) is LoginViewEvents.OnWebLoginError -> onWebLoginError(loginViewEvents)
is LoginViewEvents.OnForgetPasswordClicked -> is LoginViewEvents.OnForgetPasswordClicked ->
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginResetPasswordFragment::class.java, LoginResetPasswordFragment::class.java,
option = commonOption) option = commonOption)
is LoginViewEvents.OnResetPasswordSendThreePidDone -> { is LoginViewEvents.OnResetPasswordSendThreePidDone -> {
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE) supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginResetPasswordMailConfirmationFragment::class.java, LoginResetPasswordMailConfirmationFragment::class.java,
option = commonOption) option = commonOption)
} }
is LoginViewEvents.OnResetPasswordMailConfirmationSuccess -> { is LoginViewEvents.OnResetPasswordMailConfirmationSuccess -> {
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE) supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginResetPasswordSuccessFragment::class.java, LoginResetPasswordSuccessFragment::class.java,
option = commonOption) option = commonOption)
} }
is LoginViewEvents.OnResetPasswordMailConfirmationSuccessDone -> { is LoginViewEvents.OnResetPasswordMailConfirmationSuccessDone -> {
// Go back to the login fragment // Go back to the login fragment
supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE) supportFragmentManager.popBackStack(FRAGMENT_LOGIN_TAG, POP_BACK_STACK_EXCLUSIVE)
} }
is LoginViewEvents.OnSendEmailSuccess -> { is LoginViewEvents.OnSendEmailSuccess -> {
// Pop the enter email Fragment // Pop the enter email Fragment
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE) supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginWaitForEmailFragment::class.java, LoginWaitForEmailFragment::class.java,
LoginWaitForEmailFragmentArgument(loginViewEvents.email), LoginWaitForEmailFragmentArgument(loginViewEvents.email),
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption) option = commonOption)
} }
is LoginViewEvents.OnSendMsisdnSuccess -> { is LoginViewEvents.OnSendMsisdnSuccess -> {
// Pop the enter Msisdn Fragment // Pop the enter Msisdn Fragment
supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE) supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE)
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginGenericTextInputFormFragment::class.java, LoginGenericTextInputFormFragment::class.java,
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, loginViewEvents.msisdn), LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, loginViewEvents.msisdn),
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption) option = commonOption)
} }
is LoginViewEvents.Failure, is LoginViewEvents.Failure,
is LoginViewEvents.Loading -> is LoginViewEvents.Loading ->
// This is handled by the Fragments // This is handled by the Fragments
Unit Unit
}.exhaustive }.exhaustive
@ -207,8 +207,8 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
analyticsScreenName = MobileScreen.ScreenName.Register analyticsScreenName = MobileScreen.ScreenName.Register
} }
val intent = HomeActivity.newIntent( val intent = HomeActivity.newIntent(
this, this,
accountCreation = loginViewState.signMode == SignMode.SignUp accountCreation = loginViewState.signMode == SignMode.SignUp
) )
startActivity(intent) startActivity(intent)
finish() finish()
@ -225,55 +225,55 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
// And inform the user // And inform the user
MaterialAlertDialogBuilder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.dialog_title_error) .setTitle(R.string.dialog_title_error)
.setMessage(getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode)) .setMessage(getString(R.string.login_sso_error_message, onWebLoginError.description, onWebLoginError.errorCode))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show() .show()
} }
private fun onServerSelectionDone(loginViewEvents: LoginViewEvents.OnServerSelectionDone) { private fun onServerSelectionDone(loginViewEvents: LoginViewEvents.OnServerSelectionDone) {
when (loginViewEvents.serverType) { when (loginViewEvents.serverType) {
ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow
ServerType.EMS, ServerType.EMS,
ServerType.Other -> addFragmentToBackstack(views.loginFragmentContainer, ServerType.Other -> addFragmentToBackstack(views.loginFragmentContainer,
LoginServerUrlFormFragment::class.java, LoginServerUrlFormFragment::class.java,
option = commonOption) option = commonOption)
ServerType.Unknown -> Unit /* Should not happen */ ServerType.Unknown -> Unit /* Should not happen */
} }
} }
private fun onSignModeSelected(loginViewEvents: LoginViewEvents.OnSignModeSelected) = withState(loginViewModel) { state -> private fun onSignModeSelected(loginViewEvents: LoginViewEvents.OnSignModeSelected) = withState(loginViewModel) { state ->
// state.signMode could not be ready yet. So use value from the ViewEvent // state.signMode could not be ready yet. So use value from the ViewEvent
when (loginViewEvents.signMode) { when (loginViewEvents.signMode) {
SignMode.Unknown -> error("Sign mode has to be set before calling this method") SignMode.Unknown -> error("Sign mode has to be set before calling this method")
SignMode.SignUp -> { SignMode.SignUp -> {
// This is managed by the LoginViewEvents // This is managed by the LoginViewEvents
} }
SignMode.SignIn -> { SignMode.SignIn -> {
// It depends on the LoginMode // It depends on the LoginMode
when (state.loginMode) { when (state.loginMode) {
LoginMode.Unknown, LoginMode.Unknown -> error("Developer error")
is LoginMode.Sso -> launchSsoFlow() is LoginMode.Sso -> launchSsoFlow()
is LoginMode.SsoAndPassword, is LoginMode.SsoAndPassword,
LoginMode.Password -> addFragmentToBackstack(views.loginFragmentContainer, LoginMode.Password -> addFragmentToBackstack(views.loginFragmentContainer,
LoginFragment::class.java, LoginFragment::class.java,
tag = FRAGMENT_LOGIN_TAG, tag = FRAGMENT_LOGIN_TAG,
option = commonOption) option = commonOption)
LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes) LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes)
}.exhaustive }.exhaustive
} }
SignMode.SignInWithMatrixId -> addFragmentToBackstack(views.loginFragmentContainer, SignMode.SignInWithMatrixId -> addFragmentToBackstack(views.loginFragmentContainer,
LoginFragment::class.java, LoginFragment::class.java,
tag = FRAGMENT_LOGIN_TAG, tag = FRAGMENT_LOGIN_TAG,
option = commonOption) option = commonOption)
}.exhaustive }.exhaustive
} }
private fun launchSsoFlow() = withState(loginViewModel) { state -> private fun launchSsoFlow() = withState(loginViewModel) { state ->
loginViewModel.getSsoUrl( loginViewModel.getSsoUrl(
redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL, redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL,
deviceId = state.deviceId, deviceId = state.deviceId,
providerId = null, providerId = null,
)?.let { ssoUrl -> )?.let { ssoUrl ->
openUrlInChromeCustomTab(this, null, ssoUrl) openUrlInChromeCustomTab(this, null, ssoUrl)
} }
@ -286,34 +286,34 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
super.onNewIntent(intent) super.onNewIntent(intent)
intent?.data intent?.data
?.let { tryOrNull { it.getQueryParameter("loginToken") } } ?.let { tryOrNull { it.getQueryParameter("loginToken") } }
?.let { loginViewModel.handle(LoginAction.LoginWithToken(it)) } ?.let { loginViewModel.handle(LoginAction.LoginWithToken(it)) }
} }
private fun onRegistrationStageNotSupported() { private fun onRegistrationStageNotSupported() {
MaterialAlertDialogBuilder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.app_name) .setTitle(R.string.app_name)
.setMessage(getString(R.string.login_registration_not_supported)) .setMessage(getString(R.string.login_registration_not_supported))
.setPositiveButton(R.string.yes) { _, _ -> .setPositiveButton(R.string.yes) { _, _ ->
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginWebFragment::class.java, LoginWebFragment::class.java,
option = commonOption) option = commonOption)
} }
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
.show() .show()
} }
private fun onLoginModeNotSupported(supportedTypes: List<String>) { private fun onLoginModeNotSupported(supportedTypes: List<String>) {
MaterialAlertDialogBuilder(this) MaterialAlertDialogBuilder(this)
.setTitle(R.string.app_name) .setTitle(R.string.app_name)
.setMessage(getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" })) .setMessage(getString(R.string.login_mode_not_supported, supportedTypes.joinToString { "'$it'" }))
.setPositiveButton(R.string.yes) { _, _ -> .setPositiveButton(R.string.yes) { _, _ ->
addFragmentToBackstack(views.loginFragmentContainer, addFragmentToBackstack(views.loginFragmentContainer,
LoginWebFragment::class.java, LoginWebFragment::class.java,
option = commonOption) option = commonOption)
} }
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
.show() .show()
} }
private fun handleRegistrationNavigation(flowResult: FlowResult) { private fun handleRegistrationNavigation(flowResult: FlowResult) {
@ -339,26 +339,26 @@ open class LoginActivity : VectorBaseActivity<ActivityLoginBinding>(), UnlockedA
when (stage) { when (stage) {
is Stage.ReCaptcha -> addFragmentToBackstack(views.loginFragmentContainer, is Stage.ReCaptcha -> addFragmentToBackstack(views.loginFragmentContainer,
LoginCaptchaFragment::class.java, LoginCaptchaFragment::class.java,
LoginCaptchaFragmentArgument(stage.publicKey), LoginCaptchaFragmentArgument(stage.publicKey),
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption) option = commonOption)
is Stage.Email -> addFragmentToBackstack(views.loginFragmentContainer, is Stage.Email -> addFragmentToBackstack(views.loginFragmentContainer,
LoginGenericTextInputFormFragment::class.java, LoginGenericTextInputFormFragment::class.java,
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory), LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory),
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption) option = commonOption)
is Stage.Msisdn -> addFragmentToBackstack(views.loginFragmentContainer, is Stage.Msisdn -> addFragmentToBackstack(views.loginFragmentContainer,
LoginGenericTextInputFormFragment::class.java, LoginGenericTextInputFormFragment::class.java,
LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory), LoginGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory),
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption) option = commonOption)
is Stage.Terms -> addFragmentToBackstack(views.loginFragmentContainer, is Stage.Terms -> addFragmentToBackstack(views.loginFragmentContainer,
LoginTermsFragment::class.java, LoginTermsFragment::class.java,
LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))), LoginTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(getString(R.string.resources_language))),
tag = FRAGMENT_REGISTRATION_STAGE_TAG, tag = FRAGMENT_REGISTRATION_STAGE_TAG,
option = commonOption) option = commonOption)
else -> Unit // Should not happen else -> Unit // Should not happen
} }
} }