Fix auth prompt during linked device flow.

This commit is contained in:
Greyson Parrelli 2025-01-09 17:59:37 -05:00
parent d23c6fb41c
commit e76309f8e1
5 changed files with 32 additions and 10 deletions

View file

@ -27,7 +27,7 @@ import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
/**
* Education sheet shown before biometrics when linking a device
*/
class LinkDeviceEducationSheet : ComposeBottomSheetDialogFragment() {
class LinkDeviceAuthEducationSheet : ComposeBottomSheetDialogFragment() {
override val peekHeightPercentage: Float = 0.67f

View file

@ -157,6 +157,15 @@ 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() },
@ -167,7 +176,7 @@ class LinkDeviceFragment : ComposeFragment() {
state = state,
modifier = Modifier.padding(contentPadding),
onLearnMoreClicked = { navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet) },
onLinkNewDeviceClicked = { navController.navigateToQrScannerIfAuthed(state.seenBioAuthEducationSheet) },
onLinkNewDeviceClicked = { navController.navigateToQrScannerIfAuthed(!state.needsBioAuthEducationSheet) },
onDeviceSelectedForRemoval = { device -> viewModel.setDeviceToRemove(device) },
onDeviceRemovalConfirmed = { device -> viewModel.removeDevice(device) },
onSyncFailureRetryRequested = { viewModel.onSyncErrorRetryRequested() },
@ -181,8 +190,10 @@ class LinkDeviceFragment : ComposeFragment() {
}
private fun NavController.navigateToQrScannerIfAuthed(seenEducation: Boolean) {
if (seenEducation) {
this.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment)
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)
}
} else if (biometricAuth.canAuthenticate(requireContext())) {
this.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceEducationSheet)
} else {
@ -290,7 +301,9 @@ fun DeviceListScreen(
Buttons.LargeTonal(
onClick = onLinkNewDeviceClicked,
modifier = Modifier.defaultMinSize(300.dp).padding(bottom = 8.dp)
modifier = Modifier
.defaultMinSize(300.dp)
.padding(bottom = 8.dp)
) {
Text(stringResource(id = R.string.LinkDeviceFragment__link_a_new_device))
}
@ -394,7 +407,10 @@ fun DeviceRow(device: Device, setDeviceToRemove: (Device) -> Unit, onEditDevice:
)
Column(
modifier = Modifier.align(Alignment.CenterVertically).padding(start = 16.dp).weight(1f)
modifier = Modifier
.align(Alignment.CenterVertically)
.padding(start = 16.dp)
.weight(1f)
) {
Text(text = titleString, style = MaterialTheme.typography.bodyLarge)
Text(stringResource(R.string.DeviceListItem_linked_s, linkedDate), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant)
@ -405,7 +421,9 @@ fun DeviceRow(device: Device, setDeviceToRemove: (Device) -> Unit, onEditDevice:
Icon(
painterResource(id = R.drawable.symbol_more_vertical),
contentDescription = null,
modifier = Modifier.padding(top = 16.dp, end = 16.dp).clickable { menuController.show() }
modifier = Modifier
.padding(top = 16.dp, end = 16.dp)
.clickable { menuController.show() }
)
DropdownMenus.Menu(controller = menuController, offsetX = 16.dp, offsetY = 4.dp) { controller ->

View file

@ -18,7 +18,8 @@ data class LinkDeviceSettingsState(
val linkUri: Uri? = null,
val linkDeviceResult: LinkDeviceResult = LinkDeviceResult.None,
val seenQrEducationSheet: Boolean = SignalStore.uiHints.hasSeenLinkDeviceQrEducationSheet() || SignalStore.account.hasLinkedDevices,
val seenBioAuthEducationSheet: Boolean = SignalStore.uiHints.hasSeenLinkDeviceAuthSheet() || SignalStore.account.hasLinkedDevices,
val seenBioAuthEducationSheet: Boolean = false,
val needsBioAuthEducationSheet: Boolean = !seenBioAuthEducationSheet && !SignalStore.uiHints.hasSeenLinkDeviceAuthSheet() && !SignalStore.account.hasLinkedDevices,
val bottomSheetVisible: Boolean = false,
val deviceToEdit: Device? = null
) {

View file

@ -197,7 +197,10 @@ class LinkDeviceViewModel : ViewModel() {
fun markBioAuthEducationSheetSeen(seen: Boolean) {
SignalStore.uiHints.markHasSeenLinkDeviceAuthSheet()
_state.update {
it.copy(seenBioAuthEducationSheet = seen)
it.copy(
seenBioAuthEducationSheet = seen,
needsBioAuthEducationSheet = false
)
}
}

View file

@ -269,7 +269,7 @@
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceLearnMoreBottomSheetFragment" />
<dialog
android:id="@+id/linkDeviceEducationSheet"
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceEducationSheet" />
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceAuthEducationSheet" />
<fragment
android:id="@+id/editDeviceNameFragment"