This commit is contained in:
Benoit Marty 2021-04-15 10:37:40 +02:00 committed by Benoit Marty
parent f0433fd27d
commit 7117427686
17 changed files with 214 additions and 38 deletions

View file

@ -94,6 +94,12 @@ fun <T : Fragment> AppCompatActivity.addFragmentToBackstack(
}
}
fun AppCompatActivity.resetBackstack() {
repeat(supportFragmentManager.backStackEntryCount) {
supportFragmentManager.popBackStack()
}
}
fun AppCompatActivity.hideKeyboard() {
currentFocus?.hideKeyboard()
}

View file

@ -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

View file

@ -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<ActivityLoginBinding>(), 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<ActivityLoginBinding>(), 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

View file

@ -182,7 +182,7 @@ class LoginCaptchaFragment2 @Inject constructor(
}
override fun resetViewModel() {
loginViewModel.handle(LoginAction2.ResetLogin)
loginViewModel.handle(LoginAction2.ResetSignup)
}
override fun updateWithState(state: LoginViewState2) {

View file

@ -154,7 +154,7 @@ class LoginFragment2SigninPassword @Inject constructor(
}
override fun resetViewModel() {
loginViewModel.handle(LoginAction2.ResetLogin)
loginViewModel.handle(LoginAction2.ResetSignin)
}
override fun onError(throwable: Throwable) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -182,7 +182,7 @@ class LoginFragmentToAny2 @Inject constructor() : AbstractSSOLoginFragment2<Frag
}
override fun resetViewModel() {
loginViewModel.handle(LoginAction2.ResetLogin)
// loginViewModel.handle(LoginAction2.ResetSignin)
}
override fun onError(throwable: Throwable) {

View file

@ -33,7 +33,8 @@ import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.isEmail
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.databinding.FragmentLoginGenericTextInputFormBinding
import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.databinding.FragmentLoginGenericTextInputForm2Binding
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.auth.registration.RegisterThreePid
import org.matrix.android.sdk.api.failure.Failure
@ -56,12 +57,12 @@ data class LoginGenericTextInputFormFragmentArgument(
/**
* In this screen, the user is asked for a text input
*/
class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFragment2<FragmentLoginGenericTextInputFormBinding>() {
class LoginGenericTextInputFormFragment2 @Inject constructor() : AbstractLoginFragment2<FragmentLoginGenericTextInputForm2Binding>() {
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
}
}
}

View file

@ -48,6 +48,8 @@ sealed class LoginViewEvents2 : VectorViewEvents {
object OnResetPasswordMailConfirmationSuccess : LoginViewEvents2()
object OnResetPasswordMailConfirmationSuccessDone : LoginViewEvents2()
object CancelRegistration: LoginViewEvents2()
data class OnLoginModeNotSupported(val supportedTypes: List<String>) : LoginViewEvents2()
data class OnSendEmailSuccess(val email: String) : LoginViewEvents2()

View file

@ -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) }
}

View file

@ -70,6 +70,6 @@ class LoginWaitForEmailFragment2 @Inject constructor() : AbstractLoginFragment2<
}
override fun resetViewModel() {
loginViewModel.handle(LoginAction2.ResetLogin)
loginViewModel.handle(LoginAction2.ResetSignup)
}
}

View file

@ -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 {

View file

@ -114,6 +114,6 @@ class LoginTermsFragment2 @Inject constructor(
}
override fun resetViewModel() {
loginViewModel.handle(LoginAction2.ResetLogin)
loginViewModel.handle(LoginAction2.ResetSignup)
}
}

View file

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/login_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?riotx_background">
<androidx.core.widget.NestedScrollView style="@style/LoginFormScrollView">
<LinearLayout style="@style/LoginFormContainer">
<ImageView
style="@style/LoginLogo"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/loginGenericTextInputFormTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:textAppearance="@style/TextAppearance.Vector.Login.Title"
tools:text="@string/login_set_email_title_2" />
<TextView
android:id="@+id/loginGenericTextInputFormNotice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:layout_marginBottom="@dimen/layout_vertical_margin"
android:gravity="start"
android:textAppearance="@style/TextAppearance.Vector.Login.Text"
tools:text="@string/login_set_email_notice_2" />
<TextView
android:id="@+id/loginGenericTextInputFormMandatoryNotice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="26dp"
android:gravity="start"
android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small"
android:visibility="gone"
tools:text="@string/login_set_email_mandatory_notice_2"
tools:visibility="visible" />
<TextView
android:id="@+id/loginGenericTextInputFormNotice2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small"
android:visibility="gone"
tools:text="@string/login_set_msisdn_notice2"
tools:visibility="visible" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/loginGenericTextInputFormTil"
style="@style/VectorTextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true"
tools:hint="@string/login_set_email_optional_hint">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/loginGenericTextInputFormTextInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:maxLines="1"
tools:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/loginGenericTextInputFormOtherButton"
style="@style/Style.Vector.Login.Button.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:visibility="gone"
tools:text="@string/login_msisdn_confirm_send_again"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/loginGenericTextInputFormLater"
style="@style/Style.Vector.Login.Button.Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@string/later"
android:visibility="gone"
tools:layout_marginEnd="100dp"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/loginGenericTextInputFormSubmit"
style="@style/Style.Vector.Login.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:enabled="false"
tools:ignore="RelativeOverlap"
tools:text="@string/login_set_email_submit" />
</FrameLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>

View file

@ -35,4 +35,12 @@
<string name="login_account_created_message">Hello Matrix world!</string>
<string name="login_account_created_instruction">Click on the image and on your name to configure them.</string>
<string name="login_set_email_title_2">Associate an email</string>
<string name="login_set_email_notice_2">Associate an email to be able to later recover your account, in case you forget your password.</string>
<string name="login_set_email_mandatory_notice_2">The server %s requires you to associate an email to create an account.</string>
<string name="login_set_msisdn_title_2">Associate a phone number</string>
<string name="login_set_msisdn_notice_2">Associate a phone number to optionally allow people you know to discover you.</string>
<string name="login_set_msisdn_mandatory_notice_2">The server %s requires you to associate a phone number to create an account.</string>
</resources>