diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditFragment.java b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditFragment.java index da9f3e5195..4321e6abf8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditFragment.java @@ -317,6 +317,9 @@ public class UsernameEditFragment extends LoggingFragment { case NETWORK_FAILURE: Toast.makeText(requireContext(), R.string.UsernameEditFragment_encountered_a_network_error, Toast.LENGTH_SHORT).show(); break; + case RATE_LIMIT_EXCEEDED: + Toast.makeText(requireContext(), R.string.UsernameEditFragment_rate_limit_exceeded_error, Toast.LENGTH_SHORT).show(); + break; case SKIPPED: closeScreen(); break; diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.kt index 8806517e9a..9dd7f024e3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameEditViewModel.kt @@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit * A note on naming conventions: * Usernames are made up of two discrete components, a nickname and a discriminator. They are formatted thusly: * - * [nickname].[discriminator] + * nickname.discriminator */ internal class UsernameEditViewModel private constructor(private val mode: UsernameEditMode) : ViewModel() { private val events: PublishSubject = PublishSubject.create() @@ -207,6 +207,11 @@ internal class UsernameEditViewModel private constructor(private val mode: Usern uiState.update { State(ButtonState.SUBMIT, UsernameStatus.NONE, it.usernameState) } events.onNext(Event.NETWORK_FAILURE) } + + UsernameSetResult.RATE_LIMIT_ERROR -> { + uiState.update { State(ButtonState.SUBMIT, UsernameStatus.NONE, it.usernameState) } + events.onNext(Event.RATE_LIMIT_EXCEEDED) + } } } } @@ -343,6 +348,11 @@ internal class UsernameEditViewModel private constructor(private val mode: Usern events.onNext(Event.NETWORK_FAILURE) } + UsernameSetResult.RATE_LIMIT_ERROR -> { + uiState.update { State(ButtonState.SUBMIT, UsernameStatus.NONE, UsernameState.NoUsername) } + events.onNext(Event.RATE_LIMIT_EXCEEDED) + } + UsernameSetResult.CANDIDATE_GENERATION_ERROR -> { // TODO -- Retry uiState.update { State(ButtonState.SUBMIT_DISABLED, UsernameStatus.TAKEN, UsernameState.NoUsername) } @@ -380,7 +390,7 @@ internal class UsernameEditViewModel private constructor(private val mode: Usern } enum class Event { - NETWORK_FAILURE, SUBMIT_SUCCESS, DELETE_SUCCESS, SUBMIT_FAIL_INVALID, SUBMIT_FAIL_TAKEN, SKIPPED, NEEDS_CONFIRM_RESET + NETWORK_FAILURE, SUBMIT_SUCCESS, DELETE_SUCCESS, SUBMIT_FAIL_INVALID, SUBMIT_FAIL_TAKEN, SKIPPED, NEEDS_CONFIRM_RESET, RATE_LIMIT_EXCEEDED } class Factory(private val mode: UsernameEditMode) : ViewModelProvider.Factory { diff --git a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt index 59bb796783..27dd0d60a5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/profiles/manage/UsernameRepository.kt @@ -23,6 +23,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager import org.whispersystems.signalservice.api.push.ServiceId.ACI import org.whispersystems.signalservice.api.push.UsernameLinkComponents import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException +import org.whispersystems.signalservice.api.push.exceptions.RateLimitException import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotAssociatedWithAnAccountException import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotReservedException import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException @@ -379,6 +380,9 @@ object UsernameRepository { } catch (e: UsernameMalformedException) { Log.w(TAG, "[reserveUsername] Username malformed.") failure(UsernameSetResult.USERNAME_INVALID) + } catch (e: RateLimitException) { + Log.w(TAG, "[reserveUsername] Rate limit exceeded.") + failure(UsernameSetResult.RATE_LIMIT_ERROR) } catch (e: IOException) { Log.w(TAG, "[reserveUsername] Generic network exception.", e) failure(UsernameSetResult.NETWORK_ERROR) @@ -501,7 +505,7 @@ object UsernameRepository { } enum class UsernameSetResult { - SUCCESS, USERNAME_UNAVAILABLE, USERNAME_INVALID, NETWORK_ERROR, CANDIDATE_GENERATION_ERROR + SUCCESS, USERNAME_UNAVAILABLE, USERNAME_INVALID, NETWORK_ERROR, CANDIDATE_GENERATION_ERROR, RATE_LIMIT_ERROR } enum class UsernameReclaimResult { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 682b1daea3..8e54b279a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2298,6 +2298,8 @@ Delete Successfully removed username. Encountered a network error. + + Too many attempts made, please try again later. This username is taken. Usernames can only include a–Z, 0–9, and underscores. Usernames cannot begin with a number.