diff options
| author | saber safavi <saber.safavi@codic.se> | 2023-10-03 12:54:46 +0200 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2023-10-11 10:37:47 +0200 |
| commit | 03cb890fec0b6d17e05529de832ce075431c2f9f (patch) | |
| tree | 9356a71b39b0438bbcb7e507f9d2bb31d3493551 /android/app/src | |
| parent | 7b117b624f25299b02762bb962ce6e0304f7c095 (diff) | |
| download | mullvadvpn-03cb890fec0b6d17e05529de832ce075431c2f9f.tar.xz mullvadvpn-03cb890fec0b6d17e05529de832ce075431c2f9f.zip | |
Add MVVM parts
Diffstat (limited to 'android/app/src')
3 files changed, 118 insertions, 3 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VoucherDialogUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VoucherDialogUiState.kt new file mode 100644 index 0000000000..e719bda529 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VoucherDialogUiState.kt @@ -0,0 +1,21 @@ +package net.mullvad.mullvadvpn.compose.state + +data class VoucherDialogUiState( + val voucherInput: String = "", + val voucherViewModelState: VoucherDialogState = VoucherDialogState.Default +) { + companion object { + val INITIAL = VoucherDialogUiState() + } +} + +sealed interface VoucherDialogState { + + data object Default : VoucherDialogState + + data object Verifying : VoucherDialogState + + data class Success(val addedTime: Long) : VoucherDialogState + + data class Error(val errorMessage: String) : VoucherDialogState +} 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 18e98964e8..63fcf17ad2 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 @@ -32,6 +32,7 @@ import net.mullvad.mullvadvpn.viewmodel.SelectLocationViewModel import net.mullvad.mullvadvpn.viewmodel.SettingsViewModel import net.mullvad.mullvadvpn.viewmodel.SplitTunnelingViewModel import net.mullvad.mullvadvpn.viewmodel.ViewLogsViewModel +import net.mullvad.mullvadvpn.viewmodel.VoucherDialogViewModel import net.mullvad.mullvadvpn.viewmodel.VpnSettingsViewModel import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel import org.apache.commons.validator.routines.InetAddressValidator @@ -86,14 +87,15 @@ val uiModule = module { viewModel { DeviceListViewModel(get(), get()) } viewModel { DeviceRevokedViewModel(get(), get()) } viewModel { LoginViewModel(get(), get()) } + viewModel { OutOfTimeViewModel(get(), get()) } viewModel { PrivacyDisclaimerViewModel(get()) } + viewModel { ReportProblemViewModel(get()) } viewModel { SelectLocationViewModel(get()) } viewModel { SettingsViewModel(get(), get()) } + viewModel { ViewLogsViewModel(get()) } + viewModel { VoucherDialogViewModel(get(), get()) } viewModel { VpnSettingsViewModel(get(), get(), get(), get()) } viewModel { WelcomeViewModel(get(), get(), get()) } - viewModel { ReportProblemViewModel(get()) } - viewModel { ViewLogsViewModel(get()) } - viewModel { OutOfTimeViewModel(get(), get()) } } const val SELF_PACKAGE_NAME = "SELF_PACKAGE_NAME" diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt new file mode 100644 index 0000000000..07c56ff954 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModel.kt @@ -0,0 +1,92 @@ +package net.mullvad.mullvadvpn.viewmodel + +import android.content.res.Resources +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.shareIn +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.state.LoginUiState +import net.mullvad.mullvadvpn.compose.state.VoucherDialogState +import net.mullvad.mullvadvpn.compose.state.VoucherDialogUiState +import net.mullvad.mullvadvpn.model.VoucherSubmissionError +import net.mullvad.mullvadvpn.model.VoucherSubmissionResult +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.VoucherRedeemer + +class VoucherDialogViewModel( + serviceConnectionManager: ServiceConnectionManager, + private val resources: Resources +) : ViewModel() { + + private val vmState = MutableStateFlow<VoucherDialogState>(VoucherDialogState.Default) + private val voucherInput = MutableStateFlow(LoginUiState.INITIAL.accountNumberInput) + + private lateinit var voucherRedeemer: VoucherRedeemer + private val _shared: SharedFlow<ServiceConnectionContainer> = + serviceConnectionManager.connectionState + .flatMapLatest { state -> + if (state is ServiceConnectionState.ConnectedReady) { + flowOf(state.container) + } else { + emptyFlow() + } + } + .shareIn(viewModelScope, SharingStarted.WhileSubscribed()) + + var uiState = + _shared + .flatMapLatest { serviceConnection -> + voucherRedeemer = serviceConnection.voucherRedeemer + combine(vmState, voucherInput) { state, input -> + VoucherDialogUiState(voucherInput = input, voucherViewModelState = state) + } + } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), VoucherDialogUiState.INITIAL) + + fun onRedeem(voucherCode: String) { + vmState.update { VoucherDialogState.Verifying } + viewModelScope.launch { + when (val result = voucherRedeemer.submit(voucherCode)) { + is VoucherSubmissionResult.Ok -> handleAddedTime(result.submission.timeAdded) + is VoucherSubmissionResult.Error -> setError(result.error) + else -> { + vmState.update { VoucherDialogState.Default } + } + } + } + } + + fun onVoucherInputChange(voucherString: String) { + voucherInput.value = voucherString + } + + private fun handleAddedTime(timeAdded: Long) { + viewModelScope.launch { vmState.update { VoucherDialogState.Success(timeAdded) } } + } + + private fun setError(error: VoucherSubmissionError) { + viewModelScope.launch { + val message = + resources.getString( + when (error) { + VoucherSubmissionError.InvalidVoucher -> R.string.invalid_voucher + VoucherSubmissionError.VoucherAlreadyUsed -> R.string.voucher_already_used + else -> R.string.error_occurred + } + ) + vmState.update { VoucherDialogState.Error(message) } + } + } +} |
