mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 04:58:45 +00:00
Add education sheet to linked device biometrics.
This commit is contained in:
committed by
Cody Henthorne
parent
d59985c7b1
commit
93c8cd133d
@@ -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 = {})
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -191,4 +191,12 @@ class LinkDeviceViewModel : ViewModel() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun markEducationSheetSeen(seen: Boolean) {
|
||||
_state.update {
|
||||
it.copy(
|
||||
seenEducationSheet = seen
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
app/src/main/res/drawable-night/ic_phone_lock.xml
Normal file
27
app/src/main/res/drawable-night/ic_phone_lock.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="112dp"
|
||||
android:height="112dp"
|
||||
android:viewportWidth="112"
|
||||
android:viewportHeight="112">
|
||||
<path
|
||||
android:pathData="M28,24C28,16.27 34.27,10 42,10H70C77.73,10 84,16.27 84,24V88C84,95.73 77.73,102 70,102H42C34.27,102 28,95.73 28,88V24Z"
|
||||
android:fillColor="#E3E8FE"/>
|
||||
<path
|
||||
android:pathData="M84,63.05V88.13C84,95.86 77.73,102.13 70,102.13H42C34.27,102.13 28,95.86 28,88.13V63.48C36.12,58.1 45.86,54.96 56.33,54.96C66.52,54.96 76.02,57.93 84,63.05Z"
|
||||
android:fillColor="#C1C7FE"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M27,24C27,15.72 33.72,9 42,9H70C78.28,9 85,15.72 85,24V88C85,96.28 78.28,103 70,103H42C33.72,103 27,96.28 27,88V24ZM42,11C34.82,11 29,16.82 29,24V88C29,95.18 34.82,101 42,101H70C77.18,101 83,95.18 83,88V24C83,16.82 77.18,11 70,11H42Z"
|
||||
android:fillColor="#3B45FD"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M41,60.6C41,57.24 41,55.56 41.65,54.28C42.23,53.15 43.15,52.23 44.28,51.65C45.56,51 47.24,51 50.6,51H61.4C64.76,51 66.44,51 67.72,51.65C68.85,52.23 69.77,53.15 70.35,54.28C71,55.56 71,57.24 71,60.6V66.4C71,69.76 71,71.44 70.35,72.72C69.77,73.85 68.85,74.77 67.72,75.35C66.44,76 64.76,76 61.4,76H50.6C47.24,76 45.56,76 44.28,75.35C43.15,74.77 42.23,73.85 41.65,72.72C41,71.44 41,69.76 41,66.4V60.6Z"
|
||||
android:fillColor="#E3E8FE"/>
|
||||
<path
|
||||
android:pathData="M56,33C49.65,33 44.5,38.15 44.5,44.5V50.48C44.27,50.56 44.04,50.65 43.82,50.76C42.5,51.43 41.43,52.5 40.76,53.82C40.35,54.63 40.17,55.52 40.09,56.58C40,57.62 40,58.91 40,60.56V66.44C40,68.09 40,69.38 40.09,70.42C40.17,71.48 40.35,72.37 40.76,73.18C41.43,74.5 42.5,75.57 43.82,76.24C44.63,76.65 45.52,76.83 46.58,76.91C47.62,77 48.91,77 50.56,77H61.44C63.09,77 64.38,77 65.42,76.91C66.48,76.83 67.37,76.65 68.18,76.24C69.5,75.57 70.57,74.5 71.24,73.18C71.65,72.37 71.83,71.48 71.91,70.42C72,69.38 72,68.09 72,66.44V60.56C72,58.91 72,57.62 71.91,56.58C71.83,55.52 71.65,54.63 71.24,53.82C70.57,52.5 69.5,51.43 68.18,50.76C67.96,50.65 67.73,50.56 67.5,50.48V44.5C67.5,38.15 62.35,33 56,33ZM65.5,50.09V44.5C65.5,39.25 61.25,35 56,35C50.75,35 46.5,39.25 46.5,44.5V50.09C46.53,50.09 46.55,50.09 46.58,50.09C47.62,50 48.91,50 50.56,50H61.44C63.09,50 64.38,50 65.42,50.09C65.45,50.09 65.47,50.09 65.5,50.09ZM44.73,52.54C45.21,52.3 45.8,52.16 46.74,52.08C47.69,52 48.9,52 50.6,52H61.4C63.1,52 64.31,52 65.26,52.08C66.2,52.16 66.79,52.3 67.27,52.54C68.21,53.02 68.98,53.79 69.46,54.73C69.7,55.21 69.84,55.8 69.92,56.74C70,57.69 70,58.9 70,60.6V66.4C70,68.1 70,69.31 69.92,70.26C69.84,71.2 69.7,71.79 69.46,72.27C68.98,73.21 68.21,73.98 67.27,74.46C66.79,74.7 66.2,74.84 65.26,74.92C64.31,75 63.1,75 61.4,75H50.6C48.9,75 47.69,75 46.74,74.92C45.8,74.84 45.21,74.7 44.73,74.46C43.79,73.98 43.02,73.21 42.54,72.27C42.3,71.79 42.16,71.2 42.08,70.26C42,69.31 42,68.1 42,66.4V60.6C42,58.9 42,57.69 42.08,56.74C42.16,55.8 42.3,55.21 42.54,54.73C43.02,53.79 43.79,53.02 44.73,52.54Z"
|
||||
android:fillColor="#3B45FD"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M53.25,61.25C53.25,59.73 54.48,58.5 56,58.5C57.52,58.5 58.75,59.73 58.75,61.25C58.75,62.42 58.02,63.41 57,63.81V67.5C57,68.05 56.55,68.5 56,68.5C55.45,68.5 55,68.05 55,67.5V63.81C53.98,63.41 53.25,62.42 53.25,61.25Z"
|
||||
android:fillColor="#3B45FD"/>
|
||||
</vector>
|
||||
27
app/src/main/res/drawable/ic_phone_lock.xml
Normal file
27
app/src/main/res/drawable/ic_phone_lock.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="112dp"
|
||||
android:height="112dp"
|
||||
android:viewportWidth="112"
|
||||
android:viewportHeight="112">
|
||||
<path
|
||||
android:pathData="M28,24C28,16.27 34.27,10 42,10H70C77.73,10 84,16.27 84,24V88C84,95.73 77.73,102 70,102H42C34.27,102 28,95.73 28,88V24Z"
|
||||
android:fillColor="#E3E8FE"/>
|
||||
<path
|
||||
android:pathData="M84,63.05V88.13C84,95.86 77.73,102.13 70,102.13H42C34.27,102.13 28,95.86 28,88.13V63.48C36.12,58.1 45.86,54.96 56.33,54.96C66.52,54.96 76.02,57.93 84,63.05Z"
|
||||
android:fillColor="#C1C7FE"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M27,24C27,15.72 33.72,9 42,9H70C78.28,9 85,15.72 85,24V88C85,96.28 78.28,103 70,103H42C33.72,103 27,96.28 27,88V24ZM42,11C34.82,11 29,16.82 29,24V88C29,95.18 34.82,101 42,101H70C77.18,101 83,95.18 83,88V24C83,16.82 77.18,11 70,11H42Z"
|
||||
android:fillColor="#020BAC"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M41,60.6C41,57.24 41,55.56 41.65,54.28C42.23,53.15 43.15,52.23 44.28,51.65C45.56,51 47.24,51 50.6,51H61.4C64.76,51 66.44,51 67.72,51.65C68.85,52.23 69.77,53.15 70.35,54.28C71,55.56 71,57.24 71,60.6V66.4C71,69.76 71,71.44 70.35,72.72C69.77,73.85 68.85,74.77 67.72,75.35C66.44,76 64.76,76 61.4,76H50.6C47.24,76 45.56,76 44.28,75.35C43.15,74.77 42.23,73.85 41.65,72.72C41,71.44 41,69.76 41,66.4V60.6Z"
|
||||
android:fillColor="#E3E8FE"/>
|
||||
<path
|
||||
android:pathData="M56,33C49.65,33 44.5,38.15 44.5,44.5V50.48C44.27,50.56 44.04,50.65 43.82,50.76C42.5,51.43 41.43,52.5 40.76,53.82C40.35,54.63 40.17,55.52 40.09,56.58C40,57.62 40,58.91 40,60.56V66.44C40,68.09 40,69.38 40.09,70.42C40.17,71.48 40.35,72.37 40.76,73.18C41.43,74.5 42.5,75.57 43.82,76.24C44.63,76.65 45.52,76.83 46.58,76.91C47.62,77 48.91,77 50.56,77H61.44C63.09,77 64.38,77 65.42,76.91C66.48,76.83 67.37,76.65 68.18,76.24C69.5,75.57 70.57,74.5 71.24,73.18C71.65,72.37 71.83,71.48 71.91,70.42C72,69.38 72,68.09 72,66.44V60.56C72,58.91 72,57.62 71.91,56.58C71.83,55.52 71.65,54.63 71.24,53.82C70.57,52.5 69.5,51.43 68.18,50.76C67.96,50.65 67.73,50.56 67.5,50.48V44.5C67.5,38.15 62.35,33 56,33ZM65.5,50.09V44.5C65.5,39.25 61.25,35 56,35C50.75,35 46.5,39.25 46.5,44.5V50.09C46.53,50.09 46.55,50.09 46.58,50.09C47.62,50 48.91,50 50.56,50H61.44C63.09,50 64.38,50 65.42,50.09C65.45,50.09 65.47,50.09 65.5,50.09ZM44.73,52.54C45.21,52.3 45.8,52.16 46.74,52.08C47.69,52 48.9,52 50.6,52H61.4C63.1,52 64.31,52 65.26,52.08C66.2,52.16 66.79,52.3 67.27,52.54C68.21,53.02 68.98,53.79 69.46,54.73C69.7,55.21 69.84,55.8 69.92,56.74C70,57.69 70,58.9 70,60.6V66.4C70,68.1 70,69.31 69.92,70.26C69.84,71.2 69.7,71.79 69.46,72.27C68.98,73.21 68.21,73.98 67.27,74.46C66.79,74.7 66.2,74.84 65.26,74.92C64.31,75 63.1,75 61.4,75H50.6C48.9,75 47.69,75 46.74,74.92C45.8,74.84 45.21,74.7 44.73,74.46C43.79,73.98 43.02,73.21 42.54,72.27C42.3,71.79 42.16,71.2 42.08,70.26C42,69.31 42,68.1 42,66.4V60.6C42,58.9 42,57.69 42.08,56.74C42.16,55.8 42.3,55.21 42.54,54.73C43.02,53.79 43.79,53.02 44.73,52.54Z"
|
||||
android:fillColor="#020BAC"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M53.25,61.25C53.25,59.73 54.48,58.5 56,58.5C57.52,58.5 58.75,59.73 58.75,61.25C58.75,62.42 58.02,63.41 57,63.81V67.5C57,68.05 56.55,68.5 56,68.5C55.45,68.5 55,68.05 55,67.5V63.81C53.98,63.41 53.25,62.42 53.25,61.25Z"
|
||||
android:fillColor="#020BAC"/>
|
||||
</vector>
|
||||
@@ -249,6 +249,9 @@
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_linkDeviceLearnMoreBottomSheet"
|
||||
app:destination="@id/linkDeviceLearnMoreBottomSheet" />
|
||||
<action
|
||||
android:id="@+id/action_linkDeviceFragment_to_linkDeviceEducationSheet"
|
||||
app:destination="@id/linkDeviceEducationSheet" />
|
||||
</fragment>
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceFinishedSheet"
|
||||
@@ -256,6 +259,9 @@
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceLearnMoreBottomSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceLearnMoreBottomSheetFragment" />
|
||||
<dialog
|
||||
android:id="@+id/linkDeviceEducationSheet"
|
||||
android:name="org.thoughtcrime.securesms.linkdevice.LinkDeviceEducationSheet" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/addLinkDeviceFragment"
|
||||
|
||||
@@ -972,6 +972,12 @@
|
||||
<string name="LinkDeviceFragment__no_linked_devices">No linked devices</string>
|
||||
<!-- Title on biometrics prompt explaining what biometrics are being used for -->
|
||||
<string name="LinkDeviceFragment__unlock_to_link">Unlock to link a device</string>
|
||||
<!-- Title on bottom sheet explaining our usage of biometrics to link a device -->
|
||||
<string name="LinkDeviceFragment__before_linking">Before linking, confirm it\'s you</string>
|
||||
<!-- Body of bottom sheet explaining that users should use their device pin or biometrics and not their Signal pin -->
|
||||
<string name="LinkDeviceFragment__tap_continue_and_enter_phone">Tap continue and enter your phone\'s lock to confirm. Do not enter your Signal PIN.</string>
|
||||
<!-- Button that dismisses the bottom sheet -->
|
||||
<string name="LinkDeviceFragment__continue">Continue</string>
|
||||
|
||||
<!-- AddLinkDeviceFragment -->
|
||||
<!-- Description text shown on the QR code scanner when linking a device -->
|
||||
|
||||
Reference in New Issue
Block a user