Fix progress display hiding way before registration navigation.
Fixes #13850 Closes #13898 Co-authored-by: Sagar <sagar.0dev@gmail.com>
This commit is contained in:
parent
93604f53d4
commit
e9d80f4379
13 changed files with 78 additions and 127 deletions
|
@ -81,7 +81,6 @@ internal class ConfirmSvrPinFragment : BaseSvrPinFragment<ConfirmSvrPinViewModel
|
||||||
SaveAnimation.NONE -> confirm.cancelSpinning()
|
SaveAnimation.NONE -> confirm.cancelSpinning()
|
||||||
SaveAnimation.LOADING -> confirm.setSpinning()
|
SaveAnimation.LOADING -> confirm.setSpinning()
|
||||||
SaveAnimation.SUCCESS -> {
|
SaveAnimation.SUCCESS -> {
|
||||||
confirm.cancelSpinning()
|
|
||||||
requireActivity().setResult(Activity.RESULT_OK)
|
requireActivity().setResult(Activity.RESULT_OK)
|
||||||
closeNavGraphBranch()
|
closeNavGraphBranch()
|
||||||
RegistrationUtil.maybeMarkRegistrationComplete()
|
RegistrationUtil.maybeMarkRegistrationComplete()
|
||||||
|
|
|
@ -83,7 +83,6 @@ class RegistrationActivity : BaseActivity() {
|
||||||
if (!needsProfile && !needsPin) {
|
if (!needsProfile && !needsPin) {
|
||||||
sharedViewModel.completeRegistration()
|
sharedViewModel.completeRegistration()
|
||||||
}
|
}
|
||||||
sharedViewModel.setInProgress(false)
|
|
||||||
|
|
||||||
val startIntent = MainActivity.clearTop(this).apply {
|
val startIntent = MainActivity.clearTop(this).apply {
|
||||||
if (needsPin) {
|
if (needsPin) {
|
||||||
|
|
|
@ -86,13 +86,8 @@ class RegistrationViewModel : ViewModel() {
|
||||||
private val password = Util.getSecret(18)
|
private val password = Util.getSecret(18)
|
||||||
|
|
||||||
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
|
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||||
Log.w(TAG, "CoroutineExceptionHandler invoked.", exception)
|
Log.w(TAG, "CoroutineExceptionHandler invoked!")
|
||||||
store.update {
|
handleGenericError(exception)
|
||||||
it.copy(
|
|
||||||
networkError = exception,
|
|
||||||
inProgress = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val uiState = store.asLiveData()
|
val uiState = store.asLiveData()
|
||||||
|
@ -238,8 +233,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
canSkipSms = true,
|
canSkipSms = true,
|
||||||
isReRegister = true,
|
isReRegister = true
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -263,8 +257,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
isReRegister = true,
|
isReRegister = true,
|
||||||
canSkipSms = true,
|
canSkipSms = true,
|
||||||
svr2AuthCredentials = svrCredentialsResult.svr2Credentials,
|
svr2AuthCredentials = svrCredentialsResult.svr2Credentials,
|
||||||
svr3AuthCredentials = svrCredentialsResult.svr3Credentials,
|
svr3AuthCredentials = svrCredentialsResult.svr3Credentials
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return@launch
|
return@launch
|
||||||
|
@ -315,7 +308,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
if (e164 == null) {
|
if (e164 == null) {
|
||||||
Log.w(TAG, "Phone number was null after confirmation.")
|
Log.w(TAG, "Phone number was null after confirmation.")
|
||||||
onErrorOccurred()
|
setInProgress(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,8 +397,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
nextVerificationAttempt = RegistrationRepository.deriveTimestamp(networkResult.headers, networkResult.body.nextVerificationAttempt),
|
nextVerificationAttempt = RegistrationRepository.deriveTimestamp(networkResult.headers, networkResult.body.nextVerificationAttempt),
|
||||||
allowedToRequestCode = networkResult.body.allowedToRequestCode,
|
allowedToRequestCode = networkResult.body.allowedToRequestCode,
|
||||||
challengesRequested = Challenge.parse(networkResult.body.requestedInformation),
|
challengesRequested = Challenge.parse(networkResult.body.requestedInformation),
|
||||||
verified = networkResult.body.verified,
|
verified = networkResult.body.verified
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -451,12 +443,6 @@ class RegistrationViewModel : ViewModel() {
|
||||||
val session = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Could not create valid session for submitting a push challenge token.") }
|
val session = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Could not create valid session for submitting a push challenge token.") }
|
||||||
|
|
||||||
if (!Challenge.parse(session.body.requestedInformation).contains(Challenge.PUSH)) {
|
if (!Challenge.parse(session.body.requestedInformation).contains(Challenge.PUSH)) {
|
||||||
Log.d(TAG, "Push submission no longer necessary, bailing.")
|
|
||||||
store.update {
|
|
||||||
it.copy(
|
|
||||||
inProgress = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return@launch bail { Log.i(TAG, "Push challenge token no longer needed, bailing.") }
|
return@launch bail { Log.i(TAG, "Push challenge token no longer needed, bailing.") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,8 +472,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
nextSmsTimestamp = sessionResult.nextSmsTimestamp,
|
nextSmsTimestamp = sessionResult.nextSmsTimestamp,
|
||||||
nextCallTimestamp = sessionResult.nextCallTimestamp,
|
nextCallTimestamp = sessionResult.nextCallTimestamp,
|
||||||
isAllowedToRequestCode = sessionResult.allowedToRequestCode,
|
isAllowedToRequestCode = sessionResult.allowedToRequestCode,
|
||||||
challengesRequested = emptyList(),
|
challengesRequested = emptyList()
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -498,8 +483,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
registrationCheckpoint = RegistrationCheckpoint.CHALLENGE_RECEIVED,
|
registrationCheckpoint = RegistrationCheckpoint.CHALLENGE_RECEIVED,
|
||||||
challengesRequested = sessionResult.challenges,
|
challengesRequested = sessionResult.challenges
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -534,9 +518,10 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
is AlreadyVerified -> Log.i(TAG, "Received AlreadyVerified", sessionResult.getCause())
|
is AlreadyVerified -> Log.i(TAG, "Received AlreadyVerified", sessionResult.getCause())
|
||||||
}
|
}
|
||||||
setInProgress(false)
|
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
inProgress = false,
|
||||||
sessionStateError = sessionResult
|
sessionStateError = sessionResult
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -548,6 +533,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
*/
|
*/
|
||||||
private suspend fun handleRegistrationResult(context: Context, registrationData: RegistrationData, registrationResult: RegisterAccountResult, reglockEnabled: Boolean): Boolean {
|
private suspend fun handleRegistrationResult(context: Context, registrationData: RegistrationData, registrationResult: RegisterAccountResult, reglockEnabled: Boolean): Boolean {
|
||||||
Log.v(TAG, "handleRegistrationResult()")
|
Log.v(TAG, "handleRegistrationResult()")
|
||||||
|
var stayInProgress = false
|
||||||
when (registrationResult) {
|
when (registrationResult) {
|
||||||
is RegisterAccountResult.Success -> {
|
is RegisterAccountResult.Success -> {
|
||||||
Log.i(TAG, "Register account result: Success! Registration lock: $reglockEnabled")
|
Log.i(TAG, "Register account result: Success! Registration lock: $reglockEnabled")
|
||||||
|
@ -567,6 +553,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
is RegisterAccountResult.RegistrationLocked -> {
|
is RegisterAccountResult.RegistrationLocked -> {
|
||||||
Log.i(TAG, "Account is registration locked!", registrationResult.getCause())
|
Log.i(TAG, "Account is registration locked!", registrationResult.getCause())
|
||||||
|
stayInProgress = true
|
||||||
}
|
}
|
||||||
|
|
||||||
is RegisterAccountResult.SvrWrongPin -> {
|
is RegisterAccountResult.SvrWrongPin -> {
|
||||||
|
@ -582,9 +569,9 @@ class RegistrationViewModel : ViewModel() {
|
||||||
is RegisterAccountResult.ValidationError,
|
is RegisterAccountResult.ValidationError,
|
||||||
is RegisterAccountResult.UnknownError -> Log.i(TAG, "Received error when trying to register!", registrationResult.getCause())
|
is RegisterAccountResult.UnknownError -> Log.i(TAG, "Received error when trying to register!", registrationResult.getCause())
|
||||||
}
|
}
|
||||||
setInProgress(false)
|
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
inProgress = stayInProgress,
|
||||||
registerAccountError = registrationResult
|
registerAccountError = registrationResult
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -636,7 +623,6 @@ class RegistrationViewModel : ViewModel() {
|
||||||
updateSvrTriesRemaining(0)
|
updateSvrTriesRemaining(0)
|
||||||
setUserSkippedReRegisterFlow(true)
|
setUserSkippedReRegisterFlow(true)
|
||||||
}
|
}
|
||||||
setInProgress(false)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -647,19 +633,17 @@ class RegistrationViewModel : ViewModel() {
|
||||||
Log.d(TAG, "Found recovery password, attempting to re-register.")
|
Log.d(TAG, "Found recovery password, attempting to re-register.")
|
||||||
viewModelScope.launch(context = coroutineExceptionHandler) {
|
viewModelScope.launch(context = coroutineExceptionHandler) {
|
||||||
verifyReRegisterInternal(context, pin, SignalStore.svr.masterKey)
|
verifyReRegisterInternal(context, pin, SignalStore.svr.masterKey)
|
||||||
setInProgress(false)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Entered PIN did not match local PIN hash.")
|
Log.d(TAG, "Entered PIN did not match local PIN hash.")
|
||||||
wrongPinHandler()
|
wrongPinHandler()
|
||||||
setInProgress(false)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.w(TAG, "Could not get credentials to skip SMS registration, aborting!")
|
Log.w(TAG, "Could not get credentials to skip SMS registration, aborting!")
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(canSkipSms = false, inProgress = false)
|
it.copy(canSkipSms = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,8 +841,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
registrationCheckpoint = RegistrationCheckpoint.LOCAL_REGISTRATION_COMPLETE,
|
registrationCheckpoint = RegistrationCheckpoint.LOCAL_REGISTRATION_COMPLETE
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -898,14 +881,6 @@ class RegistrationViewModel : ViewModel() {
|
||||||
return RegistrationData(code, e164, password, RegistrationRepository.getRegistrationId(), RegistrationRepository.getProfileKey(e164), currentState.fcmToken, RegistrationRepository.getPniRegistrationId(), recoveryPassword)
|
return RegistrationData(code, e164, password, RegistrationRepository.getRegistrationId(), RegistrationRepository.getProfileKey(e164), currentState.fcmToken, RegistrationRepository.getPniRegistrationId(), recoveryPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a generic error UI handler that re-enables the UI so that the user can recover from errors.
|
|
||||||
* Do not forget to log any errors when calling this method!
|
|
||||||
*/
|
|
||||||
private fun onErrorOccurred() {
|
|
||||||
setInProgress(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for early returns in order to end the in-progress visual state, as well as print a log message explaining what happened.
|
* Used for early returns in order to end the in-progress visual state, as well as print a log message explaining what happened.
|
||||||
*
|
*
|
||||||
|
|
|
@ -198,6 +198,7 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||||
object : AssertedSuccessListener<Boolean>() {
|
object : AssertedSuccessListener<Boolean>() {
|
||||||
override fun onSuccess(result: Boolean?) {
|
override fun onSuccess(result: Boolean?) {
|
||||||
findNavController().safeNavigate(EnterCodeFragmentDirections.actionRequireKbsLockPin(timeRemaining))
|
findNavController().safeNavigate(EnterCodeFragmentDirections.actionRequireKbsLockPin(timeRemaining))
|
||||||
|
sharedViewModel.setInProgress(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -265,6 +266,7 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||||
private fun popBackStack() {
|
private fun popBackStack() {
|
||||||
sharedViewModel.setRegistrationCheckpoint(RegistrationCheckpoint.PUSH_NETWORK_AUDITED)
|
sharedViewModel.setRegistrationCheckpoint(RegistrationCheckpoint.PUSH_NETWORK_AUDITED)
|
||||||
NavHostFragment.findNavController(this).popBackStack()
|
NavHostFragment.findNavController(this).popBackStack()
|
||||||
|
sharedViewModel.setInProgress(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
|
|
@ -35,6 +35,7 @@ import com.google.android.material.textfield.TextInputEditText
|
||||||
import com.google.i18n.phonenumbers.NumberParseException
|
import com.google.i18n.phonenumbers.NumberParseException
|
||||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||||
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber
|
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber
|
||||||
|
import org.signal.core.util.ThreadUtil
|
||||||
import org.signal.core.util.isNotNullOrBlank
|
import org.signal.core.util.isNotNullOrBlank
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.LoggingFragment
|
import org.thoughtcrime.securesms.LoggingFragment
|
||||||
|
@ -114,7 +115,7 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
|
|
||||||
sharedViewModel.uiState.observe(viewLifecycleOwner) { sharedState ->
|
sharedViewModel.uiState.observe(viewLifecycleOwner) { sharedState ->
|
||||||
presentRegisterButton(sharedState)
|
presentRegisterButton(sharedState)
|
||||||
presentProgressBar(sharedState.inProgress, sharedState.isReRegister)
|
updateEnabledControls(sharedState.inProgress, sharedState.isReRegister)
|
||||||
|
|
||||||
sharedState.networkError?.let {
|
sharedState.networkError?.let {
|
||||||
presentNetworkError(it)
|
presentNetworkError(it)
|
||||||
|
@ -400,6 +401,7 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
|
|
||||||
private fun presentRegistrationLocked(timeRemaining: Long) {
|
private fun presentRegistrationLocked(timeRemaining: Long) {
|
||||||
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberRegistrationLock(timeRemaining))
|
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberRegistrationLock(timeRemaining))
|
||||||
|
sharedViewModel.setInProgress(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentRateLimitedDialog() {
|
private fun presentRateLimitedDialog() {
|
||||||
|
@ -408,10 +410,12 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
|
|
||||||
private fun presentAccountLocked() {
|
private fun presentAccountLocked() {
|
||||||
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberAccountLocked())
|
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberAccountLocked())
|
||||||
|
ThreadUtil.postToMain { sharedViewModel.setInProgress(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveToCaptcha() {
|
private fun moveToCaptcha() {
|
||||||
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionRequestCaptcha())
|
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionRequestCaptcha())
|
||||||
|
ThreadUtil.postToMain { sharedViewModel.setInProgress(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentRemoteErrorDialog(message: String, positiveButtonListener: DialogInterface.OnClickListener? = null) {
|
private fun presentRemoteErrorDialog(message: String, positiveButtonListener: DialogInterface.OnClickListener? = null) {
|
||||||
|
@ -491,12 +495,7 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentProgressBar(showProgress: Boolean, isReRegister: Boolean) {
|
private fun updateEnabledControls(showProgress: Boolean, isReRegister: Boolean) {
|
||||||
if (showProgress) {
|
|
||||||
binding.registerButton.setSpinning()
|
|
||||||
} else {
|
|
||||||
binding.registerButton.cancelSpinning()
|
|
||||||
}
|
|
||||||
binding.countryCode.isEnabled = !showProgress
|
binding.countryCode.isEnabled = !showProgress
|
||||||
binding.number.isEnabled = !showProgress
|
binding.number.isEnabled = !showProgress
|
||||||
binding.cancelButton.visible = !showProgress && isReRegister
|
binding.cancelButton.visible = !showProgress && isReRegister
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.registration.ui.RegistrationViewModel
|
||||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||||
import org.thoughtcrime.securesms.util.SupportEmailUtil
|
import org.thoughtcrime.securesms.util.SupportEmailUtil
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil
|
import org.thoughtcrime.securesms.util.ViewUtil
|
||||||
|
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||||
|
|
||||||
class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration_pin_restore_entry_v2) {
|
class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration_pin_restore_entry_v2) {
|
||||||
|
@ -76,21 +77,24 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
|
||||||
|
|
||||||
binding.pinRestoreKeyboardToggle.setIconResource(getPinEntryKeyboardType().other.iconResource)
|
binding.pinRestoreKeyboardToggle.setIconResource(getPinEntryKeyboardType().other.iconResource)
|
||||||
|
|
||||||
registrationViewModel.uiState.observe(viewLifecycleOwner, ::updateViewState)
|
LiveDataUtil
|
||||||
|
.combineLatest(registrationViewModel.uiState, reRegisterViewModel.uiState) { reg, rereg -> reg to rereg }
|
||||||
|
.observe(viewLifecycleOwner) { (registrationState, reRegisterState) -> updateViewState(registrationState, reRegisterState) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateViewState(state: RegistrationState) {
|
private fun updateViewState(state: RegistrationState, reRegisterState: ReRegisterWithPinState) {
|
||||||
if (state.networkError != null) {
|
if (state.networkError != null) {
|
||||||
genericErrorDialog()
|
genericErrorDialog()
|
||||||
registrationViewModel.networkErrorShown()
|
registrationViewModel.networkErrorShown()
|
||||||
} else if (!state.canSkipSms) {
|
} else if (!state.canSkipSms) {
|
||||||
findNavController().safeNavigate(ReRegisterWithPinFragmentDirections.actionReRegisterWithPinFragmentToEnterPhoneNumberFragment())
|
findNavController().safeNavigate(ReRegisterWithPinFragmentDirections.actionReRegisterWithPinFragmentToEnterPhoneNumberFragment())
|
||||||
|
registrationViewModel.setInProgress(false)
|
||||||
} else if (state.isRegistrationLockEnabled && state.svrTriesRemaining == 0) {
|
} else if (state.isRegistrationLockEnabled && state.svrTriesRemaining == 0) {
|
||||||
Log.w(TAG, "Unable to continue skip flow, KBS is locked")
|
Log.w(TAG, "Unable to continue skip flow, KBS is locked")
|
||||||
onAccountLocked()
|
onAccountLocked()
|
||||||
} else {
|
} else {
|
||||||
presentProgress(state.inProgress)
|
presentProgress(state.inProgress)
|
||||||
presentTriesRemaining(state.svrTriesRemaining)
|
presentTriesRemaining(reRegisterState, state.svrTriesRemaining)
|
||||||
}
|
}
|
||||||
|
|
||||||
state.registerAccountError?.let { error ->
|
state.registerAccountError?.let { error ->
|
||||||
|
@ -131,14 +135,15 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
|
||||||
context = requireContext(),
|
context = requireContext(),
|
||||||
pin = pin,
|
pin = pin,
|
||||||
wrongPinHandler = {
|
wrongPinHandler = {
|
||||||
|
registrationViewModel.setInProgress(false)
|
||||||
reRegisterViewModel.markIncorrectGuess()
|
reRegisterViewModel.markIncorrectGuess()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentTriesRemaining(triesRemaining: Int) {
|
private fun presentTriesRemaining(reRegisterState: ReRegisterWithPinState, triesRemaining: Int) {
|
||||||
if (reRegisterViewModel.hasIncorrectGuess) {
|
if (reRegisterState.hasIncorrectGuess) {
|
||||||
if (triesRemaining == 1 && !reRegisterViewModel.isLocalVerification) {
|
if (triesRemaining == 1 && !reRegisterState.isLocalVerification) {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle(R.string.PinRestoreEntryFragment_incorrect_pin)
|
.setTitle(R.string.PinRestoreEntryFragment_incorrect_pin)
|
||||||
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
||||||
|
@ -155,7 +160,7 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
|
||||||
} else {
|
} else {
|
||||||
if (triesRemaining == 1) {
|
if (triesRemaining == 1) {
|
||||||
binding.pinRestoreForgotPin.visibility = View.VISIBLE
|
binding.pinRestoreForgotPin.visibility = View.VISIBLE
|
||||||
if (!reRegisterViewModel.isLocalVerification) {
|
if (!reRegisterState.isLocalVerification) {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
|
|
@ -6,21 +6,17 @@
|
||||||
package org.thoughtcrime.securesms.registration.ui.reregisterwithpin
|
package org.thoughtcrime.securesms.registration.ui.reregisterwithpin
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.asLiveData
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import org.signal.core.util.logging.Log
|
|
||||||
|
|
||||||
class ReRegisterWithPinViewModel : ViewModel() {
|
class ReRegisterWithPinViewModel : ViewModel() {
|
||||||
companion object {
|
|
||||||
private val TAG = Log.tag(ReRegisterWithPinViewModel::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val store = MutableStateFlow(ReRegisterWithPinState())
|
private val store = MutableStateFlow(ReRegisterWithPinState())
|
||||||
|
|
||||||
|
val uiState = store.asLiveData()
|
||||||
|
|
||||||
val isLocalVerification: Boolean
|
val isLocalVerification: Boolean
|
||||||
get() = store.value.isLocalVerification
|
get() = store.value.isLocalVerification
|
||||||
val hasIncorrectGuess: Boolean
|
|
||||||
get() = store.value.hasIncorrectGuess
|
|
||||||
|
|
||||||
fun markAsRemoteVerification() {
|
fun markAsRemoteVerification() {
|
||||||
store.update {
|
store.update {
|
||||||
|
|
|
@ -83,7 +83,6 @@ class RegistrationActivity : BaseActivity() {
|
||||||
if (!needsProfile && !needsPin) {
|
if (!needsProfile && !needsPin) {
|
||||||
sharedViewModel.completeRegistration()
|
sharedViewModel.completeRegistration()
|
||||||
}
|
}
|
||||||
sharedViewModel.setInProgress(false)
|
|
||||||
|
|
||||||
val startIntent = MainActivity.clearTop(this)
|
val startIntent = MainActivity.clearTop(this)
|
||||||
|
|
||||||
|
|
|
@ -90,13 +90,8 @@ class RegistrationViewModel : ViewModel() {
|
||||||
private val password = Util.getSecret(18)
|
private val password = Util.getSecret(18)
|
||||||
|
|
||||||
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
|
private val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
|
||||||
Log.w(TAG, "CoroutineExceptionHandler invoked.", exception)
|
Log.w(TAG, "CoroutineExceptionHandler invoked!")
|
||||||
store.update {
|
handleGenericError(exception)
|
||||||
it.copy(
|
|
||||||
networkError = exception,
|
|
||||||
inProgress = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val state: StateFlow<RegistrationState> = store
|
val state: StateFlow<RegistrationState> = store
|
||||||
|
@ -244,8 +239,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
canSkipSms = true,
|
canSkipSms = true,
|
||||||
isReRegister = true,
|
isReRegister = true
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -269,8 +263,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
isReRegister = true,
|
isReRegister = true,
|
||||||
canSkipSms = true,
|
canSkipSms = true,
|
||||||
svr2AuthCredentials = svrCredentialsResult.svr2Credentials,
|
svr2AuthCredentials = svrCredentialsResult.svr2Credentials,
|
||||||
svr3AuthCredentials = svrCredentialsResult.svr3Credentials,
|
svr3AuthCredentials = svrCredentialsResult.svr3Credentials
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return@launch
|
return@launch
|
||||||
|
@ -321,7 +314,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
if (e164 == null) {
|
if (e164 == null) {
|
||||||
Log.w(TAG, "Phone number was null after confirmation.")
|
Log.w(TAG, "Phone number was null after confirmation.")
|
||||||
onErrorOccurred()
|
setInProgress(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,8 +403,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
nextVerificationAttempt = RegistrationRepository.deriveTimestamp(networkResult.headers, networkResult.body.nextVerificationAttempt),
|
nextVerificationAttempt = RegistrationRepository.deriveTimestamp(networkResult.headers, networkResult.body.nextVerificationAttempt),
|
||||||
allowedToRequestCode = networkResult.body.allowedToRequestCode,
|
allowedToRequestCode = networkResult.body.allowedToRequestCode,
|
||||||
challengesRequested = Challenge.parse(networkResult.body.requestedInformation),
|
challengesRequested = Challenge.parse(networkResult.body.requestedInformation),
|
||||||
verified = networkResult.body.verified,
|
verified = networkResult.body.verified
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -457,12 +449,6 @@ class RegistrationViewModel : ViewModel() {
|
||||||
val session = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Could not create valid session for submitting a push challenge token.") }
|
val session = getOrCreateValidSession(context) ?: return@launch bail { Log.i(TAG, "Could not create valid session for submitting a push challenge token.") }
|
||||||
|
|
||||||
if (!Challenge.parse(session.body.requestedInformation).contains(Challenge.PUSH)) {
|
if (!Challenge.parse(session.body.requestedInformation).contains(Challenge.PUSH)) {
|
||||||
Log.d(TAG, "Push submission no longer necessary, bailing.")
|
|
||||||
store.update {
|
|
||||||
it.copy(
|
|
||||||
inProgress = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return@launch bail { Log.i(TAG, "Push challenge token no longer needed, bailing.") }
|
return@launch bail { Log.i(TAG, "Push challenge token no longer needed, bailing.") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,8 +478,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
nextSmsTimestamp = sessionResult.nextSmsTimestamp,
|
nextSmsTimestamp = sessionResult.nextSmsTimestamp,
|
||||||
nextCallTimestamp = sessionResult.nextCallTimestamp,
|
nextCallTimestamp = sessionResult.nextCallTimestamp,
|
||||||
isAllowedToRequestCode = sessionResult.allowedToRequestCode,
|
isAllowedToRequestCode = sessionResult.allowedToRequestCode,
|
||||||
challengesRequested = emptyList(),
|
challengesRequested = emptyList()
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -504,8 +489,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
registrationCheckpoint = RegistrationCheckpoint.CHALLENGE_RECEIVED,
|
registrationCheckpoint = RegistrationCheckpoint.CHALLENGE_RECEIVED,
|
||||||
challengesRequested = sessionResult.challenges,
|
challengesRequested = sessionResult.challenges
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -540,10 +524,11 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
is AlreadyVerified -> Log.i(TAG, "Received AlreadyVerified", sessionResult.getCause())
|
is AlreadyVerified -> Log.i(TAG, "Received AlreadyVerified", sessionResult.getCause())
|
||||||
}
|
}
|
||||||
setInProgress(false)
|
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
sessionStateError = sessionResult
|
sessionStateError = sessionResult,
|
||||||
|
inProgress = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -554,6 +539,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
*/
|
*/
|
||||||
private suspend fun handleRegistrationResult(context: Context, registrationData: RegistrationData, registrationResult: RegisterAccountResult, reglockEnabled: Boolean): Boolean {
|
private suspend fun handleRegistrationResult(context: Context, registrationData: RegistrationData, registrationResult: RegisterAccountResult, reglockEnabled: Boolean): Boolean {
|
||||||
Log.v(TAG, "handleRegistrationResult()")
|
Log.v(TAG, "handleRegistrationResult()")
|
||||||
|
var stayInProgress = false
|
||||||
when (registrationResult) {
|
when (registrationResult) {
|
||||||
is RegisterAccountResult.Success -> {
|
is RegisterAccountResult.Success -> {
|
||||||
Log.i(TAG, "Register account result: Success! Registration lock: $reglockEnabled")
|
Log.i(TAG, "Register account result: Success! Registration lock: $reglockEnabled")
|
||||||
|
@ -573,6 +559,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
is RegisterAccountResult.RegistrationLocked -> {
|
is RegisterAccountResult.RegistrationLocked -> {
|
||||||
Log.i(TAG, "Account is registration locked!", registrationResult.getCause())
|
Log.i(TAG, "Account is registration locked!", registrationResult.getCause())
|
||||||
|
stayInProgress = true
|
||||||
}
|
}
|
||||||
|
|
||||||
is RegisterAccountResult.SvrWrongPin -> {
|
is RegisterAccountResult.SvrWrongPin -> {
|
||||||
|
@ -588,10 +575,10 @@ class RegistrationViewModel : ViewModel() {
|
||||||
is RegisterAccountResult.ValidationError,
|
is RegisterAccountResult.ValidationError,
|
||||||
is RegisterAccountResult.UnknownError -> Log.i(TAG, "Received error when trying to register!", registrationResult.getCause())
|
is RegisterAccountResult.UnknownError -> Log.i(TAG, "Received error when trying to register!", registrationResult.getCause())
|
||||||
}
|
}
|
||||||
setInProgress(false)
|
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
registerAccountError = registrationResult
|
registerAccountError = registrationResult,
|
||||||
|
inProgress = stayInProgress
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -649,7 +636,6 @@ class RegistrationViewModel : ViewModel() {
|
||||||
updateSvrTriesRemaining(0)
|
updateSvrTriesRemaining(0)
|
||||||
setUserSkippedReRegisterFlow(true)
|
setUserSkippedReRegisterFlow(true)
|
||||||
}
|
}
|
||||||
setInProgress(false)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -662,19 +648,17 @@ class RegistrationViewModel : ViewModel() {
|
||||||
val masterKey = SignalStore.svr.masterKey
|
val masterKey = SignalStore.svr.masterKey
|
||||||
setRecoveryPassword(masterKey.deriveRegistrationRecoveryPassword())
|
setRecoveryPassword(masterKey.deriveRegistrationRecoveryPassword())
|
||||||
verifyReRegisterInternal(context, pin, masterKey)
|
verifyReRegisterInternal(context, pin, masterKey)
|
||||||
setInProgress(false)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Entered PIN did not match local PIN hash.")
|
Log.d(TAG, "Entered PIN did not match local PIN hash.")
|
||||||
wrongPinHandler()
|
wrongPinHandler()
|
||||||
setInProgress(false)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.w(TAG, "Could not get credentials to skip SMS registration, aborting!")
|
Log.w(TAG, "Could not get credentials to skip SMS registration, aborting!")
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(canSkipSms = false, inProgress = false)
|
it.copy(canSkipSms = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,8 +859,7 @@ class RegistrationViewModel : ViewModel() {
|
||||||
|
|
||||||
store.update {
|
store.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
registrationCheckpoint = RegistrationCheckpoint.LOCAL_REGISTRATION_COMPLETE,
|
registrationCheckpoint = RegistrationCheckpoint.LOCAL_REGISTRATION_COMPLETE
|
||||||
inProgress = false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -916,14 +899,6 @@ class RegistrationViewModel : ViewModel() {
|
||||||
return RegistrationData(code, e164, password, RegistrationRepository.getRegistrationId(), RegistrationRepository.getProfileKey(e164), currentState.fcmToken, RegistrationRepository.getPniRegistrationId(), recoveryPassword)
|
return RegistrationData(code, e164, password, RegistrationRepository.getRegistrationId(), RegistrationRepository.getProfileKey(e164), currentState.fcmToken, RegistrationRepository.getPniRegistrationId(), recoveryPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a generic error UI handler that re-enables the UI so that the user can recover from errors.
|
|
||||||
* Do not forget to log any errors when calling this method!
|
|
||||||
*/
|
|
||||||
private fun onErrorOccurred() {
|
|
||||||
setInProgress(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for early returns in order to end the in-progress visual state, as well as print a log message explaining what happened.
|
* Used for early returns in order to end the in-progress visual state, as well as print a log message explaining what happened.
|
||||||
*
|
*
|
||||||
|
|
|
@ -198,6 +198,7 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||||
object : AssertedSuccessListener<Boolean>() {
|
object : AssertedSuccessListener<Boolean>() {
|
||||||
override fun onSuccess(result: Boolean?) {
|
override fun onSuccess(result: Boolean?) {
|
||||||
findNavController().safeNavigate(EnterCodeFragmentDirections.actionRequireKbsLockPin(timeRemaining))
|
findNavController().safeNavigate(EnterCodeFragmentDirections.actionRequireKbsLockPin(timeRemaining))
|
||||||
|
sharedViewModel.setInProgress(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -265,6 +266,7 @@ class EnterCodeFragment : LoggingFragment(R.layout.fragment_registration_enter_c
|
||||||
private fun popBackStack() {
|
private fun popBackStack() {
|
||||||
sharedViewModel.setRegistrationCheckpoint(RegistrationCheckpoint.PUSH_NETWORK_AUDITED)
|
sharedViewModel.setRegistrationCheckpoint(RegistrationCheckpoint.PUSH_NETWORK_AUDITED)
|
||||||
NavHostFragment.findNavController(this).popBackStack()
|
NavHostFragment.findNavController(this).popBackStack()
|
||||||
|
sharedViewModel.setInProgress(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
|
|
@ -36,6 +36,7 @@ import com.google.android.material.textfield.TextInputEditText
|
||||||
import com.google.i18n.phonenumbers.NumberParseException
|
import com.google.i18n.phonenumbers.NumberParseException
|
||||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||||
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber
|
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber
|
||||||
|
import org.signal.core.util.ThreadUtil
|
||||||
import org.signal.core.util.isNotNullOrBlank
|
import org.signal.core.util.isNotNullOrBlank
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.LoggingFragment
|
import org.thoughtcrime.securesms.LoggingFragment
|
||||||
|
@ -119,7 +120,7 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
|
|
||||||
sharedViewModel.uiState.observe(viewLifecycleOwner) { sharedState ->
|
sharedViewModel.uiState.observe(viewLifecycleOwner) { sharedState ->
|
||||||
presentRegisterButton(sharedState)
|
presentRegisterButton(sharedState)
|
||||||
presentProgressBar(sharedState.inProgress, sharedState.isReRegister)
|
updateEnabledControls(sharedState.inProgress, sharedState.isReRegister)
|
||||||
|
|
||||||
sharedState.networkError?.let {
|
sharedState.networkError?.let {
|
||||||
presentNetworkError(it)
|
presentNetworkError(it)
|
||||||
|
@ -412,6 +413,7 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
|
|
||||||
private fun presentRegistrationLocked(timeRemaining: Long) {
|
private fun presentRegistrationLocked(timeRemaining: Long) {
|
||||||
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberRegistrationLock(timeRemaining))
|
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberRegistrationLock(timeRemaining))
|
||||||
|
sharedViewModel.setInProgress(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentRateLimitedDialog() {
|
private fun presentRateLimitedDialog() {
|
||||||
|
@ -420,10 +422,12 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
|
|
||||||
private fun presentAccountLocked() {
|
private fun presentAccountLocked() {
|
||||||
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberAccountLocked())
|
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionPhoneNumberAccountLocked())
|
||||||
|
ThreadUtil.postToMain { sharedViewModel.setInProgress(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun moveToCaptcha() {
|
private fun moveToCaptcha() {
|
||||||
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionRequestCaptcha())
|
findNavController().safeNavigate(EnterPhoneNumberFragmentDirections.actionRequestCaptcha())
|
||||||
|
ThreadUtil.postToMain { sharedViewModel.setInProgress(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentRemoteErrorDialog(message: String, positiveButtonListener: DialogInterface.OnClickListener? = null) {
|
private fun presentRemoteErrorDialog(message: String, positiveButtonListener: DialogInterface.OnClickListener? = null) {
|
||||||
|
@ -513,12 +517,7 @@ class EnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_registration_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentProgressBar(showProgress: Boolean, isReRegister: Boolean) {
|
private fun updateEnabledControls(showProgress: Boolean, isReRegister: Boolean) {
|
||||||
if (showProgress) {
|
|
||||||
binding.registerButton.setSpinning()
|
|
||||||
} else {
|
|
||||||
binding.registerButton.cancelSpinning()
|
|
||||||
}
|
|
||||||
binding.countryCode.isEnabled = !showProgress
|
binding.countryCode.isEnabled = !showProgress
|
||||||
binding.number.isEnabled = !showProgress
|
binding.number.isEnabled = !showProgress
|
||||||
binding.cancelButton.visible = !showProgress && isReRegister
|
binding.cancelButton.visible = !showProgress && isReRegister
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.registrationv3.ui.phonenumber.EnterPhoneNumber
|
||||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||||
import org.thoughtcrime.securesms.util.SupportEmailUtil
|
import org.thoughtcrime.securesms.util.SupportEmailUtil
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil
|
import org.thoughtcrime.securesms.util.ViewUtil
|
||||||
|
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||||
|
|
||||||
class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration_pin_restore_entry_v2) {
|
class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration_pin_restore_entry_v2) {
|
||||||
|
@ -77,21 +78,24 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
|
||||||
|
|
||||||
binding.pinRestoreKeyboardToggle.setIconResource(getPinEntryKeyboardType().other.iconResource)
|
binding.pinRestoreKeyboardToggle.setIconResource(getPinEntryKeyboardType().other.iconResource)
|
||||||
|
|
||||||
registrationViewModel.uiState.observe(viewLifecycleOwner, ::updateViewState)
|
LiveDataUtil
|
||||||
|
.combineLatest(registrationViewModel.uiState, reRegisterViewModel.uiState) { reg, rereg -> reg to rereg }
|
||||||
|
.observe(viewLifecycleOwner) { (registrationState, reRegisterState) -> updateViewState(registrationState, reRegisterState) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateViewState(state: RegistrationState) {
|
private fun updateViewState(state: RegistrationState, reRegisterState: ReRegisterWithPinState) {
|
||||||
if (state.networkError != null) {
|
if (state.networkError != null) {
|
||||||
genericErrorDialog()
|
genericErrorDialog()
|
||||||
registrationViewModel.networkErrorShown()
|
registrationViewModel.networkErrorShown()
|
||||||
} else if (!state.canSkipSms) {
|
} else if (!state.canSkipSms) {
|
||||||
findNavController().safeNavigate(ReRegisterWithPinFragmentDirections.actionReRegisterWithPinFragmentToEnterPhoneNumberFragment(EnterPhoneNumberMode.NORMAL))
|
findNavController().safeNavigate(ReRegisterWithPinFragmentDirections.actionReRegisterWithPinFragmentToEnterPhoneNumberFragment(EnterPhoneNumberMode.NORMAL))
|
||||||
|
registrationViewModel.setInProgress(false)
|
||||||
} else if (state.isRegistrationLockEnabled && state.svrTriesRemaining == 0) {
|
} else if (state.isRegistrationLockEnabled && state.svrTriesRemaining == 0) {
|
||||||
Log.w(TAG, "Unable to continue skip flow, KBS is locked")
|
Log.w(TAG, "Unable to continue skip flow, KBS is locked")
|
||||||
onAccountLocked()
|
onAccountLocked()
|
||||||
} else {
|
} else {
|
||||||
presentProgress(state.inProgress)
|
presentProgress(state.inProgress)
|
||||||
presentTriesRemaining(state.svrTriesRemaining)
|
presentTriesRemaining(reRegisterState, state.svrTriesRemaining)
|
||||||
}
|
}
|
||||||
|
|
||||||
state.registerAccountError?.let { error ->
|
state.registerAccountError?.let { error ->
|
||||||
|
@ -132,14 +136,15 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
|
||||||
context = requireContext(),
|
context = requireContext(),
|
||||||
pin = pin,
|
pin = pin,
|
||||||
wrongPinHandler = {
|
wrongPinHandler = {
|
||||||
|
registrationViewModel.setInProgress(false)
|
||||||
reRegisterViewModel.markIncorrectGuess()
|
reRegisterViewModel.markIncorrectGuess()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun presentTriesRemaining(triesRemaining: Int) {
|
private fun presentTriesRemaining(reRegisterState: ReRegisterWithPinState, triesRemaining: Int) {
|
||||||
if (reRegisterViewModel.hasIncorrectGuess) {
|
if (reRegisterState.hasIncorrectGuess) {
|
||||||
if (triesRemaining == 1 && !reRegisterViewModel.isLocalVerification) {
|
if (triesRemaining == 1 && !reRegisterState.isLocalVerification) {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle(R.string.PinRestoreEntryFragment_incorrect_pin)
|
.setTitle(R.string.PinRestoreEntryFragment_incorrect_pin)
|
||||||
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
||||||
|
@ -156,7 +161,7 @@ class ReRegisterWithPinFragment : LoggingFragment(R.layout.fragment_registration
|
||||||
} else {
|
} else {
|
||||||
if (triesRemaining == 1) {
|
if (triesRemaining == 1) {
|
||||||
binding.pinRestoreForgotPin.visibility = View.VISIBLE
|
binding.pinRestoreForgotPin.visibility = View.VISIBLE
|
||||||
if (!reRegisterViewModel.isLocalVerification) {
|
if (!reRegisterState.isLocalVerification) {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
.setMessage(resources.getQuantityString(R.plurals.PinRestoreEntryFragment_you_have_d_attempt_remaining, triesRemaining, triesRemaining))
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
|
|
@ -6,21 +6,17 @@
|
||||||
package org.thoughtcrime.securesms.registrationv3.ui.reregisterwithpin
|
package org.thoughtcrime.securesms.registrationv3.ui.reregisterwithpin
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.asLiveData
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import org.signal.core.util.logging.Log
|
|
||||||
|
|
||||||
class ReRegisterWithPinViewModel : ViewModel() {
|
class ReRegisterWithPinViewModel : ViewModel() {
|
||||||
companion object {
|
|
||||||
private val TAG = Log.tag(ReRegisterWithPinViewModel::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val store = MutableStateFlow(ReRegisterWithPinState())
|
private val store = MutableStateFlow(ReRegisterWithPinState())
|
||||||
|
|
||||||
|
val uiState = store.asLiveData()
|
||||||
|
|
||||||
val isLocalVerification: Boolean
|
val isLocalVerification: Boolean
|
||||||
get() = store.value.isLocalVerification
|
get() = store.value.isLocalVerification
|
||||||
val hasIncorrectGuess: Boolean
|
|
||||||
get() = store.value.hasIncorrectGuess
|
|
||||||
|
|
||||||
fun markAsRemoteVerification() {
|
fun markAsRemoteVerification() {
|
||||||
store.update {
|
store.update {
|
||||||
|
|
Loading…
Add table
Reference in a new issue