Updated on 2026-08-14
This commit is contained in:
parent
019e98b710
commit
e0ae64248d
17 changed files with 417 additions and 144 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<DetailsState> {
|
||||
|
|
@ -24,8 +25,9 @@ class AppSettingsFragment : Fragment(), StoreSubscriber<DetailsState> {
|
|||
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<DetailsState> {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.refreshBiometricsStatus()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
store.unsubscribe(this)
|
||||
|
|
|
|||
|
|
@ -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 = { },
|
||||
)
|
||||
}
|
||||
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
|
||||
|
|
@ -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<PrivacySetting, Boolean>,
|
||||
val enrollBiometricsDialog: EnrollBiometricsDialog?,
|
||||
val onSettingToggled: (PrivacySetting, Boolean) -> Unit,
|
||||
val settings: Map<PrivacySetting, Boolean> = emptyMap(),
|
||||
val showEnrollBiometricsCard: Boolean = false,
|
||||
val isTogglesEnabled: Boolean = true,
|
||||
val onSettingToggled: (PrivacySetting, Boolean) -> Unit = { _, _ -> /* no-op */ },
|
||||
val onEnrollBiometrics: () -> Unit = { /* no-op */ },
|
||||
)
|
||||
|
|
@ -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<AppState>) {
|
|||
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<AppState>) {
|
|||
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))
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -224,4 +224,6 @@
|
|||
<string name="user_wallet_list_editing_count">%d selected</string>
|
||||
<string name="common_biometric_authentication">biometric authentication</string>
|
||||
<string name="common_biometrics">biometrics</string>
|
||||
<string name="app_settings_enable_biometrics_title">Enable biometric authentication</string>
|
||||
<string name="app_settings_enable_biometrics_description">Go to settings to enable biometric authentication in the Tangem App</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -224,4 +224,6 @@
|
|||
<string name="user_wallet_list_editing_count">%d selected</string>
|
||||
<string name="common_biometric_authentication">biometric authentication</string>
|
||||
<string name="common_biometrics">biometrics</string>
|
||||
<string name="app_settings_enable_biometrics_title">Enable biometric authentication</string>
|
||||
<string name="app_settings_enable_biometrics_description">Go to settings to enable biometric authentication in the Tangem App</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -224,4 +224,6 @@
|
|||
<string name="user_wallet_list_editing_count">%d selected</string>
|
||||
<string name="common_biometric_authentication">biometric authentication</string>
|
||||
<string name="common_biometrics">biometrics</string>
|
||||
<string name="app_settings_enable_biometrics_title">Enable biometric authentication</string>
|
||||
<string name="app_settings_enable_biometrics_description">Go to settings to enable biometric authentication in the Tangem App</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -224,4 +224,6 @@
|
|||
<string name="user_wallet_list_editing_count">%d выбрано</string>
|
||||
<string name="common_biometric_authentication">биометрическую аутентификацию</string>
|
||||
<string name="common_biometrics">биометрией</string>
|
||||
<string name="app_settings_enable_biometrics_title">Включите биометрическую аутентификацию</string>
|
||||
<string name="app_settings_enable_biometrics_description">Перейдите в настройки, чтобы включить биометрическую аутентификацию в приложении Tangem App</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -224,4 +224,6 @@
|
|||
<string name="user_wallet_list_editing_count">%d selected</string>
|
||||
<string name="common_biometric_authentication">biometric authentication</string>
|
||||
<string name="common_biometrics">biometrics</string>
|
||||
<string name="app_settings_enable_biometrics_title">Enable biometric authentication</string>
|
||||
<string name="app_settings_enable_biometrics_description">Go to settings to enable biometric authentication in the Tangem App</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
9
core/ui/src/main/res/drawable/ic_alert_circle_24.xml
Normal file
9
core/ui/src/main/res/drawable/ic_alert_circle_24.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M13,13H11V7H13M13,17H11V15H13M12,2C10.687,2 9.386,2.259 8.173,2.761C6.96,3.264 5.858,4 4.929,4.929C3.054,6.804 2,9.348 2,12C2,14.652 3.054,17.196 4.929,19.071C5.858,20 6.96,20.736 8.173,21.239C9.386,21.741 10.687,22 12,22C14.652,22 17.196,20.946 19.071,19.071C20.946,17.196 22,14.652 22,12C22,10.687 21.741,9.386 21.239,8.173C20.736,6.96 20,5.858 19.071,4.929C18.142,4 17.04,3.264 15.827,2.761C14.614,2.259 13.313,2 12,2Z" />
|
||||
</vector>
|
||||
Loading…
Add table
Add a link
Reference in a new issue