From e0ae64248dc6312526221b1fc15f414c7c6777c4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 6 Dec 2022 20:56:19 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/tap/domain/TangemSdkManager.kt | 4 +- .../details/redux/DetailsMiddleware.kt | 36 ++- .../features/details/redux/DetailsReducer.kt | 12 +- .../ui/appsettings/AppSettingsFragment.kt | 13 +- .../ui/appsettings/AppSettingsScreen.kt | 246 ++++++++++-------- .../ui/appsettings/AppSettingsScreenState.kt | 9 +- .../ui/appsettings/AppSettingsViewModel.kt | 26 +- .../components/EnrollBiometricsCard.kt | 92 +++++++ .../components/SettingsAlertDialog.kt | 101 +++++++ .../saveWallet/redux/SaveWalletMiddleware.kt | 2 +- .../src/main/res/values-de/strings_final.xml | 2 + .../src/main/res/values-fr/strings_final.xml | 2 + .../src/main/res/values-it/strings_final.xml | 2 + .../src/main/res/values-ru/strings_final.xml | 2 + .../res/src/main/res/values/strings_final.xml | 2 + .../com/tangem/core/ui/res/TangemDimens.kt | 1 + .../main/res/drawable/ic_alert_circle_24.xml | 9 + 17 files changed, 417 insertions(+), 144 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt create mode 100644 app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt create mode 100644 core/ui/src/main/res/drawable/ic_alert_circle_24.xml diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index a1b2dc8e1c..906a0f1306 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -48,9 +48,9 @@ import kotlin.coroutines.suspendCoroutine class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Context) { val canUseBiometry: Boolean - get() = tangemSdk.biometricManager.canAuthenticate || canEnrollBiometrics + get() = tangemSdk.biometricManager.canAuthenticate || needEnrollBiometrics - val canEnrollBiometrics: Boolean + val needEnrollBiometrics: Boolean get() = tangemSdk.biometricManager.canEnrollBiometrics val biometricManager: BiometricManager diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 297cb3d6e3..70751b615f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -30,6 +30,7 @@ import com.tangem.tap.userWalletsListManager import com.tangem.tap.walletStoresManager import com.tangem.wallet.R import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.rekotlin.Action @@ -194,18 +195,39 @@ class DetailsMiddleware { fun handle(state: DetailsState, action: DetailsAction.AppSettings) { when (action) { is DetailsAction.AppSettings.SwitchPrivacySetting -> { - if (tangemSdkManager.canEnrollBiometrics) { - store.dispatch(DetailsAction.AppSettings.EnrollBiometrics) - } when (action.setting) { PrivacySetting.SaveWallets -> toggleSaveWallets(state, enable = action.enable) PrivacySetting.SaveAccessCode -> toggleSaveAccessCodes(state, enable = action.enable) } } - is DetailsAction.AppSettings.SwitchPrivacySetting.Success -> Unit - is DetailsAction.AppSettings.EnrollBiometrics -> Unit - is DetailsAction.AppSettings.EnrollBiometrics.Enroll -> enrollBiometrics() - is DetailsAction.AppSettings.EnrollBiometrics.Cancel -> Unit + is DetailsAction.AppSettings.CheckBiometricsStatus -> { + checkBiometricsStatus(action.awaitStatusChange, state) + } + is DetailsAction.AppSettings.EnrollBiometrics -> { + enrollBiometrics() + } + is DetailsAction.AppSettings.SwitchPrivacySetting.Success, + is DetailsAction.AppSettings.BiometricsStatusChanged, + -> Unit + } + } + + /** + * @param awaitStatusChange If true then start a new coroutine and check the biometric status every 100 + * milliseconds until it changes + * */ + private fun checkBiometricsStatus(awaitStatusChange: Boolean, state: DetailsState) { + scope.launch { + if (awaitStatusChange) { + while (state.needEnrollBiometrics == tangemSdkManager.needEnrollBiometrics) { + delay(timeMillis = 100) + } + } + store.dispatchOnMain( + DetailsAction.AppSettings.BiometricsStatusChanged( + needEnrollBiometrics = tangemSdkManager.needEnrollBiometrics, + ), + ) } } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 28d1b87cb8..f00f0b46b4 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -157,15 +157,17 @@ private fun handlePrivacyAction( state: DetailsState, ): DetailsState { return when (action) { - is DetailsAction.AppSettings.SwitchPrivacySetting -> state is DetailsAction.AppSettings.SwitchPrivacySetting.Success -> when (action.setting) { PrivacySetting.SaveWallets -> state.copy(saveWallets = action.enable) PrivacySetting.SaveAccessCode -> state.copy(saveAccessCodes = action.enable) } - is DetailsAction.AppSettings.EnrollBiometrics -> state.copy(needEnrollBiometrics = true) - is DetailsAction.AppSettings.EnrollBiometrics.Enroll, - is DetailsAction.AppSettings.EnrollBiometrics.Cancel, - -> state.copy(needEnrollBiometrics = false) + is DetailsAction.AppSettings.BiometricsStatusChanged -> state.copy( + needEnrollBiometrics = action.needEnrollBiometrics, + ) + is DetailsAction.AppSettings.SwitchPrivacySetting, + is DetailsAction.AppSettings.EnrollBiometrics, + is DetailsAction.AppSettings.CheckBiometricsStatus, + -> state } } diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt index 9e311ef003..25a6cd0902 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsFragment.kt @@ -9,11 +9,12 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment import androidx.transition.TransitionInflater -import com.google.accompanist.appcompattheme.AppCompatTheme +import com.tangem.core.ui.res.TangemTheme import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.details.redux.DetailsAction import com.tangem.tap.features.details.redux.DetailsState import com.tangem.tap.store +import com.tangem.wallet.R import org.rekotlin.StoreSubscriber class AppSettingsFragment : Fragment(), StoreSubscriber { @@ -24,8 +25,9 @@ class AppSettingsFragment : Fragment(), StoreSubscriber { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val inflater = TransitionInflater.from(requireContext()) - enterTransition = inflater.inflateTransition(android.R.transition.fade) - exitTransition = inflater.inflateTransition(android.R.transition.fade) + enterTransition = inflater.inflateTransition(R.transition.fade) + exitTransition = inflater.inflateTransition(R.transition.fade) + viewModel.checkBiometricsStatus() } override fun onCreateView( @@ -58,6 +60,11 @@ class AppSettingsFragment : Fragment(), StoreSubscriber { } } + override fun onResume() { + super.onResume() + viewModel.refreshBiometricsStatus() + } + override fun onStop() { super.onStop() store.unsubscribe(this) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt index afdd0de6e1..b072be7b74 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt @@ -1,24 +1,31 @@ package com.tangem.tap.features.details.ui.appsettings -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.CornerSize -import androidx.compose.material.AlertDialog -import androidx.compose.material.MaterialTheme +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.material.Text -import androidx.compose.material.TextButton -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.tangem.core.ui.components.dialogs.EnrollBiometricsDialogContent -import com.tangem.core.ui.models.EnrollBiometricsDialog -import com.tangem.tap.common.compose.TangemTypography +import com.tangem.core.ui.components.SpacerH24 +import com.tangem.core.ui.components.SpacerH32 +import com.tangem.core.ui.components.SpacerH4 +import com.tangem.core.ui.components.SpacerW32 +import com.tangem.core.ui.res.TangemTheme import com.tangem.tap.features.details.redux.PrivacySetting +import com.tangem.tap.features.details.ui.appsettings.components.EnrollBiometricsCard +import com.tangem.tap.features.details.ui.appsettings.components.SettingsAlertDialog import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold import com.tangem.tap.features.details.ui.common.TangemSwitch import com.tangem.wallet.R @@ -51,47 +58,43 @@ private fun AppSettings( element = it, onDialogStateChange = onDialogStateChange, onSettingToggled = state.onSettingToggled, - modifier = modifier, ) } - EnrollBiometricsDialog(dialog = state.enrollBiometricsDialog) - Column( modifier = modifier .fillMaxSize(), ) { + if (state.showEnrollBiometricsCard) { + EnrollBiometricsCard( + modifier = Modifier + .padding(horizontal = TangemTheme.dimens.spacing8) + .fillMaxWidth(), + onClick = state.onEnrollBiometrics, + ) + SpacerH24() + } + AppSettingsElement( state = state, setting = PrivacySetting.SaveWallets, onDialogStateChange = onDialogStateChange, - modifier = modifier, ) - Spacer(modifier = Modifier.size(32.dp)) + SpacerH32() AppSettingsElement( state = state, setting = PrivacySetting.SaveAccessCode, onDialogStateChange = onDialogStateChange, - modifier = modifier, ) } } -@Composable -private fun EnrollBiometricsDialog( - modifier: Modifier = Modifier, - dialog: EnrollBiometricsDialog?, -) { - if (dialog == null) return - EnrollBiometricsDialogContent(modifier, dialog) -} - @Composable private fun AppSettingsElement( + modifier: Modifier = Modifier, state: AppSettingsScreenState, setting: PrivacySetting, onDialogStateChange: (PrivacySetting?) -> Unit, - modifier: Modifier = Modifier, ) { val titleRes = when (setting) { PrivacySetting.SaveWallets -> R.string.app_settings_saved_wallet @@ -103,48 +106,63 @@ private fun AppSettingsElement( } val checked = state.settings[setting] ?: false + val titleTextColor by rememberUpdatedState( + newValue = if (state.isTogglesEnabled) { + TangemTheme.colors.text.primary1 + } else { + TangemTheme.colors.text.secondary + }, + ) + val descriptionTextColor by rememberUpdatedState( + newValue = if (state.isTogglesEnabled) { + TangemTheme.colors.text.secondary + } else { + TangemTheme.colors.text.tertiary + }, + ) + Row( modifier = modifier .fillMaxWidth() - .padding(start = 20.dp), + .padding(horizontal = TangemTheme.dimens.spacing20), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, ) { Column( + modifier = Modifier.weight(weight = .9f), verticalArrangement = Arrangement.Center, - modifier = modifier - .weight(0.6f) - .padding(end = 4.dp), ) { Text( text = stringResource(id = titleRes), - style = TangemTypography.subtitle1, - color = colorResource(id = R.color.text_primary_1), + style = TangemTheme.typography.subtitle1, + color = titleTextColor, ) - Spacer(modifier = Modifier.size(4.dp)) + SpacerH4() Text( text = stringResource(id = subtitleRes), - style = TangemTypography.body2, - color = colorResource(id = R.color.text_secondary), + style = TangemTheme.typography.body2, + color = descriptionTextColor, ) } + SpacerW32() TangemSwitch( checked = checked, - onCheckedChange = { + enabled = state.isTogglesEnabled, + onCheckedChange = { isChecked -> onCheckedChange( element = setting, - enabled = it, + enabled = isChecked, onSettingToggled = state.onSettingToggled, onDialogStateChange = onDialogStateChange, ) }, - modifier = modifier - .padding(20.dp), ) } } private fun onCheckedChange( - element: PrivacySetting, enabled: Boolean, + element: PrivacySetting, + enabled: Boolean, onSettingToggled: (PrivacySetting, Boolean) -> Unit, onDialogStateChange: (PrivacySetting?) -> Unit, ) { @@ -152,82 +170,88 @@ private fun onCheckedChange( if (!enabled) { onDialogStateChange(element) } else { - onSettingToggled(element, enabled) + onSettingToggled(element, true) } } +// region Preview @Composable -private fun SettingsAlertDialog( - element: PrivacySetting, - onDialogStateChange: (PrivacySetting?) -> Unit, - onSettingToggled: (PrivacySetting, Boolean) -> Unit, +private fun AppSettingsScreenSample( modifier: Modifier = Modifier, ) { - val text = when (element) { - PrivacySetting.SaveWallets -> R.string.app_settings_off_saved_wallet_alert_message - PrivacySetting.SaveAccessCode -> R.string.app_settings_off_saved_access_code_alert_message + Column( + modifier = modifier + .background(TangemTheme.colors.background.primary), + ) { + AppSettingsScreen( + state = AppSettingsScreenState( + settings = mapOf( + PrivacySetting.SaveWallets to true, + PrivacySetting.SaveAccessCode to false, + ), + showEnrollBiometricsCard = false, + isTogglesEnabled = true, + onSettingToggled = { _, _ -> }, + onEnrollBiometrics = {}, + ), + onBackPressed = { }, + ) } - AlertDialog( - onDismissRequest = { onDialogStateChange(null) }, - confirmButton = { - TextButton( - onClick = { - onDialogStateChange(null) - }, - ) { - Text( - text = stringResource(id = R.string.common_cancel), - color = colorResource(id = R.color.text_secondary), - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - ) - } - }, - dismissButton = { - TextButton( - onClick = { - onDialogStateChange(null) - onSettingToggled(element, false) - }, - modifier = modifier.padding(bottom = 14.dp), - ) { - Text( - text = stringResource(id = R.string.common_delete), - color = colorResource(id = R.color.text_warning), - fontSize = 14.sp, - fontWeight = FontWeight.Medium, - ) - } - }, - title = { - Text( - text = stringResource(id = R.string.common_attention), - color = colorResource(id = R.color.text_primary_1), - ) - }, - text = { - Text( - text = stringResource(id = text), - color = colorResource(id = R.color.text_secondary), - ) - }, - shape = MaterialTheme.shapes.medium.copy(all = CornerSize(size = 28.dp)), - modifier = modifier.padding(vertical = 34.dp, horizontal = 24.dp), - ) } -@Preview +@Preview(showBackground = true, widthDp = 360) @Composable -fun AppSettingsScreenPreview() { - AppSettingsScreen( - state = AppSettingsScreenState( - settings = mapOf( - PrivacySetting.SaveWallets to true, - PrivacySetting.SaveAccessCode to false, +private fun AppSettingsScreenPreview_Light() { + TangemTheme { + AppSettingsScreenSample() + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun AppSettingsScreenPreview_Dark() { + TangemTheme(isDark = true) { + AppSettingsScreenSample() + } +} + +@Composable +private fun AppSettingsScreen_EnrollBiometrics_Sample( + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .background(TangemTheme.colors.background.primary), + ) { + AppSettingsScreen( + state = AppSettingsScreenState( + settings = mapOf( + PrivacySetting.SaveWallets to true, + PrivacySetting.SaveAccessCode to false, + ), + showEnrollBiometricsCard = true, + isTogglesEnabled = false, + onSettingToggled = { _, _ -> }, + onEnrollBiometrics = {}, ), - onSettingToggled = { _, _ -> }, - enrollBiometricsDialog = null, - ), - onBackPressed = { }, - ) -} \ No newline at end of file + onBackPressed = { }, + ) + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun AppSettingsScreen_EnrollBiometrics_Preview_Light() { + TangemTheme { + AppSettingsScreen_EnrollBiometrics_Sample() + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun AppSettingsScreen_EnrollBiometrics_Preview_Dark() { + TangemTheme(isDark = true) { + AppSettingsScreen_EnrollBiometrics_Sample() + } +} +// endregion Preview \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreenState.kt index 1e4c1abeee..615a0a167d 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreenState.kt @@ -1,10 +1,11 @@ package com.tangem.tap.features.details.ui.appsettings -import com.tangem.core.ui.models.EnrollBiometricsDialog import com.tangem.tap.features.details.redux.PrivacySetting data class AppSettingsScreenState( - val settings: Map, - val enrollBiometricsDialog: EnrollBiometricsDialog?, - val onSettingToggled: (PrivacySetting, Boolean) -> Unit, + val settings: Map = emptyMap(), + val showEnrollBiometricsCard: Boolean = false, + val isTogglesEnabled: Boolean = true, + val onSettingToggled: (PrivacySetting, Boolean) -> Unit = { _, _ -> /* no-op */ }, + val onEnrollBiometrics: () -> Unit = { /* no-op */ }, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt index 16a6ebdbba..802435f578 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsViewModel.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.details.ui.appsettings -import com.tangem.core.ui.models.EnrollBiometricsDialog import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.details.redux.DetailsAction @@ -20,8 +19,14 @@ class AppSettingsViewModel(private val store: Store) { PrivacySetting.SaveWallets to state.saveWallets, PrivacySetting.SaveAccessCode to state.saveAccessCodes, ), - enrollBiometricsDialog = if (state.needEnrollBiometrics) createEnrollBiometricsDialog() else null, - onSettingToggled = { privacySetting, enabled -> onSettingsToggled(privacySetting, enabled) }, + showEnrollBiometricsCard = state.needEnrollBiometrics, + isTogglesEnabled = !state.needEnrollBiometrics, + onSettingToggled = { privacySetting, enabled -> + onSettingsToggled(privacySetting, enabled) + }, + onEnrollBiometrics = { + store.dispatchOnMain(DetailsAction.AppSettings.EnrollBiometrics) + }, ) } @@ -29,12 +34,11 @@ class AppSettingsViewModel(private val store: Store) { store.dispatch(DetailsAction.AppSettings.SwitchPrivacySetting(enable = enable, setting = setting)) } - private fun createEnrollBiometricsDialog() = EnrollBiometricsDialog( - onCancel = { - store.dispatchOnMain(DetailsAction.AppSettings.EnrollBiometrics.Cancel) - }, - onEnroll = { - store.dispatchOnMain(DetailsAction.AppSettings.EnrollBiometrics.Enroll) - }, - ) + fun checkBiometricsStatus() { + store.dispatch(DetailsAction.AppSettings.CheckBiometricsStatus(awaitStatusChange = false)) + } + + fun refreshBiometricsStatus() { + store.dispatch(DetailsAction.AppSettings.CheckBiometricsStatus(awaitStatusChange = true)) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt new file mode 100644 index 0000000000..fddc2b0e7b --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/EnrollBiometricsCard.kt @@ -0,0 +1,92 @@ +package com.tangem.tap.features.details.ui.appsettings.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.Icon +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.SpacerH4 +import com.tangem.core.ui.components.SpacerW16 +import com.tangem.core.ui.res.TangemTheme +import com.tangem.wallet.R + +@OptIn(ExperimentalMaterialApi::class) +@Composable +internal fun EnrollBiometricsCard( + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + Surface( + modifier = modifier, + color = TangemTheme.colors.background.primary, + shape = TangemTheme.shapes.roundedCornersLarge, + onClick = onClick, + ) { + Row( + modifier = Modifier.padding(all = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceEvenly, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_alert_circle_24), + tint = TangemTheme.colors.icon.attention, + contentDescription = null, + ) + SpacerW16() + Column { + Text( + text = stringResource(id = R.string.app_settings_enable_biometrics_title), + style = TangemTheme.typography.subtitle1, + color = TangemTheme.colors.text.primary1, + ) + SpacerH4() + Text( + text = stringResource(id = R.string.app_settings_enable_biometrics_description), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.secondary, + ) + } + } + } +} + +// region Preview +@Composable +private fun EnrollBiometricsCardSample( + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .background(TangemTheme.colors.background.secondary), + ) { + EnrollBiometricsCard(onClick = {}) + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun EnrollBiometricsCardPreview_Light() { + TangemTheme { + EnrollBiometricsCardSample() + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun EnrollBiometricsCardPreview_Dark() { + TangemTheme(isDark = true) { + EnrollBiometricsCardSample() + } +} +// endregion Preview \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt new file mode 100644 index 0000000000..65514a2f86 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/components/SettingsAlertDialog.kt @@ -0,0 +1,101 @@ +package com.tangem.tap.features.details.ui.appsettings.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.AlertDialog +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.TextButton +import com.tangem.core.ui.components.WarningTextButton +import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.features.details.redux.PrivacySetting +import com.tangem.wallet.R + +@Composable +internal fun SettingsAlertDialog( + element: PrivacySetting, + onDialogStateChange: (PrivacySetting?) -> Unit, + onSettingToggled: (PrivacySetting, Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + val text = when (element) { + PrivacySetting.SaveWallets -> R.string.app_settings_off_saved_wallet_alert_message + PrivacySetting.SaveAccessCode -> R.string.app_settings_off_saved_access_code_alert_message + } + + AlertDialog( + onDismissRequest = { onDialogStateChange(null) }, + confirmButton = { + TextButton( + modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12), + text = stringResource(id = R.string.common_cancel), + onClick = { + onDialogStateChange(null) + }, + ) + }, + dismissButton = { + WarningTextButton( + text = stringResource(id = R.string.common_delete), + onClick = { + onDialogStateChange(null) + onSettingToggled(element, false) + }, + ) + }, + title = { + Text( + text = stringResource(id = R.string.common_attention), + color = TangemTheme.colors.text.primary1, + style = TangemTheme.typography.h2, + ) + }, + text = { + Text( + text = stringResource(id = text), + color = TangemTheme.colors.text.secondary, + style = TangemTheme.typography.body2, + ) + }, + shape = TangemTheme.shapes.roundedCornersLarge, + modifier = modifier, + ) +} + +// region Preview +@Composable +private fun SettingsAlertDialogSample( + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier + .background(TangemTheme.colors.background.primary), + ) { + SettingsAlertDialog( + element = PrivacySetting.SaveAccessCode, + onDialogStateChange = {}, + onSettingToggled = { _, _ -> }, + ) + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun SettingsAlertDialogPreview_Light() { + TangemTheme { + SettingsAlertDialogSample() + } +} + +@Preview(showBackground = true, widthDp = 360) +@Composable +private fun SettingsAlertDialogPreview_Dark() { + TangemTheme(isDark = true) { + SettingsAlertDialogSample() + } +} +// endregion Preview \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt index d4717299e0..bd8b4d0459 100644 --- a/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/saveWallet/redux/SaveWalletMiddleware.kt @@ -52,7 +52,7 @@ internal class SaveWalletMiddleware { } private fun saveWalletIfBiometricsEnrolled(state: SaveWalletState) { - if (tangemSdkManager.canEnrollBiometrics) { + if (tangemSdkManager.needEnrollBiometrics) { store.dispatchOnMain(SaveWalletAction.EnrollBiometrics) } else { saveWallet(state) diff --git a/core/res/src/main/res/values-de/strings_final.xml b/core/res/src/main/res/values-de/strings_final.xml index 5e5e0bc90b..e3c0beeaa6 100644 --- a/core/res/src/main/res/values-de/strings_final.xml +++ b/core/res/src/main/res/values-de/strings_final.xml @@ -224,4 +224,6 @@ %d selected biometric authentication biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App diff --git a/core/res/src/main/res/values-fr/strings_final.xml b/core/res/src/main/res/values-fr/strings_final.xml index fdba526339..431975c183 100644 --- a/core/res/src/main/res/values-fr/strings_final.xml +++ b/core/res/src/main/res/values-fr/strings_final.xml @@ -224,4 +224,6 @@ %d selected biometric authentication biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App diff --git a/core/res/src/main/res/values-it/strings_final.xml b/core/res/src/main/res/values-it/strings_final.xml index b812e23de8..edf533dbe1 100644 --- a/core/res/src/main/res/values-it/strings_final.xml +++ b/core/res/src/main/res/values-it/strings_final.xml @@ -224,4 +224,6 @@ %d selected biometric authentication biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App diff --git a/core/res/src/main/res/values-ru/strings_final.xml b/core/res/src/main/res/values-ru/strings_final.xml index d8a604f287..dabccca8cd 100644 --- a/core/res/src/main/res/values-ru/strings_final.xml +++ b/core/res/src/main/res/values-ru/strings_final.xml @@ -224,4 +224,6 @@ %d выбрано биометрическую аутентификацию биометрией + Включите биометрическую аутентификацию + Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem App diff --git a/core/res/src/main/res/values/strings_final.xml b/core/res/src/main/res/values/strings_final.xml index c7b9866169..55f6540953 100644 --- a/core/res/src/main/res/values/strings_final.xml +++ b/core/res/src/main/res/values/strings_final.xml @@ -224,4 +224,6 @@ %d selected biometric authentication biometrics + Enable biometric authentication + Go to settings to enable biometric authentication in the Tangem App diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt index 0febb1a8af..38321bcba1 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/res/TangemDimens.kt @@ -59,6 +59,7 @@ data class TangemDimens internal constructor( val spacing12: Dp = 12.dp, val spacing14: Dp = 14.dp, val spacing16: Dp = 16.dp, + val spacing20: Dp = 20.dp, val spacing24: Dp = 24.dp, val spacing32: Dp = 32.dp, val spacing34: Dp = 34.dp, diff --git a/core/ui/src/main/res/drawable/ic_alert_circle_24.xml b/core/ui/src/main/res/drawable/ic_alert_circle_24.xml new file mode 100644 index 0000000000..278bfde255 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_alert_circle_24.xml @@ -0,0 +1,9 @@ + + +