diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceEducationSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceEducationSheet.kt new file mode 100644 index 0000000000..411dfeb2cd --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceEducationSheet.kt @@ -0,0 +1,96 @@ +package org.thoughtcrime.securesms.linkdevice + +import android.content.DialogInterface +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +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 org.signal.core.ui.BottomSheets +import org.signal.core.ui.Buttons +import org.signal.core.ui.Previews +import org.signal.core.ui.SignalPreview +import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment + +/** + * Education sheet shown before biometrics when linking a device + */ +class LinkDeviceEducationSheet : ComposeBottomSheetDialogFragment() { + + override val peekHeightPercentage: Float = 0.67f + + private val viewModel: LinkDeviceViewModel by activityViewModels() + + @Composable + override fun SheetContent() { + DeviceEducationSheet(this::onDismiss) + } + + override fun onCancel(dialog: DialogInterface) { + viewModel.markEducationSheetSeen(true) + super.onCancel(dialog) + } + + fun onDismiss() { + viewModel.markEducationSheetSeen(true) + dismissAllowingStateLoss() + } +} + +@Composable +private fun DeviceEducationSheet(onClick: () -> Unit) { + return Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + BottomSheets.Handle() + Icon( + painter = painterResource(R.drawable.ic_phone_lock), + contentDescription = null, + tint = Color.Unspecified, + modifier = Modifier.padding(top = 24.dp) + ) + + Text( + text = stringResource(R.string.LinkDeviceFragment__before_linking), + style = MaterialTheme.typography.titleLarge, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 20.dp, bottom = 8.dp), + color = MaterialTheme.colorScheme.onSurface + ) + Text( + text = stringResource(R.string.LinkDeviceFragment__tap_continue_and_enter_phone), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.padding(horizontal = 44.dp), + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Buttons.LargeTonal( + onClick = onClick, + modifier = Modifier.defaultMinSize(minWidth = 220.dp).padding(top = 28.dp, bottom = 56.dp) + ) { + Text(stringResource(id = R.string.LinkDeviceFragment__continue)) + } + } +} + +@SignalPreview +@Composable +fun DeviceEducationSheetPreview() { + Previews.BottomSheetPreview { + DeviceEducationSheet(onClick = {}) + } +} 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 f0f42a0265..cd2fd0fbb2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceFragment.kt @@ -133,6 +133,13 @@ class LinkDeviceFragment : ComposeFragment() { } } + LaunchedEffect(state.seenEducationSheet) { + if (state.seenEducationSheet) { + biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.LinkDeviceFragment__unlock_to_link)) } + viewModel.markEducationSheetSeen(false) + } + } + Scaffolds.Settings( title = stringResource(id = R.string.preferences__linked_devices), onNavigationClick = { navController.popOrFinish() }, @@ -146,7 +153,7 @@ class LinkDeviceFragment : ComposeFragment() { onLearnMore = { navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet) }, onLinkDevice = { if (biometricAuth.canAuthenticate()) { - biometricAuth.authenticate(requireContext(), true) { biometricDeviceLockLauncher.launch(getString(R.string.LinkDeviceFragment__unlock_to_link)) } + navController.safeNavigate(R.id.action_linkDeviceFragment_to_linkDeviceEducationSheet) } else { navController.safeNavigate(R.id.action_linkDeviceFragment_to_addLinkDeviceFragment) } 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 a6168fe67b..ba840b7ecd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceSettingsState.kt @@ -17,5 +17,6 @@ data class LinkDeviceSettingsState( val linkDeviceResult: LinkDeviceRepository.LinkDeviceResult = LinkDeviceRepository.LinkDeviceResult.UNKNOWN, val showFinishedSheet: Boolean = false, val seenIntroSheet: Boolean = false, - val pendingNewDevice: Boolean = false + val pendingNewDevice: Boolean = false, + val seenEducationSheet: 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 2797815860..7eaadc258e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceViewModel.kt @@ -191,4 +191,12 @@ class LinkDeviceViewModel : ViewModel() { ) } } + + fun markEducationSheetSeen(seen: Boolean) { + _state.update { + it.copy( + seenEducationSheet = seen + ) + } + } } diff --git a/app/src/main/res/drawable-night/ic_phone_lock.xml b/app/src/main/res/drawable-night/ic_phone_lock.xml new file mode 100644 index 0000000000..dcae314fe1 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_phone_lock.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_phone_lock.xml b/app/src/main/res/drawable/ic_phone_lock.xml new file mode 100644 index 0000000000..08817858aa --- /dev/null +++ b/app/src/main/res/drawable/ic_phone_lock.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/app/src/main/res/navigation/app_settings_with_change_number.xml b/app/src/main/res/navigation/app_settings_with_change_number.xml index 9669c2a659..2fcb080693 100644 --- a/app/src/main/res/navigation/app_settings_with_change_number.xml +++ b/app/src/main/res/navigation/app_settings_with_change_number.xml @@ -249,6 +249,9 @@ + + No linked devices Unlock to link a device + + Before linking, confirm it\'s you + + Tap continue and enter your phone\'s lock to confirm. Do not enter your Signal PIN. + + Continue