Allow for multiple captchas to be solved during registration.

This commit is contained in:
Cody Henthorne
2025-09-08 16:23:19 -04:00
committed by Greyson Parrelli
parent 23b5a3dcb0
commit bdf2ef5a05
19 changed files with 60 additions and 168 deletions

View File

@@ -5,10 +5,7 @@
package org.thoughtcrime.securesms.components.settings.app.changenumber
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import org.thoughtcrime.securesms.registration.data.network.Challenge
import org.thoughtcrime.securesms.registration.ui.captcha.CaptchaFragment
/**
@@ -16,16 +13,8 @@ import org.thoughtcrime.securesms.registration.ui.captcha.CaptchaFragment
*/
class ChangeNumberCaptchaFragment : CaptchaFragment() {
private val viewModel by activityViewModels<ChangeNumberViewModel>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.addPresentedChallenge(Challenge.CAPTCHA)
}
override fun handleCaptchaToken(token: String) {
viewModel.setCaptchaResponse(token)
}
override fun handleUserExit() {
viewModel.removePresentedChallenge(Challenge.CAPTCHA)
}
}

View File

@@ -35,10 +35,9 @@ data class ChangeNumberState(
val challengesPresented: Set<Challenge> = emptySet(),
val allowedToRequestCode: Boolean = false,
val oldCountry: Country? = null,
val newCountry: Country? = null
) {
val challengesRemaining: List<Challenge> = challengesRequested.filterNot { it in challengesPresented }
}
val newCountry: Country? = null,
val challengeInProgress: Boolean = false
)
sealed interface ChangeNumberOutcome {
data object RecoveryPasswordWorked : ChangeNumberOutcome

View File

@@ -54,8 +54,10 @@ class ChangeNumberVerifyFragment : LoggingFragment(R.layout.fragment_change_phon
private fun onStateUpdate(state: ChangeNumberState) {
if (state.challengesRequested.contains(Challenge.CAPTCHA) && state.captchaToken.isNotNullOrBlank()) {
viewModel.submitCaptchaToken(requireContext())
} else if (state.challengesRemaining.isNotEmpty()) {
handleChallenges(state.challengesRemaining)
} else if (state.challengesRequested.isNotEmpty()) {
if (!state.challengeInProgress) {
handleChallenges(state.challengesRequested)
}
} else if (state.changeNumberOutcome != null) {
handleRequestCodeResult(state.changeNumberOutcome)
} else if (!state.inProgress) {

View File

@@ -156,20 +156,6 @@ class ChangeNumberViewModel : ViewModel() {
}
}
fun addPresentedChallenge(challenge: Challenge) {
Log.v(TAG, "addPresentedChallenge()")
store.update {
it.copy(challengesPresented = it.challengesPresented.plus(challenge))
}
}
fun removePresentedChallenge(challenge: Challenge) {
Log.v(TAG, "addPresentedChallenge()")
store.update {
it.copy(challengesPresented = it.challengesPresented.minus(challenge))
}
}
fun resetLocalSessionState() {
Log.v(TAG, "resetLocalSessionState()")
store.update {
@@ -292,7 +278,8 @@ class ChangeNumberViewModel : ViewModel() {
it.copy(
captchaToken = null,
inProgress = true,
changeNumberOutcome = null
changeNumberOutcome = null,
challengeInProgress = true
)
}
@@ -304,7 +291,8 @@ class ChangeNumberViewModel : ViewModel() {
store.update {
it.copy(
inProgress = false,
changeNumberOutcome = null
changeNumberOutcome = null,
challengeInProgress = false
)
}
return@launch
@@ -313,7 +301,7 @@ class ChangeNumberViewModel : ViewModel() {
val captchaSubmissionResult = RegistrationRepository.submitCaptchaToken(context, e164, password, sessionData.sessionId, captchaToken)
Log.d(TAG, "Captcha token submitted.")
store.update {
it.copy(inProgress = false, changeNumberOutcome = ChangeNumberOutcome.ChangeNumberRequestOutcome(captchaSubmissionResult))
it.copy(inProgress = false, changeNumberOutcome = ChangeNumberOutcome.ChangeNumberRequestOutcome(captchaSubmissionResult), challengeInProgress = false)
}
}
}
@@ -321,8 +309,6 @@ class ChangeNumberViewModel : ViewModel() {
fun requestAndSubmitPushToken(context: Context) {
Log.v(TAG, "validatePushToken()")
addPresentedChallenge(Challenge.PUSH)
val e164 = number.e164Number
viewModelScope.launch {