diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d40afea..309334c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,8 +12,8 @@ android { applicationId = "pl.firmatpp.kierowca" minSdk = 26 targetSdk = 35 - versionCode = 11 - versionName = "1.0.10" + versionCode = 12 + versionName = "1.0.11" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "API_BASE_URL", "\"https://api-intranet.firmatpp.pl/api/\"") @@ -45,6 +45,10 @@ android { compose = true buildConfig = true } + + lint { + disable += "NullSafeMutableLiveData" + } } dependencies { diff --git a/app/src/main/java/pl/firmatpp/kierowca/ui/DriverViewModel.kt b/app/src/main/java/pl/firmatpp/kierowca/ui/DriverViewModel.kt index db3d72b..a97d21e 100644 --- a/app/src/main/java/pl/firmatpp/kierowca/ui/DriverViewModel.kt +++ b/app/src/main/java/pl/firmatpp/kierowca/ui/DriverViewModel.kt @@ -40,6 +40,7 @@ data class DriverUiState( class DriverViewModel(application: Application) : AndroidViewModel(application) { private val repository = DriverRepository(application) private val _state = MutableStateFlow(DriverUiState(loading = true)) + private val otpAutoSubmitPolicy = OtpAutoSubmitPolicy() val state: StateFlow = _state init { @@ -50,6 +51,7 @@ class DriverViewModel(application: Application) : AndroidViewModel(application) fun requestOtp(phone: String) = runLoading { val response = repository.requestOtp(phone) + otpAutoSubmitPolicy.reset() _state.update { it.copy( screen = DriverScreen.Otp, @@ -68,7 +70,12 @@ class DriverViewModel(application: Application) : AndroidViewModel(application) } fun updateOtpCode(code: String) { - _state.update { it.copy(otpCode = code.filter(Char::isDigit).take(10)) } + val sanitized = code.filter(Char::isDigit).take(6) + _state.update { it.copy(otpCode = sanitized) } + + if (otpAutoSubmitPolicy.shouldSubmit(sanitized, _state.value.loading)) { + verifyOtp(sanitized) + } } fun refreshRoutes() = loadRoutes(date = _state.value.selectedDate, showLoading = true, navigateToRoutes = true) diff --git a/app/src/main/java/pl/firmatpp/kierowca/ui/OtpAutoSubmitPolicy.kt b/app/src/main/java/pl/firmatpp/kierowca/ui/OtpAutoSubmitPolicy.kt new file mode 100644 index 0000000..4aaf09e --- /dev/null +++ b/app/src/main/java/pl/firmatpp/kierowca/ui/OtpAutoSubmitPolicy.kt @@ -0,0 +1,27 @@ +package pl.firmatpp.kierowca.ui + +class OtpAutoSubmitPolicy { + private var lastSubmittedCode: String? = null + + fun shouldSubmit(code: String, loading: Boolean): Boolean { + if (code.length < OTP_LENGTH) { + lastSubmittedCode = null + return false + } + + if (loading || code.length != OTP_LENGTH || code == lastSubmittedCode) { + return false + } + + lastSubmittedCode = code + return true + } + + fun reset() { + lastSubmittedCode = null + } + + private companion object { + const val OTP_LENGTH = 6 + } +} diff --git a/app/src/test/java/pl/firmatpp/kierowca/ui/OtpAutoSubmitPolicyTest.kt b/app/src/test/java/pl/firmatpp/kierowca/ui/OtpAutoSubmitPolicyTest.kt new file mode 100644 index 0000000..2e464de --- /dev/null +++ b/app/src/test/java/pl/firmatpp/kierowca/ui/OtpAutoSubmitPolicyTest.kt @@ -0,0 +1,41 @@ +package pl.firmatpp.kierowca.ui + +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +class OtpAutoSubmitPolicyTest { + @Test + fun submitsWhenSixthDigitIsEntered() { + val policy = OtpAutoSubmitPolicy() + + assertFalse(policy.shouldSubmit("12345", loading = false)) + assertTrue(policy.shouldSubmit("123456", loading = false)) + } + + @Test + fun submitsSmsRetrieverCodeOnlyOnceWhileItStaysTheSame() { + val policy = OtpAutoSubmitPolicy() + + assertTrue(policy.shouldSubmit("987654", loading = false)) + assertFalse(policy.shouldSubmit("987654", loading = false)) + } + + @Test + fun allowsRetryAfterCodeIsEditedBelowSixDigits() { + val policy = OtpAutoSubmitPolicy() + + assertTrue(policy.shouldSubmit("111111", loading = false)) + assertFalse(policy.shouldSubmit("111111", loading = false)) + assertFalse(policy.shouldSubmit("11111", loading = false)) + assertTrue(policy.shouldSubmit("111111", loading = false)) + } + + @Test + fun doesNotSubmitWhileLoadingOrForLongerCodes() { + val policy = OtpAutoSubmitPolicy() + + assertFalse(policy.shouldSubmit("123456", loading = true)) + assertFalse(policy.shouldSubmit("1234567", loading = false)) + } +}