mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 00:59:49 +01:00
Notify a user when they link a device.
This commit is contained in:
committed by
Greyson Parrelli
parent
919648b94b
commit
d4c8c16df3
@@ -137,7 +137,7 @@ class LinkDeviceFragment : ComposeFragment() {
|
||||
Log.i(TAG, "Acquiring wake lock for linked device")
|
||||
linkDeviceWakeLock.acquire()
|
||||
}
|
||||
DialogState.Unlinking -> Unit
|
||||
DialogState.Unlinking, is DialogState.DeviceUnlinked -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,8 @@ class LinkDeviceFragment : ComposeFragment() {
|
||||
onEditDevice = { device ->
|
||||
viewModel.setDeviceToEdit(device)
|
||||
navController.safeNavigate(R.id.action_linkDeviceFragment_to_editDeviceNameFragment)
|
||||
}
|
||||
},
|
||||
onDialogDismissed = { viewModel.onDialogDismissed() }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -257,7 +258,8 @@ fun DeviceListScreen(
|
||||
onSyncFailureRetryRequested: () -> Unit = {},
|
||||
onSyncFailureIgnored: () -> Unit = {},
|
||||
onSyncCancelled: () -> Unit = {},
|
||||
onEditDevice: (Device) -> Unit = {}
|
||||
onEditDevice: (Device) -> Unit = {},
|
||||
onDialogDismissed: () -> Unit = {}
|
||||
) {
|
||||
// If a bottom sheet is showing, we don't want the spinner underneath
|
||||
if (!state.bottomSheetVisible) {
|
||||
@@ -291,6 +293,15 @@ fun DeviceListScreen(
|
||||
onDeny = onSyncFailureIgnored
|
||||
)
|
||||
}
|
||||
is DialogState.DeviceUnlinked -> {
|
||||
val createdAt = DateUtils.getOnlyTimeString(LocalContext.current, state.dialogState.deviceCreatedAt)
|
||||
Dialogs.SimpleMessageDialog(
|
||||
title = stringResource(id = R.string.LinkDeviceFragment__device_unlinked),
|
||||
message = stringResource(id = R.string.LinkDeviceFragment__the_device_that_was, createdAt),
|
||||
dismiss = stringResource(id = R.string.LinkDeviceFragment__ok),
|
||||
onDismiss = onDialogDismissed
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,3 +606,17 @@ private fun DeviceListScreenSyncingFailedPreview() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
private fun DeviceListScreenDeviceUnlinkedPreview() {
|
||||
Previews.Preview {
|
||||
DeviceListScreen(
|
||||
state = LinkDeviceSettingsState(
|
||||
dialogState = DialogState.DeviceUnlinked(1736454440342),
|
||||
seenBioAuthEducationSheet = true,
|
||||
seenQrEducationSheet = true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ data class LinkDeviceSettingsState(
|
||||
data class SyncingMessages(val deviceId: Int, val deviceCreatedAt: Long) : DialogState
|
||||
data object SyncingTimedOut : DialogState
|
||||
data class SyncingFailed(val deviceId: Int, val deviceCreatedAt: Long) : DialogState
|
||||
data class DeviceUnlinked(val deviceCreatedAt: Long) : DialogState
|
||||
}
|
||||
|
||||
sealed interface OneTimeEvent {
|
||||
|
||||
@@ -9,14 +9,18 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobs.LinkedDeviceInactiveCheckJob
|
||||
import org.thoughtcrime.securesms.jobs.NewLinkedDeviceNotificationJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.linkdevice.LinkDeviceRepository.LinkDeviceResult
|
||||
import org.thoughtcrime.securesms.linkdevice.LinkDeviceRepository.getPlaintextDeviceName
|
||||
import org.thoughtcrime.securesms.linkdevice.LinkDeviceSettingsState.DialogState
|
||||
import org.thoughtcrime.securesms.linkdevice.LinkDeviceSettingsState.OneTimeEvent
|
||||
import org.thoughtcrime.securesms.linkdevice.LinkDeviceSettingsState.QrCodeState
|
||||
import org.thoughtcrime.securesms.notifications.NotificationIds
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.api.backup.MessageBackupKey
|
||||
import org.whispersystems.signalservice.api.link.TransferArchiveError
|
||||
@@ -36,7 +40,32 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
fun initialize() {
|
||||
loadDevices()
|
||||
loadDevices(initialLoad = true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for the existence of a newly linked device and shows a dialog if it has since been unlinked
|
||||
*/
|
||||
private fun checkForNewDevice(devices: List<Device>) {
|
||||
val newLinkedDeviceId = SignalStore.misc.newLinkedDeviceId
|
||||
val newLinkedDeviceCreatedAt = SignalStore.misc.newLinkedDeviceCreatedTime
|
||||
|
||||
val hasNewLinkedDevice = newLinkedDeviceId > 0
|
||||
if (hasNewLinkedDevice) {
|
||||
ServiceUtil.getNotificationManager(AppDependencies.application).cancel(NotificationIds.NEW_LINKED_DEVICE)
|
||||
SignalStore.misc.newLinkedDeviceId = 0
|
||||
SignalStore.misc.newLinkedDeviceCreatedTime = 0
|
||||
}
|
||||
|
||||
val isMissingNewLinkedDevice = devices.none { device -> device.id == newLinkedDeviceId && device.createdMillis == newLinkedDeviceCreatedAt }
|
||||
|
||||
val dialogState = if (hasNewLinkedDevice && isMissingNewLinkedDevice) {
|
||||
DialogState.DeviceUnlinked(newLinkedDeviceCreatedAt)
|
||||
} else {
|
||||
DialogState.None
|
||||
}
|
||||
|
||||
_state.update { it.copy(dialogState = dialogState) }
|
||||
}
|
||||
|
||||
fun setDeviceToRemove(device: Device?) {
|
||||
@@ -66,7 +95,7 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadDevices() {
|
||||
private fun loadDevices(initialLoad: Boolean = false) {
|
||||
_state.value = _state.value.copy(
|
||||
deviceListLoading = true,
|
||||
showFrontCamera = null
|
||||
@@ -80,6 +109,9 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
deviceListLoading = false
|
||||
)
|
||||
} else {
|
||||
if (initialLoad) {
|
||||
checkForNewDevice(devices)
|
||||
}
|
||||
_state.update {
|
||||
it.copy(
|
||||
oneTimeEvent = OneTimeEvent.None,
|
||||
@@ -143,6 +175,10 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun onDialogDismissed() {
|
||||
_state.update { it.copy(dialogState = DialogState.None) }
|
||||
}
|
||||
|
||||
fun addDevice(shouldSync: Boolean) = viewModelScope.launch(Dispatchers.IO) {
|
||||
val linkUri: Uri = _state.value.linkUri!!
|
||||
|
||||
@@ -243,7 +279,8 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
return
|
||||
}
|
||||
|
||||
Log.d(TAG, "[addDeviceWithSync] Found a linked device!")
|
||||
Log.d(TAG, "[addDeviceWithSync] Found a linked device! Creating notification job.")
|
||||
NewLinkedDeviceNotificationJob.enqueue(waitResult.id, waitResult.created)
|
||||
|
||||
_state.update {
|
||||
it.copy(
|
||||
@@ -319,6 +356,8 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
if (waitResult == null) {
|
||||
Log.i(TAG, "No linked device found!")
|
||||
} else {
|
||||
Log.i(TAG, "Found a linked device! Creating notification job.")
|
||||
NewLinkedDeviceNotificationJob.enqueue(waitResult.id, waitResult.created)
|
||||
_state.update {
|
||||
it.copy(oneTimeEvent = OneTimeEvent.ToastLinked(waitResult.getPlaintextDeviceName()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user