summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2024-03-11 13:26:33 +0100
committerDavid Göransson <david.goransson@mullvad.net>2024-03-11 15:56:57 +0100
commitc6b1744b673644eaec26c93da9beadec4344a575 (patch)
tree92c296ac643d3e5061434138279bfa1ddd208c31 /android/app/src
parent5560072b52fd1fc883ce3864328c5751ac778528 (diff)
downloadmullvadvpn-c6b1744b673644eaec26c93da9beadec4344a575.tar.xz
mullvadvpn-c6b1744b673644eaec26c93da9beadec4344a575.zip
Revert navigation logic on Welcome to handle bad clocks better
Diffstat (limited to 'android/app/src')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt23
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt26
3 files changed, 22 insertions, 29 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
index 942ad8aa39..f36e579a52 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
@@ -154,7 +154,7 @@ val uiModule = module {
viewModel { SplashViewModel(get(), get(), get()) }
viewModel { VoucherDialogViewModel(get(), get()) }
viewModel { VpnSettingsViewModel(get(), get(), get(), get(), get()) }
- viewModel { WelcomeViewModel(get(), get(), get(), get(), get(), isPlayBuild = IS_PLAY_BUILD) }
+ viewModel { WelcomeViewModel(get(), get(), get(), get(), isPlayBuild = IS_PLAY_BUILD) }
viewModel { ReportProblemViewModel(get(), get()) }
viewModel { ViewLogsViewModel(get()) }
viewModel { OutOfTimeViewModel(get(), get(), get(), get(), get(), isPlayBuild = IS_PLAY_BUILD) }
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt
index 66b41a17c7..0f6b23a306 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt
@@ -14,7 +14,9 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -27,7 +29,6 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ConnectionProxy
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache
-import net.mullvad.mullvadvpn.usecase.OutOfTimeUseCase
import net.mullvad.mullvadvpn.usecase.PaymentUseCase
import net.mullvad.mullvadvpn.util.UNKNOWN_STATE_DEBOUNCE_DELAY_MILLISECONDS
import net.mullvad.mullvadvpn.util.addDebounceForUnknownState
@@ -40,12 +41,11 @@ class WelcomeViewModel(
private val deviceRepository: DeviceRepository,
private val serviceConnectionManager: ServiceConnectionManager,
private val paymentUseCase: PaymentUseCase,
- private val outOfTimeUseCase: OutOfTimeUseCase,
private val pollAccountExpiry: Boolean = true,
private val isPlayBuild: Boolean
) : ViewModel() {
private val _uiSideEffect = Channel<UiSideEffect>()
- val uiSideEffect = merge(_uiSideEffect.receiveAsFlow(), notOutOfTimeEffect())
+ val uiSideEffect = merge(_uiSideEffect.receiveAsFlow(), hasAddedTimeEffect())
val uiState =
serviceConnectionManager.connectionState
@@ -86,13 +86,12 @@ class WelcomeViewModel(
fetchPaymentAvailability()
}
- private fun notOutOfTimeEffect() =
- outOfTimeUseCase.isOutOfTime
- .filter { it == false }
- .map {
- paymentUseCase.resetPurchaseResult()
- UiSideEffect.OpenConnectScreen
- }
+ private fun hasAddedTimeEffect() =
+ accountRepository.accountExpiryState
+ .mapNotNull { it.date() }
+ .filter { it.minusHours(MIN_HOURS_PAST_ACCOUNT_EXPIRY).isAfterNow }
+ .onEach { paymentUseCase.resetPurchaseResult() }
+ .map { UiSideEffect.OpenConnectScreen }
private fun ConnectionProxy.tunnelUiStateFlow(): Flow<TunnelState> =
callbackFlowFromNotifier(this.onUiStateChange)
@@ -144,4 +143,8 @@ class WelcomeViewModel(
data object OpenConnectScreen : UiSideEffect
}
+
+ companion object {
+ private const val MIN_HOURS_PAST_ACCOUNT_EXPIRY = 20
+ }
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
index c52dd3a103..91554193bc 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
@@ -32,11 +32,9 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache
-import net.mullvad.mullvadvpn.usecase.OutOfTimeUseCase
import net.mullvad.mullvadvpn.usecase.PaymentUseCase
import net.mullvad.talpid.util.EventNotifier
import org.joda.time.DateTime
-import org.joda.time.ReadableInstant
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -51,7 +49,6 @@ class WelcomeViewModelTest {
private val accountExpiryStateFlow = MutableStateFlow<AccountExpiry>(AccountExpiry.Missing)
private val purchaseResultFlow = MutableStateFlow<PurchaseResult?>(null)
private val paymentAvailabilityFlow = MutableStateFlow<PaymentAvailability?>(null)
- private val outOfTimeFlow = MutableStateFlow(true)
// Service connections
private val mockServiceConnectionContainer: ServiceConnectionContainer = mockk()
@@ -64,7 +61,6 @@ class WelcomeViewModelTest {
private val mockDeviceRepository: DeviceRepository = mockk()
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private val mockPaymentUseCase: PaymentUseCase = mockk(relaxed = true)
- private val mockOutOfTimeUseCase: OutOfTimeUseCase = mockk(relaxed = true)
private lateinit var viewModel: WelcomeViewModel
@@ -87,15 +83,12 @@ class WelcomeViewModelTest {
coEvery { mockPaymentUseCase.paymentAvailability } returns paymentAvailabilityFlow
- coEvery { mockOutOfTimeUseCase.isOutOfTime } returns outOfTimeFlow
-
viewModel =
WelcomeViewModel(
accountRepository = mockAccountRepository,
deviceRepository = mockDeviceRepository,
serviceConnectionManager = mockServiceConnectionManager,
paymentUseCase = mockPaymentUseCase,
- outOfTimeUseCase = mockOutOfTimeUseCase,
pollAccountExpiry = false,
isPlayBuild = false
)
@@ -164,19 +157,16 @@ class WelcomeViewModelTest {
}
@Test
- fun `when OutOfTimeUseCase return false uiSideEffect should emit OpenConnectScreen`() =
- runTest {
- // Arrange
- val mockExpiryDate: DateTime = mockk()
- every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true
+ fun `when user has added time then uiSideEffect should emit OpenConnectScreen`() = runTest {
+ // Arrange
+ accountExpiryStateFlow.emit(AccountExpiry.Available(DateTime().plusDays(1)))
- // Act, Assert
- viewModel.uiSideEffect.test {
- outOfTimeFlow.value = false
- val action = awaitItem()
- assertIs<WelcomeViewModel.UiSideEffect.OpenConnectScreen>(action)
- }
+ // Act, Assert
+ viewModel.uiSideEffect.test {
+ val action = awaitItem()
+ assertIs<WelcomeViewModel.UiSideEffect.OpenConnectScreen>(action)
}
+ }
@Test
fun `when paymentAvailability emits ProductsUnavailable uiState should include state NoPayment`() =