Update devices screen after linking a new device.
This commit is contained in:
parent
7bd5ad8c0b
commit
7086709082
7 changed files with 103 additions and 39 deletions
|
@ -26,7 +26,8 @@ import java.util.Optional;
|
|||
|
||||
public class MultiDeviceConfigurationUpdateJob extends BaseJob {
|
||||
|
||||
public static final String KEY = "MultiDeviceConfigurationUpdateJob";
|
||||
public static final String KEY = "MultiDeviceConfigurationUpdateJob";
|
||||
public static final String QUEUE = "__MULTI_DEVICE_CONFIGURATION_UPDATE_JOB__";
|
||||
|
||||
private static final String TAG = Log.tag(MultiDeviceConfigurationUpdateJob.class);
|
||||
|
||||
|
@ -46,7 +47,7 @@ public class MultiDeviceConfigurationUpdateJob extends BaseJob {
|
|||
boolean linkPreviewsEnabled)
|
||||
{
|
||||
this(new Job.Parameters.Builder()
|
||||
.setQueue("__MULTI_DEVICE_CONFIGURATION_UPDATE_JOB__")
|
||||
.setQueue(QUEUE)
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setMaxAttempts(10)
|
||||
.build(),
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.thoughtcrime.securesms.linkdevice
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
|
@ -23,6 +25,8 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
@ -36,6 +40,7 @@ import androidx.compose.ui.text.TextStyle
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.signal.core.ui.Buttons
|
||||
import org.signal.core.ui.Dialogs
|
||||
|
@ -45,7 +50,6 @@ import org.signal.core.ui.Scaffolds
|
|||
import org.signal.core.ui.SignalPreview
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.compose.ComposeFragment
|
||||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import java.util.Locale
|
||||
|
@ -57,69 +61,54 @@ class LinkDeviceFragment : ComposeFragment() {
|
|||
|
||||
private val viewModel: LinkDeviceViewModel by activityViewModels()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
viewModel.initialize(requireContext())
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val navController: NavController by remember { mutableStateOf(findNavController()) }
|
||||
|
||||
LaunchedEffect(state.toastDialog) {
|
||||
if (state.toastDialog.isNotEmpty()) {
|
||||
Toast.makeText(requireContext(), state.toastDialog, Toast.LENGTH_LONG).show()
|
||||
viewModel.clearToast()
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(state.showFinishedSheet) {
|
||||
if (state.showFinishedSheet) {
|
||||
onShowFinishedSheet()
|
||||
findNavController().safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceFinishedSheet)
|
||||
viewModel.markFinishedSheetSeen()
|
||||
}
|
||||
}
|
||||
|
||||
Scaffolds.Settings(
|
||||
title = stringResource(id = R.string.preferences__linked_devices),
|
||||
onNavigationClick = { findNavController().popBackStack() },
|
||||
onNavigationClick = { navController.popBackStack() },
|
||||
navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24),
|
||||
navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close)
|
||||
) { contentPadding: PaddingValues ->
|
||||
DeviceDescriptionScreen(
|
||||
state = state,
|
||||
navController = navController,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
onLearnMore = this::openLearnMore,
|
||||
onLinkDevice = this::openLinkNewDevice,
|
||||
setDeviceToRemove = this::setDeviceToRemove,
|
||||
onRemoveDevice = this::onRemoveDevice
|
||||
onLearnMore = { navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet) },
|
||||
onLinkDevice = { navController.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment) },
|
||||
setDeviceToRemove = { device -> viewModel.setDeviceToRemove(device) },
|
||||
onRemoveDevice = { device -> viewModel.removeDevice(requireContext(), device) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.loadDevices(requireContext())
|
||||
}
|
||||
|
||||
private fun openLearnMore() {
|
||||
LinkDeviceLearnMoreBottomSheetFragment().show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
|
||||
private fun openLinkNewDevice() {
|
||||
findNavController().safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment)
|
||||
}
|
||||
|
||||
private fun setDeviceToRemove(device: Device?) {
|
||||
viewModel.setDeviceToRemove(device)
|
||||
}
|
||||
|
||||
private fun onRemoveDevice(device: Device) {
|
||||
viewModel.removeDevice(requireContext(), device)
|
||||
}
|
||||
|
||||
private fun onShowFinishedSheet() {
|
||||
LinkDeviceFinishedSheet().show(childFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
viewModel.markFinishedSheetSeen()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DeviceDescriptionScreen(
|
||||
state: LinkDeviceSettingsState,
|
||||
navController: NavController? = null,
|
||||
modifier: Modifier = Modifier,
|
||||
onLearnMore: () -> Unit = {},
|
||||
onLinkDevice: () -> Unit = {},
|
||||
|
@ -127,6 +116,9 @@ fun DeviceDescriptionScreen(
|
|||
onRemoveDevice: (Device) -> Unit = {}
|
||||
) {
|
||||
if (state.progressDialogMessage != -1) {
|
||||
if (navController?.currentDestination?.id == R.id.linkDeviceFinishedSheet) {
|
||||
navController?.popBackStack()
|
||||
}
|
||||
Dialogs.IndeterminateProgressDialog(stringResource(id = state.progressDialogMessage))
|
||||
}
|
||||
if (state.deviceToRemove != null) {
|
||||
|
|
|
@ -17,5 +17,6 @@ data class LinkDeviceSettingsState(
|
|||
val linkDeviceResult: LinkDeviceRepository.LinkDeviceResult = LinkDeviceRepository.LinkDeviceResult.UNKNOWN,
|
||||
val showFinishedSheet: Boolean = false,
|
||||
val seenIntroSheet: Boolean = false,
|
||||
val pendingBiometrics: Boolean = false
|
||||
val pendingBiometrics: Boolean = false,
|
||||
val pendingNewDevice: Boolean = false
|
||||
)
|
||||
|
|
|
@ -14,7 +14,11 @@ import kotlinx.coroutines.launch
|
|||
import org.signal.core.util.toOptional
|
||||
import org.signal.qr.QrProcessor
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.JobTracker
|
||||
import org.thoughtcrime.securesms.jobs.LinkedDeviceInactiveCheckJob
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceConfigurationUpdateJob
|
||||
|
||||
/**
|
||||
* Maintains the state of the [LinkDeviceFragment]
|
||||
|
@ -24,6 +28,26 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
private val _state = MutableStateFlow(LinkDeviceSettingsState())
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
private lateinit var listener: JobTracker.JobListener
|
||||
|
||||
fun initialize(context: Context) {
|
||||
listener = JobTracker.JobListener { _, jobState ->
|
||||
if (jobState.isComplete) {
|
||||
loadDevices(context = context, isPotentialNewDevice = true)
|
||||
}
|
||||
}
|
||||
AppDependencies.jobManager.addListener(
|
||||
{ job: Job -> job.parameters.queue?.startsWith(MultiDeviceConfigurationUpdateJob.QUEUE) ?: false },
|
||||
listener
|
||||
)
|
||||
loadDevices(context)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
AppDependencies.jobManager.removeListener(listener)
|
||||
}
|
||||
|
||||
fun setDeviceToRemove(device: Device?) {
|
||||
_state.update { it.copy(deviceToRemove = device) }
|
||||
}
|
||||
|
@ -47,7 +71,14 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
fun loadDevices(context: Context) {
|
||||
private fun loadDevices(context: Context, isPotentialNewDevice: Boolean = false) {
|
||||
if (isPotentialNewDevice && !_state.value.pendingNewDevice) {
|
||||
return
|
||||
}
|
||||
_state.value = _state.value.copy(
|
||||
progressDialogMessage = if (isPotentialNewDevice) R.string.LinkDeviceFragment__linking_device else -1,
|
||||
pendingNewDevice = if (isPotentialNewDevice) false else _state.value.pendingNewDevice
|
||||
)
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val devices = LinkDeviceRepository.loadDevices()
|
||||
if (devices == null) {
|
||||
|
@ -58,7 +89,7 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
} else {
|
||||
_state.update {
|
||||
it.copy(
|
||||
toastDialog = "",
|
||||
toastDialog = if (isPotentialNewDevice) context.getString(R.string.LinkDeviceFragment__device_approved) else "",
|
||||
devices = devices,
|
||||
progressDialogMessage = -1
|
||||
)
|
||||
|
@ -160,7 +191,8 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
it.copy(
|
||||
showFinishedSheet = showSheet,
|
||||
linkDeviceResult = LinkDeviceRepository.LinkDeviceResult.UNKNOWN,
|
||||
toastDialog = ""
|
||||
toastDialog = "",
|
||||
pendingNewDevice = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -192,4 +224,12 @@ class LinkDeviceViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearToast() {
|
||||
_state.update {
|
||||
it.copy(
|
||||
toastDialog = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -243,7 +243,20 @@
|
|||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_linkDeviceFinishedSheet"
|
||||
app:destination="@id/linkDeviceFinishedSheet" />
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet"
|
||||
app:destination="@id/linkDeviceLearnMoreBottomSheet" />
|
||||
</fragment>
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceFinishedSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceFinishedSheet" />
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceLearnMoreBottomSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceLearnMoreBottomSheetFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/addLinkDeviceFragment"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.AddLinkDeviceFragment"
|
||||
|
|
|
@ -243,7 +243,20 @@
|
|||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_linkDeviceFinishedSheet"
|
||||
app:destination="@id/linkDeviceFinishedSheet" />
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet"
|
||||
app:destination="@id/linkDeviceLearnMoreBottomSheet" />
|
||||
</fragment>
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceFinishedSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceFinishedSheet" />
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceLearnMoreBottomSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceLearnMoreBottomSheetFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/addLinkDeviceFragment"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.AddLinkDeviceFragment"
|
||||
|
|
|
@ -881,6 +881,10 @@
|
|||
<string name="LinkDeviceFragment__unlink">Unlink</string>
|
||||
<!-- Toast message indicating a device has been unlinked where %s is the name of the device -->
|
||||
<string name="LinkDeviceFragment__s_unlinked">%s unlinked</string>
|
||||
<!-- Progress dialog message indicating that a device is currently being linked with an account -->
|
||||
<string name="LinkDeviceFragment__linking_device">Linking device…</string>
|
||||
<!-- Toast message shown after a device has been linked -->
|
||||
<string name="LinkDeviceFragment__device_approved">Device approved</string>
|
||||
|
||||
<!-- AddLinkDeviceFragment -->
|
||||
<!-- Description text shown on the QR code scanner when linking a device -->
|
||||
|
|
Loading…
Add table
Reference in a new issue