Do not repeat password fields for account creation or reset password

This commit is contained in:
Benoit Marty 2021-04-19 13:39:32 +02:00 committed by Benoit Marty
parent d235d1be15
commit ef55ddd683
5 changed files with 82 additions and 144 deletions

View File

@ -28,7 +28,6 @@ import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.showPassword import im.vector.app.core.extensions.showPassword
import im.vector.app.databinding.FragmentLoginSignupPassword2Binding import im.vector.app.databinding.FragmentLoginSignupPassword2Binding
import io.reactivex.rxkotlin.Observables
import io.reactivex.rxkotlin.subscribeBy import io.reactivex.rxkotlin.subscribeBy
import javax.inject.Inject import javax.inject.Inject
@ -38,7 +37,7 @@ import javax.inject.Inject
*/ */
class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment2<FragmentLoginSignupPassword2Binding>() { class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment2<FragmentLoginSignupPassword2Binding>() {
private var passwordsShown = false private var passwordShown = false
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginSignupPassword2Binding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginSignupPassword2Binding {
return FragmentLoginSignupPassword2Binding.inflate(inflater, container, false) return FragmentLoginSignupPassword2Binding.inflate(inflater, container, false)
@ -51,7 +50,7 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
setupAutoFill() setupAutoFill()
setupPasswordReveal() setupPasswordReveal()
views.passwordFieldRepeat.setOnEditorActionListener { _, actionId, _ -> views.passwordField.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
submit() submit()
return@setOnEditorActionListener true return@setOnEditorActionListener true
@ -63,7 +62,6 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
private fun setupAutoFill() { private fun setupAutoFill() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD) views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
views.passwordFieldRepeat.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
} }
} }
@ -79,13 +77,6 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
error++ error++
} }
val passwordRepeat = views.passwordFieldRepeat.text.toString()
if (password != passwordRepeat) {
views.passwordFieldTilRepeat.error = getString(R.string.auth_password_dont_match)
error++
}
if (error == 0) { if (error == 0) {
loginViewModel.handle(LoginAction2.SetUserPassword(password)) loginViewModel.handle(LoginAction2.SetUserPassword(password))
} }
@ -98,23 +89,19 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
private fun setupSubmitButton() { private fun setupSubmitButton() {
views.loginSubmit.setOnClickListener { submit() } views.loginSubmit.setOnClickListener { submit() }
Observables.combineLatest( views.passwordField.textChanges()
views.passwordField.textChanges(), .subscribeBy { password ->
views.passwordFieldRepeat.textChanges()
)
.subscribeBy { (password, passwordRepeat) ->
views.passwordFieldTil.error = null views.passwordFieldTil.error = null
views.passwordFieldTilRepeat.error = null views.loginSubmit.isEnabled = password.isNotEmpty()
views.loginSubmit.isEnabled = password.isNotEmpty() && passwordRepeat.isNotEmpty()
} }
.disposeOnDestroyView() .disposeOnDestroyView()
} }
private fun setupPasswordReveal() { private fun setupPasswordReveal() {
passwordsShown = false passwordShown = false
views.passwordReveal.setOnClickListener { views.passwordReveal.setOnClickListener {
passwordsShown = !passwordsShown passwordShown = !passwordShown
renderPasswordField() renderPasswordField()
} }
@ -123,9 +110,8 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
} }
private fun renderPasswordField() { private fun renderPasswordField() {
views.passwordReveal.render(passwordsShown) views.passwordReveal.render(passwordShown)
views.passwordField.showPassword(passwordsShown) views.passwordField.showPassword(passwordShown)
views.passwordFieldRepeat.showPassword(passwordsShown)
} }
override fun resetViewModel() { override fun resetViewModel() {
@ -140,8 +126,8 @@ class LoginFragmentSignupPassword2 @Inject constructor() : AbstractLoginFragment
views.loginMatrixIdentifier.text = state.userIdentifier() views.loginMatrixIdentifier.text = state.userIdentifier()
if (state.isLoading) { if (state.isLoading) {
// Ensure passwords are hidden // Ensure password is hidden
passwordsShown = false passwordShown = false
renderPasswordField() renderPasswordField()
} }
} }

View File

