diff options
Diffstat (limited to 'android')
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt index 0057457c5e..4a60508a38 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt @@ -33,6 +33,7 @@ class DeviceListViewModel( private val dispatcher: CoroutineDispatcher = Dispatchers.Default ) : ViewModel() { private val _stagedDeviceId = MutableStateFlow<DeviceId?>(null) + private val _loadingDevices = MutableStateFlow<List<DeviceId>>(emptyList()) private val _toastMessages = MutableSharedFlow<String>(extraBufferCapacity = 1) val toastMessages = _toastMessages.asSharedFlow() @@ -40,27 +41,29 @@ class DeviceListViewModel( var accountToken: String? = null private var cachedDeviceList: List<Device>? = null - val uiState = deviceRepository.deviceList - .combine(_stagedDeviceId) { deviceList, stagedDeviceId -> - val devices = if (deviceList is DeviceList.Available) { - deviceList.devices.also { cachedDeviceList = it } - } else { - cachedDeviceList - } - val deviceUiItems = devices?.map { device -> - DeviceListItemUiState(device, false) - } ?: emptyList() - val isLoading = devices == null - val stagedDevice = devices?.firstOrNull { device -> - device.id == stagedDeviceId - } - DeviceListUiState( - deviceUiItems = deviceUiItems, - isLoading = isLoading, - stagedDevice = stagedDevice - ) + val uiState = combine( + deviceRepository.deviceList, + _stagedDeviceId, + _loadingDevices + ) { deviceList, stagedDeviceId, loadingDevices -> + val devices = if (deviceList is DeviceList.Available) { + deviceList.devices.also { cachedDeviceList = it } + } else { + cachedDeviceList } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), DeviceListUiState.INITIAL) + val deviceUiItems = devices?.map { device -> + DeviceListItemUiState(device, loadingDevices.any { device.id == it }) + } ?: emptyList() + val isLoading = devices == null + val stagedDevice = devices?.firstOrNull { device -> + device.id == stagedDeviceId + } + DeviceListUiState( + deviceUiItems = deviceUiItems, + isLoading = isLoading, + stagedDevice = stagedDevice + ) + }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), DeviceListUiState.INITIAL) fun stageDeviceForRemoval(deviceId: DeviceId) { _stagedDeviceId.value = deviceId @@ -81,6 +84,7 @@ class DeviceListViewModel( deviceRepository.deviceRemovalEvent .onSubscription { clearStagedDevice() + setLoadingDevice(stagedDeviceId) deviceRepository.removeDevice(token, stagedDeviceId) } .filter { (deviceId, result) -> @@ -89,6 +93,8 @@ class DeviceListViewModel( .first() } + clearLoadingDevice(stagedDeviceId) + if (result == null) { _toastMessages.tryEmit( resources.getString(R.string.failed_to_remove_device) @@ -99,6 +105,7 @@ class DeviceListViewModel( } } else { _toastMessages.tryEmit(resources.getString(R.string.error_occurred)) + clearLoadingDevices() clearStagedDevice() refreshDeviceList() } @@ -110,6 +117,18 @@ class DeviceListViewModel( deviceRepository.refreshDeviceList(token) } + private fun setLoadingDevice(deviceId: DeviceId) { + _loadingDevices.value = _loadingDevices.value.toMutableList().apply { add(deviceId) } + } + + private fun clearLoadingDevice(deviceId: DeviceId) { + _loadingDevices.value = _loadingDevices.value.toMutableList().apply { remove(deviceId) } + } + + private fun clearLoadingDevices() { + _loadingDevices.value = emptyList() + } + companion object { private const val DEVICE_REMOVAL_TIMEOUT_MILLIS = 5000L } |
