mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-03-01 06:07:37 +00:00
Improve username creation error debouncing.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.thoughtcrime.securesms.profiles.manage;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -9,8 +10,6 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -24,8 +23,6 @@ import androidx.navigation.Navigation;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicatorSpec;
|
||||
import com.google.android.material.progressindicator.IndeterminateDrawable;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import org.signal.core.util.DimensionUnit;
|
||||
@@ -52,6 +49,17 @@ public class UsernameEditFragment extends LoggingFragment {
|
||||
private LifecycleDisposable lifecycleDisposable;
|
||||
private UsernameEditFragmentArgs args;
|
||||
|
||||
private static final LayoutTransition ANIMATED_LAYOUT = new LayoutTransition();
|
||||
private static final LayoutTransition STATIC_LAYOUT = new LayoutTransition();
|
||||
|
||||
static {
|
||||
STATIC_LAYOUT.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
|
||||
STATIC_LAYOUT.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
|
||||
STATIC_LAYOUT.disableTransitionType(LayoutTransition.APPEARING);
|
||||
STATIC_LAYOUT.disableTransitionType(LayoutTransition.DISAPPEARING);
|
||||
STATIC_LAYOUT.disableTransitionType(LayoutTransition.CHANGING);
|
||||
}
|
||||
|
||||
public static UsernameEditFragment newInstance() {
|
||||
return new UsernameEditFragment();
|
||||
}
|
||||
@@ -155,6 +163,8 @@ public class UsernameEditFragment extends LoggingFragment {
|
||||
presentButtonState(state.buttonState);
|
||||
presentSummary(state.username);
|
||||
|
||||
binding.root.setLayoutTransition(ANIMATED_LAYOUT);
|
||||
|
||||
switch (state.usernameStatus) {
|
||||
case NONE:
|
||||
usernameInputWrapper.setError(null);
|
||||
@@ -190,6 +200,8 @@ public class UsernameEditFragment extends LoggingFragment {
|
||||
CharSequence error = usernameInputWrapper.getError();
|
||||
binding.usernameError.setVisibility(error != null ? View.VISIBLE : View.GONE);
|
||||
binding.usernameError.setText(usernameInputWrapper.getError());
|
||||
|
||||
binding.root.setLayoutTransition(STATIC_LAYOUT);
|
||||
}
|
||||
|
||||
private void presentButtonState(@NonNull UsernameEditViewModel.ButtonState buttonState) {
|
||||
|
||||
@@ -71,9 +71,19 @@ internal class UsernameEditViewModel private constructor(private val isInRegistr
|
||||
val invalidReason: InvalidReason? = checkUsername(nickname)
|
||||
|
||||
if (invalidReason != null) {
|
||||
State(ButtonState.SUBMIT_DISABLED, mapUsernameError(invalidReason), state.username)
|
||||
// We only want to show actual errors after debouncing. But we also don't want to allow users to submit names with errors.
|
||||
// So we disable submit, but we don't show an error yet.
|
||||
State(
|
||||
buttonState = ButtonState.SUBMIT_DISABLED,
|
||||
usernameStatus = UsernameStatus.NONE,
|
||||
username = state.username
|
||||
)
|
||||
} else {
|
||||
State(ButtonState.SUBMIT_DISABLED, UsernameStatus.NONE, state.username)
|
||||
State(
|
||||
buttonState = ButtonState.SUBMIT_DISABLED,
|
||||
usernameStatus = UsernameStatus.NONE,
|
||||
username = state.username
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +179,13 @@ internal class UsernameEditViewModel private constructor(private val isInRegistr
|
||||
|
||||
val invalidReason: InvalidReason? = checkUsername(nickname)
|
||||
if (invalidReason != null) {
|
||||
uiState.update { state ->
|
||||
State(
|
||||
buttonState = ButtonState.SUBMIT_DISABLED,
|
||||
usernameStatus = mapUsernameError(invalidReason),
|
||||
username = state.username
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -229,7 +246,8 @@ internal class UsernameEditViewModel private constructor(private val isInRegistr
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NICKNAME_PUBLISHER_DEBOUNCE_TIMEOUT_MILLIS: Long = 500
|
||||
private const val NICKNAME_PUBLISHER_DEBOUNCE_TIMEOUT_MILLIS: Long = 1000
|
||||
|
||||
private fun mapUsernameError(invalidReason: InvalidReason): UsernameStatus {
|
||||
return when (invalidReason) {
|
||||
InvalidReason.TOO_SHORT -> UsernameStatus.TOO_SHORT
|
||||
|
||||
Reference in New Issue
Block a user