From eae0b43858f4d59407d8945e91282f02236fcfb3 Mon Sep 17 00:00:00 2001 From: Michelle Tang Date: Fri, 18 Jul 2025 13:03:49 -0400 Subject: [PATCH] Generalize device authentication education sheet for backups. --- .../BiometricDeviceAuthentication.kt | 25 +++++-- ...heet.kt => DevicePinAuthEducationSheet.kt} | 66 ++++++++++++------- .../v2/ui/verify/VerifyBackupKeyActivity.kt | 10 ++- .../remote/RemoteBackupsSettingsFragment.kt | 10 ++- .../securesms/keyvalue/UiHintValues.java | 9 --- .../linkdevice/LinkDeviceFragment.kt | 57 ++++++---------- .../linkdevice/LinkDeviceSettingsState.kt | 3 - .../linkdevice/LinkDeviceViewModel.kt | 10 --- .../{ic_phone_lock.xml => phone_lock.xml} | 0 .../{ic_phone_lock.xml => phone_lock.xml} | 0 app/src/main/res/values/strings.xml | 2 + 11 files changed, 104 insertions(+), 88 deletions(-) rename app/src/main/java/org/thoughtcrime/securesms/{linkdevice/LinkDeviceAuthEducationSheet.kt => DevicePinAuthEducationSheet.kt} (60%) rename app/src/main/res/drawable-night/{ic_phone_lock.xml => phone_lock.xml} (100%) rename app/src/main/res/drawable/{ic_phone_lock.xml => phone_lock.xml} (100%) diff --git a/app/src/main/java/org/thoughtcrime/securesms/BiometricDeviceAuthentication.kt b/app/src/main/java/org/thoughtcrime/securesms/BiometricDeviceAuthentication.kt index 23be616211..6fb952cf1f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/BiometricDeviceAuthentication.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/BiometricDeviceAuthentication.kt @@ -45,8 +45,25 @@ class BiometricDeviceAuthentication( } } + /** + * From the docs on [BiometricManager.canAuthenticate] + * + * > Note that not all combinations of authenticator types are supported prior to Android 11 (API 30). + * > Developers that wish to check for the presence of a PIN, pattern, or password on these versions should instead use KeyguardManager.isDeviceSecure(). + */ fun canAuthenticate(context: Context): Boolean { - return isDeviceSecure(context) && biometricManager.canAuthenticate(ALLOWED_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS + return if (Build.VERSION.SDK_INT >= 30) { + biometricManager.canAuthenticate(ALLOWED_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS + } else { + biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS || isDeviceSecure(context) + } + } + + /** + * Returns whether the device credentials education sheet should be shown (only when biometrics is not enabled) + */ + fun shouldShowEducationSheet(context: Context): Boolean { + return canAuthenticate(context) && biometricManager.canAuthenticate(BIOMETRIC_AUTHENTICATORS) != BiometricManager.BIOMETRIC_SUCCESS } private fun isDontKeepActivitiesOn(context: Context): Boolean { @@ -54,10 +71,8 @@ class BiometricDeviceAuthentication( } fun authenticate(context: Context, force: Boolean, showConfirmDeviceCredentialIntent: () -> Unit): Boolean { - val isDeviceSecure = isDeviceSecure(context) - - if (!isDeviceSecure) { - Log.w(TAG, "Device not secure...") + if (!canAuthenticate(context)) { + Log.w(TAG, "Cannot authenticate, skipping. isDeviceSecure: ${isDeviceSecure(context)}, Auth status: ${biometricManager.canAuthenticate(ALLOWED_AUTHENTICATORS)}") return false } diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceAuthEducationSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/DevicePinAuthEducationSheet.kt similarity index 60% rename from app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceAuthEducationSheet.kt rename to app/src/main/java/org/thoughtcrime/securesms/DevicePinAuthEducationSheet.kt index ba2b4982be..23dc786187 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceAuthEducationSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/DevicePinAuthEducationSheet.kt @@ -1,6 +1,7 @@ -package org.thoughtcrime.securesms.linkdevice +package org.thoughtcrime.securesms import android.content.DialogInterface +import android.os.Bundle import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth @@ -16,55 +17,73 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.fragment.app.activityViewModels +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.setFragmentResult import org.signal.core.ui.compose.BottomSheets import org.signal.core.ui.compose.Buttons import org.signal.core.ui.compose.Previews import org.signal.core.ui.compose.SignalPreview -import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment +import org.thoughtcrime.securesms.util.BottomSheetUtil /** - * Education sheet shown before biometrics when linking a device + * Education sheet shown before authentication explaining that users should use their device credentials */ -class LinkDeviceAuthEducationSheet : ComposeBottomSheetDialogFragment() { +class DevicePinAuthEducationSheet : ComposeBottomSheetDialogFragment() { override val peekHeightPercentage: Float = 0.67f - private val viewModel: LinkDeviceViewModel by activityViewModels() + companion object { + const val REQUEST_KEY = "DevicePinAuthEducationSheet" + + private const val ARG_TITLE = "arg.title" + + @JvmStatic + fun show(title: String, fragmentManager: FragmentManager) { + DevicePinAuthEducationSheet().apply { + arguments = Bundle().apply { + putString(ARG_TITLE, title) + } + }.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG) + } + } + + private val title: String + get() = requireArguments().getString(ARG_TITLE)!! + + override fun onDismiss(dialog: DialogInterface) { + setFragmentResult(REQUEST_KEY, Bundle()) + super.onDismiss(dialog) + } @Composable override fun SheetContent() { - DeviceEducationSheet(this::onDismiss) - } - - override fun onCancel(dialog: DialogInterface) { - viewModel.markBioAuthEducationSheetSeen(true) - super.onCancel(dialog) - } - - fun onDismiss() { - viewModel.markBioAuthEducationSheetSeen(true) - dismissAllowingStateLoss() + DevicePinAuthEducationSheet( + title = title, + onClick = { dismissAllowingStateLoss() } + ) } } @Composable -private fun DeviceEducationSheet(onClick: () -> Unit) { +fun DevicePinAuthEducationSheet( + title: String, + onClick: () -> Unit +) { return Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxWidth() ) { BottomSheets.Handle() Icon( - painter = painterResource(R.drawable.ic_phone_lock), + painter = painterResource(R.drawable.phone_lock), contentDescription = null, tint = Color.Unspecified, modifier = Modifier.padding(top = 24.dp) ) Text( - text = stringResource(R.string.LinkDeviceFragment__before_linking), + text = title, style = MaterialTheme.typography.titleLarge, textAlign = TextAlign.Center, modifier = Modifier.padding(top = 20.dp, bottom = 8.dp), @@ -89,8 +108,11 @@ private fun DeviceEducationSheet(onClick: () -> Unit) { @SignalPreview @Composable -fun DeviceEducationSheetPreview() { +fun DevicePinAuthEducationSheetPreview() { Previews.BottomSheetPreview { - DeviceEducationSheet(onClick = {}) + DevicePinAuthEducationSheet( + title = "To continue, confirm it's you", + onClick = {} + ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/verify/VerifyBackupKeyActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/verify/VerifyBackupKeyActivity.kt index 6cc321df4e..347df24b53 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/verify/VerifyBackupKeyActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/verify/VerifyBackupKeyActivity.kt @@ -31,6 +31,7 @@ import org.signal.core.ui.compose.theme.SignalTheme import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.BiometricDeviceAuthentication import org.thoughtcrime.securesms.BiometricDeviceLockContract +import org.thoughtcrime.securesms.DevicePinAuthEducationSheet import org.thoughtcrime.securesms.PassphraseRequiredActivity import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.backup.v2.ui.subscription.EnterKeyScreen @@ -66,7 +67,14 @@ class VerifyBackupKeyActivity : PassphraseRequiredActivity() { VerifyBackupPinScreen( backupKey = SignalStore.account.accountEntropyPool.displayValue, onForgotKeyClick = { - if (!biometricDeviceAuthentication.authenticate(this, true) { biometricDeviceLockLauncher.launch(getString(R.string.RemoteBackupsSettingsFragment__unlock_to_view_backup_key)) }) { + if (biometricDeviceAuthentication.shouldShowEducationSheet(this)) { + DevicePinAuthEducationSheet.show(getString(R.string.RemoteBackupsSettingsFragment__to_view_your_key), supportFragmentManager) + supportFragmentManager.setFragmentResultListener(DevicePinAuthEducationSheet.REQUEST_KEY, this) { _, _ -> + if (!biometricDeviceAuthentication.authenticate(this, true) { biometricDeviceLockLauncher.launch(getString(R.string.RemoteBackupsSettingsFragment__unlock_to_view_backup_key)) }) { + displayBackupKey() + } + } + } else if (!biometricDeviceAuthentication.authenticate(this, true) { biometricDeviceLockLauncher.launch(getString(R.string.RemoteBackupsSettingsFragment__unlock_to_view_backup_key)) }) { displayBackupKey() } }, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt index fcea8563e1..17cb7ea2bf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/RemoteBackupsSettingsFragment.kt @@ -91,6 +91,7 @@ import org.signal.core.util.logging.Log import org.signal.core.util.mebiBytes import org.signal.core.util.money.FiatMoney import org.thoughtcrime.securesms.BiometricDeviceAuthentication +import org.thoughtcrime.securesms.DevicePinAuthEducationSheet import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.backup.ArchiveUploadProgress import org.thoughtcrime.securesms.backup.DeletionState @@ -214,7 +215,14 @@ class RemoteBackupsSettingsFragment : ComposeFragment() { } override fun onViewBackupKeyClick() { - if (!biometricDeviceAuthentication.authenticate(requireContext(), true, this@RemoteBackupsSettingsFragment::showConfirmDeviceCredentialIntent)) { + if (biometricDeviceAuthentication.shouldShowEducationSheet(requireContext())) { + DevicePinAuthEducationSheet.show(getString(R.string.RemoteBackupsSettingsFragment__to_view_your_key), parentFragmentManager) + parentFragmentManager.setFragmentResultListener(DevicePinAuthEducationSheet.REQUEST_KEY, viewLifecycleOwner) { _, _ -> + if (!biometricDeviceAuthentication.authenticate(requireContext(), true, this@RemoteBackupsSettingsFragment::showConfirmDeviceCredentialIntent)) { + displayBackupKey() + } + } + } else if (!biometricDeviceAuthentication.authenticate(requireContext(), true, this@RemoteBackupsSettingsFragment::showConfirmDeviceCredentialIntent)) { displayBackupKey() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/UiHintValues.java b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/UiHintValues.java index c30347a5d6..3d2a090fcd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/UiHintValues.java +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/UiHintValues.java @@ -30,7 +30,6 @@ public class UiHintValues extends SignalStoreValues { private static final String HAS_EVER_ENABLED_REMOTE_BACKUPS = "uihints.has_ever_enabled_remote_backups"; private static final String HAS_SEEN_CHAT_FOLDERS_EDUCATION_SHEET = "uihints.has_seen_chat_folders_education_sheet"; private static final String HAS_SEEN_LINK_DEVICE_QR_EDUCATION_SHEET = "uihints.has_seen_link_device_qr_education_sheet"; - private static final String LAST_SEEN_LINK_DEVICE_AUTH_SHEET_TIME = "uihints.last_seen_link_device_auth_sheet_time"; private static final String HAS_DISMISSED_SAVE_STORAGE_WARNING = "uihints.has_dismissed_save_storage_warning"; UiHintValues(@NonNull KeyValueStore store) { @@ -230,14 +229,6 @@ public class UiHintValues extends SignalStoreValues { return getBoolean(HAS_SEEN_LINK_DEVICE_QR_EDUCATION_SHEET, false); } - public void setLastSeenLinkDeviceAuthSheetTime(long time) { - putLong(LAST_SEEN_LINK_DEVICE_AUTH_SHEET_TIME, time); - } - - public long getLastSeenLinkDeviceAuthSheetTime() { - return getLong(LAST_SEEN_LINK_DEVICE_AUTH_SHEET_TIME, 0); - } - public boolean hasDismissedSaveStorageWarning() { return getBoolean(HAS_DISMISSED_SAVE_STORAGE_WARNING, false); } 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 7498c7bd56..a5d662a01c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt @@ -68,6 +68,7 @@ import org.signal.core.ui.compose.SignalPreview import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.BiometricDeviceAuthentication import org.thoughtcrime.securesms.BiometricDeviceLockContract +import org.thoughtcrime.securesms.DevicePinAuthEducationSheet import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.compose.ComposeFragment import org.thoughtcrime.securesms.linkdevice.LinkDeviceSettingsState.DialogState @@ -161,7 +162,7 @@ class LinkDeviceFragment : ComposeFragment() { Toast.makeText(context, context.getString(R.string.DeviceListActivity_network_failed), Toast.LENGTH_LONG).show() } LinkDeviceSettingsState.OneTimeEvent.LaunchQrCodeScanner -> { - navController.navigateToQrScannerIfAuthed(state.seenBioAuthEducationSheet) + navController.navigateToQrScannerIfAuthed() } LinkDeviceSettingsState.OneTimeEvent.ShowFinishedSheet -> { navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceFinishedSheet) @@ -185,15 +186,6 @@ class LinkDeviceFragment : ComposeFragment() { } } - LaunchedEffect(state.seenBioAuthEducationSheet) { - if (state.seenBioAuthEducationSheet) { - if (!biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.LinkDeviceFragment__unlock_to_link)) }) { - navController.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment) - } - viewModel.markBioAuthEducationSheetSeen(false) - } - } - Scaffolds.Settings( title = stringResource(id = R.string.preferences__linked_devices), onNavigationClick = { navController.popOrFinish() }, @@ -206,7 +198,7 @@ class LinkDeviceFragment : ComposeFragment() { onLearnMoreClicked = { navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet) }, onLinkNewDeviceClicked = { viewModel.stopExistingPolling() - navController.navigateToQrScannerIfAuthed(!state.needsBioAuthEducationSheet) + navController.navigateToQrScannerIfAuthed() }, onDeviceSelectedForRemoval = { device -> viewModel.setDeviceToRemove(device) }, onDeviceRemovalConfirmed = { device -> viewModel.removeDevice(device) }, @@ -236,14 +228,15 @@ class LinkDeviceFragment : ComposeFragment() { return SupportEmailUtil.generateSupportEmailBody(requireContext(), filter, prefix.toString(), null) } - private fun NavController.navigateToQrScannerIfAuthed(seenEducation: Boolean) { - if (seenEducation && biometricAuth.canAuthenticate(requireContext())) { - if (!biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.LinkDeviceFragment__unlock_to_link)) }) { - this.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment) + private fun NavController.navigateToQrScannerIfAuthed() { + if (biometricAuth.shouldShowEducationSheet(requireContext())) { + DevicePinAuthEducationSheet.show(getString(R.string.LinkDeviceFragment__before_linking), parentFragmentManager) + parentFragmentManager.setFragmentResultListener(DevicePinAuthEducationSheet.REQUEST_KEY, viewLifecycleOwner) { _, _ -> + if (!biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.LinkDeviceFragment__unlock_to_link)) }) { + this.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment) + } } - } else if (biometricAuth.canAuthenticate(requireContext())) { - this.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceEducationSheet) - } else { + } else if (!biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.LinkDeviceFragment__unlock_to_link)) }) { this.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment) } } @@ -609,8 +602,7 @@ private fun DeviceListScreenPreview() { Device(1, "Sam's Macbook Pro", 1715793982000, 1716053182000), Device(1, "Sam's iPad", 1715793182000, 1716053122000) ), - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -623,8 +615,7 @@ private fun DeviceListScreenLoadingPreview() { DeviceListScreen( state = LinkDeviceSettingsState( deviceListLoading = true, - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -637,8 +628,7 @@ private fun DeviceListScreenLinkingPreview() { DeviceListScreen( state = LinkDeviceSettingsState( dialogState = DialogState.Linking, - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -651,8 +641,7 @@ private fun DeviceListScreenUnlinkingPreview() { DeviceListScreen( state = LinkDeviceSettingsState( dialogState = DialogState.Unlinking, - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -665,8 +654,7 @@ private fun DeviceListScreenSyncingMessagesPreview() { DeviceListScreen( state = LinkDeviceSettingsState( dialogState = DialogState.SyncingMessages(1, 1), - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -679,8 +667,7 @@ private fun DeviceListScreenSyncingFailedRetryPreview() { DeviceListScreen( state = LinkDeviceSettingsState( dialogState = DialogState.SyncingTimedOut, - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -697,8 +684,7 @@ private fun DeviceListScreenSyncingFailedPreview() { deviceCreatedAt = 1, syncFailType = LinkDeviceSettingsState.SyncFailType.NOT_RETRYABLE ), - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -711,8 +697,7 @@ private fun DeviceListScreenContactSupportPreview() { DeviceListScreen( state = LinkDeviceSettingsState( dialogState = DialogState.ContactSupport, - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } @@ -725,7 +710,6 @@ private fun DeviceListScreenDeviceUnlinkedPreview() { DeviceListScreen( state = LinkDeviceSettingsState( dialogState = DialogState.DeviceUnlinked(1736454440342), - seenBioAuthEducationSheet = true, seenQrEducationSheet = true ) ) @@ -743,8 +727,7 @@ private fun DeviceListScreenNotEnoughStoragePreview() { deviceCreatedAt = 1, syncFailType = LinkDeviceSettingsState.SyncFailType.NOT_ENOUGH_SPACE ), - seenQrEducationSheet = true, - seenBioAuthEducationSheet = true + seenQrEducationSheet = true ) ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt index 6d416cf7a2..b9e78b6953 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt @@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.linkdevice import android.net.Uri import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.linkdevice.LinkDeviceRepository.LinkDeviceResult -import kotlin.time.Duration.Companion.days /** * Information about linked devices. Used in [LinkDeviceViewModel]. @@ -19,8 +18,6 @@ data class LinkDeviceSettingsState( val linkUri: Uri? = null, val linkDeviceResult: LinkDeviceResult = LinkDeviceResult.None, val seenQrEducationSheet: Boolean = SignalStore.uiHints.hasSeenLinkDeviceQrEducationSheet() || SignalStore.account.hasLinkedDevices, - val seenBioAuthEducationSheet: Boolean = false, - val needsBioAuthEducationSheet: Boolean = !seenBioAuthEducationSheet && SignalStore.uiHints.lastSeenLinkDeviceAuthSheetTime < System.currentTimeMillis() - 30.days.inWholeMilliseconds, val bottomSheetVisible: Boolean = false, val deviceToEdit: Device? = null, val shouldCancelArchiveUpload: Boolean = false, 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 db0510a1c3..7715c6dd33 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt @@ -261,16 +261,6 @@ class LinkDeviceViewModel : ViewModel() { } } - fun markBioAuthEducationSheetSeen(seen: Boolean) { - SignalStore.uiHints.lastSeenLinkDeviceAuthSheetTime = System.currentTimeMillis() - _state.update { - it.copy( - seenBioAuthEducationSheet = seen, - needsBioAuthEducationSheet = false - ) - } - } - private fun addDeviceWithSync(linkUri: Uri) { Log.d(TAG, "[addDeviceWithSync] Beginning device adding process.") diff --git a/app/src/main/res/drawable-night/ic_phone_lock.xml b/app/src/main/res/drawable-night/phone_lock.xml similarity index 100% rename from app/src/main/res/drawable-night/ic_phone_lock.xml rename to app/src/main/res/drawable-night/phone_lock.xml diff --git a/app/src/main/res/drawable/ic_phone_lock.xml b/app/src/main/res/drawable/phone_lock.xml similarity index 100% rename from app/src/main/res/drawable/ic_phone_lock.xml rename to app/src/main/res/drawable/phone_lock.xml diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 54c0ad3c3c..91f26e6544 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8144,6 +8144,8 @@ View backup key Unlock to view backup key + + To view your key, confirm it\'s you Turn off and delete backup