diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt index 4657a2f673..96c3c34abd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt @@ -198,7 +198,10 @@ class LinkDeviceFragment : ComposeFragment() { state = state, modifier = Modifier.padding(contentPadding), onLearnMoreClicked = { navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet) }, - onLinkNewDeviceClicked = { navController.navigateToQrScannerIfAuthed(!state.needsBioAuthEducationSheet) }, + onLinkNewDeviceClicked = { + viewModel.stopExistingPolling() + navController.navigateToQrScannerIfAuthed(!state.needsBioAuthEducationSheet) + }, onDeviceSelectedForRemoval = { device -> viewModel.setDeviceToRemove(device) }, onDeviceRemovalConfirmed = { device -> viewModel.removeDevice(device) }, onSyncFailureRetryRequested = { viewModel.onSyncErrorRetryRequested() }, diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt index 4a4b2bfcad..a99d63d8ff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt @@ -4,6 +4,8 @@ import android.net.Uri import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update @@ -39,8 +41,11 @@ class LinkDeviceViewModel : ViewModel() { private val _state = MutableStateFlow(LinkDeviceSettingsState()) val state = _state.asStateFlow() + private var pollJob: Job? = null + fun initialize() { loadDevices(initialLoad = true) + pollForDevices() } /** @@ -123,6 +128,28 @@ class LinkDeviceViewModel : ViewModel() { } } + /** + * Poll the server for devices every 5 seconds for 60 seconds + */ + private fun pollForDevices() { + stopExistingPolling() + pollJob = viewModelScope.launch(Dispatchers.IO) { + for (i in 1..12) { + delay(5.seconds) + val devices = LinkDeviceRepository.loadDevices() + if (devices != null) { + _state.value = _state.value.copy( + devices = devices + ) + } + } + } + } + + fun stopExistingPolling() { + pollJob?.cancel() + } + fun showFrontCamera() { _state.update { val frontCamera = it.showFrontCamera @@ -380,9 +407,7 @@ class LinkDeviceViewModel : ViewModel() { LinkedDeviceInactiveCheckJob.enqueue() } - private fun Uri.supportsLinkAndSync(): Boolean { - return this.getQueryParameter("capabilities")?.split(",")?.contains("backup") == true - } + private fun Uri.supportsLinkAndSync(): Boolean = this.getQueryParameter("capabilities")?.split(",")?.contains("backup") == true fun onSyncErrorIgnored() = viewModelScope.launch(Dispatchers.IO) { val dialogState = _state.value.dialogState @@ -443,6 +468,7 @@ class LinkDeviceViewModel : ViewModel() { } fun setDeviceToEdit(device: Device) { + stopExistingPolling() _state.update { it.copy( deviceToEdit = device