mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-15 07:28:30 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
508688e533 | ||
|
|
eef0f299b7 | ||
|
|
f9e8ace5f7 |
@@ -22,8 +22,8 @@ plugins {
|
||||
apply(from = "static-ips.gradle.kts")
|
||||
|
||||
val canonicalVersionCode = 1436
|
||||
val canonicalVersionName = "7.11.3"
|
||||
val currentHotfixVersion = 0
|
||||
val canonicalVersionName = "7.11.4"
|
||||
val currentHotfixVersion = 1
|
||||
val maxHotfixVersions = 100
|
||||
|
||||
val keystores: Map<String, Properties?> = mapOf("debug" to loadKeystoreProperties("keystore.debug.properties"))
|
||||
|
||||
@@ -5,19 +5,9 @@
|
||||
|
||||
package org.thoughtcrime.securesms.registration.ui
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber
|
||||
|
||||
fun PhoneNumber.toE164(): String {
|
||||
return PhoneNumberUtil.getInstance().format(this, PhoneNumberUtil.PhoneNumberFormat.E164)
|
||||
}
|
||||
|
||||
fun Fragment.isBindingInvalid(): Boolean {
|
||||
if (view == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
return viewLifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)
|
||||
}
|
||||
|
||||
@@ -11,10 +11,12 @@ import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.signal.core.util.logging.Log
|
||||
@@ -31,7 +33,6 @@ import org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegat
|
||||
import org.thoughtcrime.securesms.registration.fragments.SignalStrengthPhoneStateListener
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationCheckpoint
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationViewModel
|
||||
import org.thoughtcrime.securesms.registration.ui.isBindingInvalid
|
||||
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
@@ -48,17 +49,15 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||
private val TAG = Log.tag(EnterCodeFragment::class.java)
|
||||
|
||||
private val sharedViewModel by activityViewModels<RegistrationViewModel>()
|
||||
private val bottomSheet = ContactSupportBottomSheetFragment()
|
||||
private val binding: FragmentRegistrationEnterCodeBinding by ViewBinderDelegate(FragmentRegistrationEnterCodeBinding::bind)
|
||||
|
||||
private lateinit var phoneStateListener: SignalStrengthPhoneStateListener
|
||||
|
||||
private var autopilotCodeEntryActive = false
|
||||
|
||||
private val bottomSheet = ContactSupportBottomSheetFragment()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setDebugLogSubmitMultiTapView(binding.verifyHeader)
|
||||
|
||||
phoneStateListener = SignalStrengthPhoneStateListener(this, PhoneStateCallback())
|
||||
@@ -134,34 +133,28 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||
}
|
||||
|
||||
private fun handleSessionErrorResponse(result: RegistrationResult) {
|
||||
if (isBindingInvalid()) {
|
||||
Log.w(TAG, "Binding not valid, aborting! Result: $result")
|
||||
result.logCause()
|
||||
return
|
||||
}
|
||||
when (result) {
|
||||
is VerificationCodeRequestResult.Success -> binding.keyboard.displaySuccess()
|
||||
is VerificationCodeRequestResult.RateLimited -> presentRateLimitedDialog()
|
||||
is VerificationCodeRequestResult.AttemptsExhausted -> presentAccountLocked()
|
||||
is VerificationCodeRequestResult.RegistrationLocked -> presentRegistrationLocked(result.timeRemaining)
|
||||
else -> presentGenericError(result)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
when (result) {
|
||||
is VerificationCodeRequestResult.Success -> binding.keyboard.displaySuccess()
|
||||
is VerificationCodeRequestResult.RateLimited -> presentRateLimitedDialog()
|
||||
is VerificationCodeRequestResult.AttemptsExhausted -> presentAccountLocked()
|
||||
is VerificationCodeRequestResult.RegistrationLocked -> presentRegistrationLocked(result.timeRemaining)
|
||||
else -> presentGenericError(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRegistrationErrorResponse(result: RegisterAccountResult) {
|
||||
if (isBindingInvalid()) {
|
||||
Log.w(TAG, "Binding not valid, aborting! Result: $result")
|
||||
result.logCause()
|
||||
return
|
||||
}
|
||||
when (result) {
|
||||
is RegisterAccountResult.Success -> binding.keyboard.displaySuccess()
|
||||
is RegisterAccountResult.RegistrationLocked -> presentRegistrationLocked(result.timeRemaining)
|
||||
is RegisterAccountResult.AuthorizationFailed -> presentIncorrectCodeDialog()
|
||||
is RegisterAccountResult.AttemptsExhausted -> presentAccountLocked()
|
||||
is RegisterAccountResult.RateLimited -> presentRateLimitedDialog()
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
when (result) {
|
||||
is RegisterAccountResult.Success -> binding.keyboard.displaySuccess()
|
||||
is RegisterAccountResult.RegistrationLocked -> presentRegistrationLocked(result.timeRemaining)
|
||||
is RegisterAccountResult.AuthorizationFailed -> presentIncorrectCodeDialog()
|
||||
is RegisterAccountResult.AttemptsExhausted -> presentAccountLocked()
|
||||
is RegisterAccountResult.RateLimited -> presentRateLimitedDialog()
|
||||
|
||||
else -> presentGenericError(result)
|
||||
else -> presentGenericError(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,22 +202,19 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||
private fun presentIncorrectCodeDialog() {
|
||||
sharedViewModel.incrementIncorrectCodeAttempts()
|
||||
|
||||
Toast.makeText(requireContext(), R.string.RegistrationActivity_incorrect_code, Toast.LENGTH_LONG).show()
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
Toast.makeText(requireContext(), R.string.RegistrationActivity_incorrect_code, Toast.LENGTH_LONG).show()
|
||||
|
||||
if (isBindingInvalid()) {
|
||||
Log.w(TAG, "Binding not valid, aborting updating keyboard!")
|
||||
return
|
||||
binding.keyboard.displayFailure().addListener(object : AssertedSuccessListener<Boolean?>() {
|
||||
override fun onSuccess(result: Boolean?) {
|
||||
binding.callMeCountDown.visibility = View.VISIBLE
|
||||
binding.resendSmsCountDown.visibility = View.VISIBLE
|
||||
binding.wrongNumber.visibility = View.VISIBLE
|
||||
binding.code.clear()
|
||||
binding.keyboard.displayKeyboard()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
binding.keyboard.displayFailure().addListener(object : AssertedSuccessListener<Boolean?>() {
|
||||
override fun onSuccess(result: Boolean?) {
|
||||
binding.callMeCountDown.visibility = View.VISIBLE
|
||||
binding.resendSmsCountDown.visibility = View.VISIBLE
|
||||
binding.wrongNumber.visibility = View.VISIBLE
|
||||
binding.code.clear()
|
||||
binding.keyboard.displayKeyboard()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun presentGenericError(requestResult: RegistrationResult) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.core.view.MenuProvider
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.android.gms.common.ConnectionResult
|
||||
@@ -35,6 +36,7 @@ import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.i18n.phonenumbers.NumberParseException
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.isNotNullOrBlank
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.LoggingFragment
|
||||
@@ -51,7 +53,6 @@ import org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegat
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationCheckpoint
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationState
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationViewModel
|
||||
import org.thoughtcrime.securesms.registration.ui.isBindingInvalid
|
||||
import org.thoughtcrime.securesms.registration.ui.toE164
|
||||
import org.thoughtcrime.securesms.registration.util.CountryPrefix
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
@@ -300,54 +301,59 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||
}
|
||||
|
||||
private fun handleErrorResponse(result: RegistrationResult) {
|
||||
if (isBindingInvalid()) {
|
||||
Log.w(TAG, "Binding not valid, aborting! Result: $result")
|
||||
result.logCause()
|
||||
return
|
||||
}
|
||||
if (!result.isSuccess()) {
|
||||
Log.i(TAG, "Handling error response.", result.getCause())
|
||||
}
|
||||
when (result) {
|
||||
is RegistrationSessionCreationResult.Success,
|
||||
is VerificationCodeRequestResult.Success -> Unit
|
||||
is RegistrationSessionCreationResult.AttemptsExhausted,
|
||||
is VerificationCodeRequestResult.AttemptsExhausted -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_rate_limited_to_service))
|
||||
is VerificationCodeRequestResult.ChallengeRequired -> {
|
||||
handleChallenges(result.challenges)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
if (!result.isSuccess()) {
|
||||
Log.i(TAG, "Handling error response.", result.getCause())
|
||||
}
|
||||
is VerificationCodeRequestResult.ExternalServiceFailure -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service), skipToNextScreen)
|
||||
is VerificationCodeRequestResult.ImpossibleNumber -> {
|
||||
MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setMessage(getString(R.string.RegistrationActivity_the_number_you_specified_s_is_invalid, fragmentViewModel.phoneNumber?.toE164()))
|
||||
setPositiveButton(android.R.string.ok, null)
|
||||
show()
|
||||
when (result) {
|
||||
is RegistrationSessionCreationResult.Success,
|
||||
is VerificationCodeRequestResult.Success -> Unit
|
||||
|
||||
is RegistrationSessionCreationResult.AttemptsExhausted,
|
||||
is VerificationCodeRequestResult.AttemptsExhausted -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_rate_limited_to_service))
|
||||
|
||||
is VerificationCodeRequestResult.ChallengeRequired -> {
|
||||
handleChallenges(result.challenges)
|
||||
}
|
||||
}
|
||||
is VerificationCodeRequestResult.InvalidTransportModeFailure -> {
|
||||
MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setMessage(R.string.RegistrationActivity_we_couldnt_send_you_a_verification_code)
|
||||
setPositiveButton(R.string.RegistrationActivity_voice_call) { _, _ ->
|
||||
sharedViewModel.requestVerificationCall(requireContext(), ::handleErrorResponse)
|
||||
|
||||
is VerificationCodeRequestResult.ExternalServiceFailure -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service), skipToNextScreen)
|
||||
is VerificationCodeRequestResult.ImpossibleNumber -> {
|
||||
MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setMessage(getString(R.string.RegistrationActivity_the_number_you_specified_s_is_invalid, fragmentViewModel.phoneNumber?.toE164()))
|
||||
setPositiveButton(android.R.string.ok, null)
|
||||
show()
|
||||
}
|
||||
setNegativeButton(R.string.RegistrationActivity_cancel, null)
|
||||
show()
|
||||
}
|
||||
|
||||
is VerificationCodeRequestResult.InvalidTransportModeFailure -> {
|
||||
MaterialAlertDialogBuilder(requireContext()).apply {
|
||||
setMessage(R.string.RegistrationActivity_we_couldnt_send_you_a_verification_code)
|
||||
setPositiveButton(R.string.RegistrationActivity_voice_call) { _, _ ->
|
||||
sharedViewModel.requestVerificationCall(requireContext(), ::handleErrorResponse)
|
||||
}
|
||||
setNegativeButton(R.string.RegistrationActivity_cancel, null)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
is RegistrationSessionCreationResult.MalformedRequest,
|
||||
is VerificationCodeRequestResult.MalformedRequest -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service), skipToNextScreen)
|
||||
|
||||
is VerificationCodeRequestResult.MustRetry -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service), skipToNextScreen)
|
||||
is VerificationCodeRequestResult.NonNormalizedNumber -> handleNonNormalizedNumberError(result.originalNumber, result.normalizedNumber, fragmentViewModel.mode)
|
||||
is RegistrationSessionCreationResult.RateLimited -> {
|
||||
Log.i(TAG, "Session creation rate limited! Next attempt: ${result.timeRemaining.milliseconds}")
|
||||
presentRemoteErrorDialog(getString(R.string.RegistrationActivity_rate_limited_to_try_again, result.timeRemaining.milliseconds.toString()))
|
||||
}
|
||||
|
||||
is VerificationCodeRequestResult.RateLimited -> {
|
||||
Log.i(TAG, "Code request rate limited! Next attempt: ${result.timeRemaining.milliseconds}")
|
||||
presentRemoteErrorDialog(getString(R.string.RegistrationActivity_rate_limited_to_try_again, result.timeRemaining.milliseconds.toString()))
|
||||
}
|
||||
|
||||
is VerificationCodeRequestResult.TokenNotAccepted -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_we_need_to_verify_that_youre_human)) { _, _ -> moveToCaptcha() }
|
||||
else -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service))
|
||||
}
|
||||
is RegistrationSessionCreationResult.MalformedRequest,
|
||||
is VerificationCodeRequestResult.MalformedRequest -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service), skipToNextScreen)
|
||||
is VerificationCodeRequestResult.MustRetry -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service), skipToNextScreen)
|
||||
is VerificationCodeRequestResult.NonNormalizedNumber -> handleNonNormalizedNumberError(result.originalNumber, result.normalizedNumber, fragmentViewModel.mode)
|
||||
is RegistrationSessionCreationResult.RateLimited -> {
|
||||
Log.i(TAG, "Session creation rate limited! Next attempt: ${result.timeRemaining.milliseconds}")
|
||||
presentRemoteErrorDialog(getString(R.string.RegistrationActivity_rate_limited_to_try_again, result.timeRemaining.milliseconds.toString()))
|
||||
}
|
||||
is VerificationCodeRequestResult.RateLimited -> {
|
||||
Log.i(TAG, "Code request rate limited! Next attempt: ${result.timeRemaining.milliseconds}")
|
||||
presentRemoteErrorDialog(getString(R.string.RegistrationActivity_rate_limited_to_try_again, result.timeRemaining.milliseconds.toString()))
|
||||
}
|
||||
is VerificationCodeRequestResult.TokenNotAccepted -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_we_need_to_verify_that_youre_human)) { _, _ -> moveToCaptcha() }
|
||||
else -> presentRemoteErrorDialog(getString(R.string.RegistrationActivity_unable_to_connect_to_service))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ class WelcomeFragment : LoggingFragment(R.layout.fragment_registration_welcome)
|
||||
}
|
||||
Activity.RESULT_CANCELED -> {
|
||||
Log.w(TAG, "Backup restoration canceled.")
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
else -> Log.w(TAG, "Backup restoration activity ended with unknown result code: $resultCode")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user