Skip to content

Commit

Permalink
Prevent loading when logging out
Browse files Browse the repository at this point in the history
  • Loading branch information
Rawa committed Jun 11, 2024
1 parent f6e490f commit d7b2161
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.PaymentState
import net.mullvad.mullvadvpn.compose.test.PLAY_PAYMENT_INFO_ICON_TEST_TAG
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct
import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
Expand Down Expand Up @@ -290,6 +291,6 @@ class AccountScreenTest {

companion object {
private const val DUMMY_DEVICE_NAME = "fake_name"
private const val DUMMY_ACCOUNT_NUMBER = "fake_number"
private val DUMMY_ACCOUNT_NUMBER = AccountNumber("1234123412341234")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import net.mullvad.mullvadvpn.compose.transitions.SlideInFromBottomTransition
import net.mullvad.mullvadvpn.compose.util.LaunchedEffectCollect
import net.mullvad.mullvadvpn.compose.util.SecureScreenWhileInView
import net.mullvad.mullvadvpn.compose.util.createCopyToClipboardHandle
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct
import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
Expand All @@ -76,7 +77,7 @@ private fun PreviewAccountScreen() {
state =
AccountUiState(
deviceName = "Test Name",
accountNumber = "1234123412341234",
accountNumber = AccountNumber("1234123412341234"),
accountExpiry = null,
showSitePayment = true,
billingPaymentState =
Expand Down Expand Up @@ -201,7 +202,10 @@ fun AccountScreen(
onInfoClick = navigateToDeviceInfo
)

AccountNumberRow(accountNumber = state.accountNumber ?: "", onCopyAccountNumber)
AccountNumberRow(
accountNumber = state.accountNumber?.value ?: "",
onCopyAccountNumber
)

PaidUntilRow(accountExpiry = state.accountExpiry)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@ import android.app.Activity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.compose.state.PaymentState
import net.mullvad.mullvadvpn.lib.model.AccountData
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.DeviceState
import net.mullvad.mullvadvpn.lib.model.WebsiteAuthToken
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
import net.mullvad.mullvadvpn.lib.shared.AccountRepository
Expand All @@ -30,13 +38,13 @@ class AccountViewModel(

val uiState: StateFlow<AccountUiState> =
combine(
deviceRepository.deviceState,
accountRepository.accountData,
deviceRepository.deviceState.filterIsInstance<DeviceState.LoggedIn>(),
accountData(),
paymentUseCase.paymentAvailability
) { deviceState, accountData, paymentAvailability ->
AccountUiState(
deviceName = deviceState?.displayName() ?: "",
accountNumber = deviceState?.token()?.value ?: "",
deviceName = deviceState.device.displayName(),
accountNumber = deviceState.accountNumber,
accountExpiry = accountData?.expiryDate,
showSitePayment = !isPlayBuild,
billingPaymentState = paymentAvailability?.toPaymentState()
Expand All @@ -50,6 +58,13 @@ class AccountViewModel(
fetchPaymentAvailability()
}

private fun accountData(): Flow<AccountData?> =
// Ignore nulls expect first, to avoid loading when logging out.
accountRepository.accountData
.filterNotNull()
.onStart<AccountData?> { emit(accountRepository.accountData.value) }
.distinctUntilChanged()

fun onManageAccountClick() {
viewModelScope.launch {
accountRepository.getWebsiteAuthToken()?.let { wwwAuthToken ->
Expand Down Expand Up @@ -115,7 +130,7 @@ class AccountViewModel(

data class AccountUiState(
val deviceName: String?,
val accountNumber: String?,
val accountNumber: AccountNumber?,
val accountExpiry: DateTime?,
val showSitePayment: Boolean,
val billingPaymentState: PaymentState? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,21 @@ class AccountViewModelTest {
private val mockDeviceRepository: DeviceRepository = mockk(relaxUnitFun = true)
private val mockPaymentUseCase: PaymentUseCase = mockk(relaxed = true)

private val deviceState: MutableStateFlow<DeviceState?> = MutableStateFlow(null)
private val paymentAvailability = MutableStateFlow<PaymentAvailability?>(null)
private val purchaseResult = MutableStateFlow<PurchaseResult?>(null)
private val accountExpiryState = MutableStateFlow(null)

private val dummyDevice =
Device(id = DeviceId.fromString(UUID), name = "fake_name", creationDate = DateTime.now())
private val dummyAccountNumber: AccountNumber =
AccountNumber(
DUMMY_DEVICE_NAME,
)

private val deviceState: MutableStateFlow<DeviceState?> =
MutableStateFlow(
DeviceState.LoggedIn(accountNumber = dummyAccountNumber, device = dummyDevice)
)
private val paymentAvailability = MutableStateFlow<PaymentAvailability?>(null)
private val purchaseResult = MutableStateFlow<PurchaseResult?>(null)
private val accountExpiryState = MutableStateFlow(null)

private lateinit var viewModel: AccountViewModel

@BeforeEach
Expand Down Expand Up @@ -80,11 +83,10 @@ class AccountViewModelTest {
fun `given device state LoggedIn uiState should contain accountNumber`() = runTest {
// Act, Assert
viewModel.uiState.test {
awaitItem() // Default state
deviceState.value =
DeviceState.LoggedIn(accountNumber = dummyAccountNumber, device = dummyDevice)
val result = awaitItem()
assertEquals(DUMMY_DEVICE_NAME, result.accountNumber)
assertEquals(dummyAccountNumber, result.accountNumber)
}
}

Expand All @@ -100,8 +102,6 @@ class AccountViewModelTest {
@Test
fun `when paymentAvailability emits ProductsUnavailable uiState should be NoPayment`() =
runTest {
// Arrange in setup

// Act, Assert
viewModel.uiState.test {
awaitItem() // Default state
Expand Down

0 comments on commit d7b2161

Please sign in to comment.