@ -42,7 +42,7 @@ import javax.inject.Inject
*/ */
class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2<FragmentLoginResetPassword2Binding>() { class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2<FragmentLoginResetPassword2Binding>() {
private var passwordsShown = false private var passwordShown = false
// Show warning only once // Show warning only once
private var showWarning = true private var showWarning = true
@ -58,9 +58,9 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
setupPasswordReveal() setupPasswordReveal()
setupAutoFill() setupAutoFill()
autoResetTextInputLayoutErrors(listOf(views.resetPasswordEmailTil, views.passwordFieldTil, views.passwordFieldTilRepeat)) autoResetTextInputLayoutErrors(listOf(views.resetPasswordEmailTil, views.passwordFieldTil))
views.passwordFieldRepeat.setOnEditorActionListener { _, actionId, _ -> views.passwordField.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) { if (actionId == EditorInfo.IME_ACTION_DONE) {
submit() submit()
return@setOnEditorActionListener true return@setOnEditorActionListener true
@ -73,7 +73,6 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
views.resetPasswordEmail.setAutofillHints(HintConstants.AUTOFILL_HINT_EMAIL_ADDRESS) views.resetPasswordEmail.setAutofillHints(HintConstants.AUTOFILL_HINT_EMAIL_ADDRESS)
views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD) views.passwordField.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
views.passwordFieldRepeat.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
} }
} }
@ -105,7 +104,6 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
val email = views.resetPasswordEmail.text.toString() val email = views.resetPasswordEmail.text.toString()
val password = views.passwordField.text.toString() val password = views.passwordField.text.toString()
val passwordRepeat = views.passwordFieldRepeat.text.toString()
if (email.isEmpty()) { if (email.isEmpty()) {
views.resetPasswordEmailTil.error = getString(R.string.auth_reset_password_missing_email) views.resetPasswordEmailTil.error = getString(R.string.auth_reset_password_missing_email)
@ -115,9 +113,6 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
if (password.isEmpty()) { if (password.isEmpty()) {
views.passwordFieldTil.error = getString(R.string.login_please_choose_a_new_password) views.passwordFieldTil.error = getString(R.string.login_please_choose_a_new_password)
error++ error++
} else if (password != passwordRepeat) {
views.passwordFieldTilRepeat.error = getString(R.string.auth_password_dont_match)
error++
} }
if (error > 0) { if (error > 0) {
@ -151,14 +146,13 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
views.resetPasswordSubmit.hideKeyboard() views.resetPasswordSubmit.hideKeyboard()
views.resetPasswordEmailTil.error = null views.resetPasswordEmailTil.error = null
views.passwordFieldTil.error = null views.passwordFieldTil.error = null
views.passwordFieldTilRepeat.error = null
} }
private fun setupPasswordReveal() { private fun setupPasswordReveal() {
passwordsShown = false passwordShown = false
views.passwordReveal.setOnClickListener { views.passwordReveal.setOnClickListener {
passwordsShown = !passwordsShown passwordShown = !passwordShown
renderPasswordField() renderPasswordField()
} }
@ -167,9 +161,8 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
} }
private fun renderPasswordField() { private fun renderPasswordField() {
views.passwordField.showPassword(passwordsShown) views.passwordField.showPassword(passwordShown)
views.passwordFieldRepeat.showPassword(passwordsShown) views.passwordReveal.render(passwordShown)
views.passwordReveal.render(passwordsShown)
} }
override fun resetViewModel() { override fun resetViewModel() {
@ -184,8 +177,8 @@ class LoginResetPasswordFragment2 @Inject constructor() : AbstractLoginFragment2
setupUi(state) setupUi(state)
if (state.isLoading) { if (state.isLoading) {
// Ensure new passwords are hidden // Ensure new password is hidden
passwordsShown = false passwordShown = false
renderPasswordField() renderPasswordField()
} }
} }

View File

@ -57,36 +57,25 @@
android:text="@string/login_reset_password_notice" android:text="@string/login_reset_password_notice"
android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small" /> android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small" />
<FrameLayout
android:id="@+id/passwordLabelContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginTop="16dp"
android:text="@string/login_choose_a_new_password" android:text="@string/login_choose_a_new_password"
android:textAppearance="@style/TextAppearance.Vector.Login.Title.Small" /> android:textAppearance="@style/TextAppearance.Vector.Login.Title.Small" />
<im.vector.app.core.ui.views.RevealPasswordImageView <FrameLayout
android:id="@+id/passwordReveal" android:id="@+id/passwordContainer"
android:layout_width="@dimen/layout_touch_size" android:layout_width="match_parent"
android:layout_height="@dimen/layout_touch_size" android:layout_height="wrap_content"
android:layout_gravity="end" android:layout_marginTop="8dp">
android:background="?attr/selectableItemBackground"
android:scaleType="center"
app:tint="?attr/colorAccent" />
</FrameLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordFieldTil" android:id="@+id/passwordFieldTil"
style="@style/VectorTextInputLayout" style="@style/VectorTextInputLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/login_reset_password_password_hint" android:hint="@string/login_reset_password_password_hint"
app:errorEnabled="true" app:errorEnabled="true"
app:errorIconDrawable="@null"> app:errorIconDrawable="@null">
@ -96,34 +85,26 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:ems="10"
android:inputType="textPassword"
android:maxLines="1"
tools:ignore="RtlSymmetry" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordFieldTilRepeat"
style="@style/VectorTextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/login_signup_password_repeat_hint"
app:errorEnabled="true"
app:errorIconDrawable="@null">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordFieldRepeat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:imeOptions="actionDone" android:imeOptions="actionDone"
android:inputType="textPassword" android:inputType="textPassword"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="48dp"
tools:ignore="RtlSymmetry" /> tools:ignore="RtlSymmetry" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<im.vector.app.core.ui.views.RevealPasswordImageView
android:id="@+id/passwordReveal"
android:layout_width="@dimen/layout_touch_size"
android:layout_height="@dimen/layout_touch_size"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackground"
android:scaleType="center"
app:tint="?attr/colorAccent" />
</FrameLayout>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/resetPasswordSubmit" android:id="@+id/resetPasswordSubmit"
style="@style/Style.Vector.Login.Button" style="@style/Style.Vector.Login.Button"

View File

@ -45,36 +45,25 @@
android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small" android:textAppearance="@style/TextAppearance.Vector.Login.Text.Small"
android:textStyle="italic" /> android:textStyle="italic" />
<FrameLayout
android:id="@+id/passwordLabelContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginTop="@dimen/layout_vertical_margin"
android:text="@string/login_choose_a_password" android:text="@string/login_choose_a_password"
android:textAppearance="@style/TextAppearance.Vector.Login.Title.Small" /> android:textAppearance="@style/TextAppearance.Vector.Login.Title.Small" />
<im.vector.app.core.ui.views.RevealPasswordImageView <FrameLayout
android:id="@+id/passwordReveal" android:id="@+id/passwordContainer"
android:layout_width="@dimen/layout_touch_size" android:layout_width="match_parent"
android:layout_height="@dimen/layout_touch_size" android:layout_height="wrap_content"
android:layout_gravity="end" android:layout_marginTop="8dp">
android:background="?attr/selectableItemBackground"
android:scaleType="center"
app:tint="?attr/colorAccent" />
</FrameLayout>
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordFieldTil" android:id="@+id/passwordFieldTil"
style="@style/VectorTextInputLayout" style="@style/VectorTextInputLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/login_signup_password_hint" android:hint="@string/login_signup_password_hint"
app:errorEnabled="true" app:errorEnabled="true"
app:errorIconDrawable="@null"> app:errorIconDrawable="@null">
@ -84,36 +73,26 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:ems="10"
android:imeOptions="actionNext"
android:inputType="textPassword"
android:maxLines="1"
tools:ignore="RtlSymmetry" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordFieldTilRepeat"
style="@style/VectorTextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/login_signup_password_repeat_hint"
app:errorEnabled="true"
app:errorIconDrawable="@null">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/passwordFieldRepeat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:imeOptions="actionDone" android:imeOptions="actionDone"
android:inputType="textPassword" android:inputType="textPassword"
android:maxLines="1" android:maxLines="1"
android:paddingEnd="48dp"
tools:ignore="RtlSymmetry" /> tools:ignore="RtlSymmetry" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<im.vector.app.core.ui.views.RevealPasswordImageView
android:id="@+id/passwordReveal"
android:layout_width="@dimen/layout_touch_size"
android:layout_height="@dimen/layout_touch_size"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackground"
android:scaleType="center"
app:tint="?attr/colorAccent" />
</FrameLayout>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/loginSubmit" android:id="@+id/loginSubmit"
style="@style/Style.Vector.Login.Button" style="@style/Style.Vector.Login.Button"

View File

@ -3,7 +3,6 @@
<!-- Those strings are not final, so do not put them into Weblate for the moment --> <!-- Those strings are not final, so do not put them into Weblate for the moment -->
<string name="login_signup_password_repeat_hint">Type it again</string>
<string name="login_welcome_back">Welcome back %s!</string> <string name="login_welcome_back">Welcome back %s!</string>
<string name="login_please_enter_your_password">Please enter your password</string> <string name="login_please_enter_your_password">Please enter your password</string>
<string name="login_please_enter_your_matrix_identifier">Please enter your Matrix identifier</string> <string name="login_please_enter_your_matrix_identifier">Please enter your Matrix identifier</string>