diff --git a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt index 5b36e4e628..55ec8b605e 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt @@ -94,6 +94,12 @@ fun AppCompatActivity.addFragmentToBackstack( } } +fun AppCompatActivity.resetBackstack() { + repeat(supportFragmentManager.backStackEntryCount) { + supportFragmentManager.popBackStack() + } +} + fun AppCompatActivity.hideKeyboard() { currentFocus?.hideKeyboard() } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt index 63c163fd6e..a9df217e3c 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt @@ -69,7 +69,8 @@ sealed class LoginAction2 : VectorViewModelAction { object ResetHomeServerUrl : ResetAction() object ResetSignMode : ResetAction() - object ResetLogin : ResetAction() + object ResetSignin : ResetAction() + object ResetSignup : ResetAction() object ResetResetPassword : ResetAction() // Homeserver history diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginActivity2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginActivity2.kt index dd96c14fec..deb489a34f 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginActivity2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginActivity2.kt @@ -36,6 +36,7 @@ import im.vector.app.core.extensions.POP_BACK_STACK_EXCLUSIVE import im.vector.app.core.extensions.addFragment import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.exhaustive +import im.vector.app.core.extensions.resetBackstack import im.vector.app.core.platform.ToolbarConfigurable import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityLoginBinding @@ -227,6 +228,7 @@ open class LoginActivity2 : VectorBaseActivity(), ToolbarC is LoginViewEvents2.OpenSignUpChooseUsernameScreen -> { addFragmentToBackstack(R.id.loginFragmentContainer, LoginFragment2SignupUsername::class.java, + tag = FRAGMENT_REGISTRATION_STAGE_TAG, option = commonOption) } is LoginViewEvents2.OpenSignInWithAnythingScreen -> { @@ -247,9 +249,15 @@ open class LoginActivity2 : VectorBaseActivity(), ToolbarC onLoginModeNotSupported(event.supportedTypes) is LoginViewEvents2.OnSessionCreated -> handleOnSessionCreated(event) is LoginViewEvents2.Finish -> terminate(true) + is LoginViewEvents2.CancelRegistration -> handleCancelRegistration() }.exhaustive } + private fun handleCancelRegistration() { + // Cleanup the back stack + resetBackstack() + } + private fun handleOnSessionCreated(event: LoginViewEvents2.OnSessionCreated) { if (event.newAccount) { // Propose to set avatar and display name diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt index 9c3ef6b94d..682fc4089e 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt @@ -182,7 +182,7 @@ class LoginCaptchaFragment2 @Inject constructor( } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignup) } override fun updateWithState(state: LoginViewState2) { diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninPassword.kt b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninPassword.kt index 39701cb01b..76657db891 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninPassword.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninPassword.kt @@ -154,7 +154,7 @@ class LoginFragment2SigninPassword @Inject constructor( } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignin) } override fun onError(throwable: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninUsername.kt b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninUsername.kt index ee83a0409a..1624e641a8 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninUsername.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SigninUsername.kt @@ -91,7 +91,7 @@ class LoginFragment2SigninUsername @Inject constructor() : AbstractLoginFragment } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignin) } override fun onError(throwable: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupPassword.kt b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupPassword.kt index 917e97306c..372d5dad79 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupPassword.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupPassword.kt @@ -129,7 +129,7 @@ class LoginFragment2SignupPassword @Inject constructor() : AbstractSSOLoginFragm } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + // loginViewModel.handle(LoginAction2.ResetSignup) } override fun onError(throwable: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupUsername.kt b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupUsername.kt index 3667f2f1b9..ce9add677d 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupUsername.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginFragment2SignupUsername.kt @@ -125,7 +125,7 @@ class LoginFragment2SignupUsername @Inject constructor() : AbstractSSOLoginFragm } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + // loginViewModel.handle(LoginAction2.ResetSignup) } override fun onError(throwable: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginFragmentToAny2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginFragmentToAny2.kt index 0768c9cdb9..252ae0482a 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginFragmentToAny2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginFragmentToAny2.kt @@ -182,7 +182,7 @@ class LoginFragmentToAny2 @Inject constructor() : AbstractSSOLoginFragment2() { +class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFragment2() { private val params: LoginGenericTextInputFormFragmentArgument by args() - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginGenericTextInputFormBinding { - return FragmentLoginGenericTextInputFormBinding.inflate(inflater, container, false) + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginGenericTextInputForm2Binding { + return FragmentLoginGenericTextInputForm2Binding.inflate(inflater, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -77,6 +78,7 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr private fun setupViews() { views.loginGenericTextInputFormOtherButton.setOnClickListener { onOtherButtonClicked() } views.loginGenericTextInputFormSubmit.setOnClickListener { submit() } + views.loginGenericTextInputFormLater.setOnClickListener { submit() } } private fun setupAutoFill() { @@ -102,9 +104,11 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr private fun setupUi() { when (params.mode) { TextInputFormFragmentMode.SetEmail -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_email_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_email_notice) - views.loginGenericTextInputFormNotice2.setTextOrHide(null) + views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_email_title_2) + views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_email_notice_2) + // Text will be updated with the state + views.loginGenericTextInputFormMandatoryNotice.isVisible = params.mandatory + views.loginGenericTextInputFormNotice2.isVisible = false views.loginGenericTextInputFormTil.hint = getString(if (params.mandatory) R.string.login_set_email_mandatory_hint else R.string.login_set_email_optional_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS @@ -112,8 +116,10 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr views.loginGenericTextInputFormSubmit.text = getString(R.string.login_set_email_submit) } TextInputFormFragmentMode.SetMsisdn -> { - views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_msisdn_title) - views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_msisdn_notice) + views.loginGenericTextInputFormTitle.text = getString(R.string.login_set_msisdn_title_2) + views.loginGenericTextInputFormNotice.text = getString(R.string.login_set_msisdn_notice_2) + // Text will be updated with the state + views.loginGenericTextInputFormMandatoryNotice.isVisible = params.mandatory views.loginGenericTextInputFormNotice2.setTextOrHide(getString(R.string.login_set_msisdn_notice2)) views.loginGenericTextInputFormTil.hint = getString(if (params.mandatory) R.string.login_set_msisdn_mandatory_hint else R.string.login_set_msisdn_optional_hint) @@ -124,7 +130,8 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr TextInputFormFragmentMode.ConfirmMsisdn -> { views.loginGenericTextInputFormTitle.text = getString(R.string.login_msisdn_confirm_title) views.loginGenericTextInputFormNotice.text = getString(R.string.login_msisdn_confirm_notice, params.extra) - views.loginGenericTextInputFormNotice2.setTextOrHide(null) + views.loginGenericTextInputFormMandatoryNotice.isVisible = false + views.loginGenericTextInputFormNotice2.isVisible = false views.loginGenericTextInputFormTil.hint = getString(R.string.login_msisdn_confirm_hint) views.loginGenericTextInputFormTextInput.inputType = InputType.TYPE_CLASS_NUMBER @@ -195,26 +202,31 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr private fun setupSubmitButton() { views.loginGenericTextInputFormSubmit.isEnabled = false views.loginGenericTextInputFormTextInput.textChanges() - .subscribe { - views.loginGenericTextInputFormSubmit.isEnabled = isInputValid(it) + .subscribe { text -> + views.loginGenericTextInputFormSubmit.isEnabled = isInputValid(text) + text?.let { updateSubmitButtons(it) } } .disposeOnDestroyView() } + private fun updateSubmitButtons(text: CharSequence) { + if (params.mandatory) { + views.loginGenericTextInputFormSubmit.isVisible = true + views.loginGenericTextInputFormLater.isVisible = false + } else { + views.loginGenericTextInputFormSubmit.isVisible = text.isNotEmpty() + views.loginGenericTextInputFormLater.isVisible = text.isEmpty() + } + } + private fun isInputValid(input: CharSequence): Boolean { return if (input.isEmpty() && !params.mandatory) { true } else { when (params.mode) { - TextInputFormFragmentMode.SetEmail -> { - input.isEmail() - } - TextInputFormFragmentMode.SetMsisdn -> { - input.isNotBlank() - } - TextInputFormFragmentMode.ConfirmMsisdn -> { - input.isNotBlank() - } + TextInputFormFragmentMode.SetEmail -> input.isEmail() + TextInputFormFragmentMode.SetMsisdn -> input.isNotBlank() + TextInputFormFragmentMode.ConfirmMsisdn -> input.isNotBlank() } } } @@ -253,6 +265,14 @@ class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFr } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignup) + } + + override fun updateWithState(state: LoginViewState2) { + views.loginGenericTextInputFormMandatoryNotice.text = when (params.mode) { + TextInputFormFragmentMode.SetEmail -> getString(R.string.login_set_email_mandatory_notice_2, state.homeServerUrlFromUser.toReducedUrl()) + TextInputFormFragmentMode.SetMsisdn -> getString(R.string.login_set_msisdn_mandatory_notice_2, state.homeServerUrlFromUser.toReducedUrl()) + TextInputFormFragmentMode.ConfirmMsisdn -> null + } } } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginViewEvents2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginViewEvents2.kt index 91cb6cac58..fd4cc76450 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginViewEvents2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginViewEvents2.kt @@ -48,6 +48,8 @@ sealed class LoginViewEvents2 : VectorViewEvents { object OnResetPasswordMailConfirmationSuccess : LoginViewEvents2() object OnResetPasswordMailConfirmationSuccessDone : LoginViewEvents2() + object CancelRegistration: LoginViewEvents2() + data class OnLoginModeNotSupported(val supportedTypes: List) : LoginViewEvents2() data class OnSendEmailSuccess(val email: String) : LoginViewEvents2() diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt index c412317b93..2e464043e4 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginViewModel2.kt @@ -44,7 +44,6 @@ import kotlinx.coroutines.launch import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.HomeServerHistoryService import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig -import org.matrix.android.sdk.api.auth.data.LoginFlowResult import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.registration.FlowResult @@ -379,11 +378,26 @@ class LoginViewModel2 @AssistedInject constructor( ) } } - LoginAction2.ResetLogin -> { + LoginAction2.ResetSignin -> { viewModelScope.launch { authenticationService.cancelPendingLoginOrRegistration() - setState { copy(isLoading = false) } + setState { + copy(isLoading = false) + } } + _viewEvents.post(LoginViewEvents2.CancelRegistration) + } + LoginAction2.ResetSignup -> { + viewModelScope.launch { + authenticationService.cancelPendingLoginOrRegistration() + setState { + // Always create a new state, to ensure the state is correctly reset + LoginViewState2( + knownCustomHomeServersUrls = knownCustomHomeServersUrls + ) + } + } + _viewEvents.post(LoginViewEvents2.CancelRegistration) } LoginAction2.ResetResetPassword -> { setState { @@ -397,8 +411,7 @@ class LoginViewModel2 @AssistedInject constructor( private fun handleUpdateSignMode(action: LoginAction2.UpdateSignMode) { setState { - // Always create a new state, to ensure the state is correctly reset - LoginViewState2( + copy( signMode = action.signMode ) } @@ -667,7 +680,7 @@ class LoginViewModel2 @AssistedInject constructor( if (safeLoginWizard != null) { setState { copy(loginProfileInfo = Loading()) } val result = tryAsync { - safeLoginWizard.getProfileInfo(username) + safeLoginWizard.getProfileInfo(username) } setState { copy(loginProfileInfo = result) } } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginWaitForEmailFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginWaitForEmailFragment2.kt index db3c607480..0cac52b306 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginWaitForEmailFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginWaitForEmailFragment2.kt @@ -70,6 +70,6 @@ class LoginWaitForEmailFragment2 @Inject constructor() : AbstractLoginFragment2< } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignup) } } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt index 2acb30bd8a..fb9a498b97 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt @@ -242,7 +242,7 @@ class LoginWebFragment2 @Inject constructor( } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignin) } override fun onBackPressed(toolbarButton: Boolean): Boolean { diff --git a/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt index ac174f4a48..fcd3268983 100755 --- a/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt @@ -114,6 +114,6 @@ class LoginTermsFragment2 @Inject constructor( } override fun resetViewModel() { - loginViewModel.handle(LoginAction2.ResetLogin) + loginViewModel.handle(LoginAction2.ResetSignup) } } diff --git a/vector/src/main/res/layout/fragment_login_generic_text_input_form_2.xml b/vector/src/main/res/layout/fragment_login_generic_text_input_form_2.xml new file mode 100644 index 0000000000..1ae081fd88 --- /dev/null +++ b/vector/src/main/res/layout/fragment_login_generic_text_input_form_2.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/values/strings_login_v2.xml b/vector/src/main/res/values/strings_login_v2.xml index 3062929050..23cc578ebd 100644 --- a/vector/src/main/res/values/strings_login_v2.xml +++ b/vector/src/main/res/values/strings_login_v2.xml @@ -35,4 +35,12 @@ Hello Matrix world! Click on the image and on your name to configure them. + Associate an email + Associate an email to be able to later recover your account, in case you forget your password. + The server %s requires you to associate an email to create an account. + + Associate a phone number + Associate a phone number to optionally allow people you know to discover you. + The server %s requires you to associate a phone number to create an account. + \ No newline at end of file