Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-05 10:00:14 +03:00
parent 5dd09c485a
commit 5a169e6211
10 changed files with 513 additions and 318 deletions

View file

@ -0,0 +1,28 @@
package com.tangem.tap.features.details.ui.appsettings
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Alert
import com.tangem.wallet.R
internal class AppSettingsAlertsFactory {
fun createDeleteSavedWalletsAlert(onDelete: () -> Unit, onDismiss: () -> Unit): Alert {
return Alert(
title = resourceReference(R.string.common_attention),
description = resourceReference(R.string.app_settings_off_saved_wallet_alert_message),
confirmText = resourceReference(R.string.common_delete),
onConfirm = onDelete,
onDismiss = onDismiss,
)
}
fun createDeleteSavedAccessCodesAlert(onDelete: () -> Unit, onDismiss: () -> Unit): Alert {
return Alert(
title = resourceReference(R.string.common_attention),
description = resourceReference(R.string.app_settings_off_saved_access_code_alert_message),
confirmText = resourceReference(R.string.common_delete),
onConfirm = onDelete,
onDismiss = onDismiss,
)
}
}

View file

@ -2,8 +2,6 @@ package com.tangem.tap.features.details.ui.appsettings
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.navigation.NavigationAction
@ -24,14 +22,12 @@ internal class AppSettingsFragment : ComposeFragment(), StoreSubscriber<DetailsS
override lateinit var appThemeModeHolder: AppThemeModeHolder
private val viewModel = AppSettingsViewModel(store)
private var screenState: MutableState<AppSettingsScreenState> =
mutableStateOf(viewModel.updateState(store.state.detailsState))
@Composable
override fun ScreenContent(modifier: Modifier) {
AppSettingsScreen(
modifier = modifier,
state = screenState.value,
state = viewModel.uiState,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
@ -73,6 +69,6 @@ internal class AppSettingsFragment : ComposeFragment(), StoreSubscriber<DetailsS
override fun newState(state: DetailsState) {
if (activity == null || view == null) return
screenState.value = viewModel.updateState(state)
viewModel.updateState(state)
}
}

View file

@ -0,0 +1,48 @@
package com.tangem.tap.features.details.ui.appsettings
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
import com.tangem.wallet.R
internal class AppSettingsItemsFactory {
fun createEnrollBiometricsCard(onClick: () -> Unit): Item.Card {
return Item.Card(
id = "enroll_biometrics_card",
title = resourceReference(R.string.app_settings_enable_biometrics_title),
description = resourceReference(R.string.app_settings_enable_biometrics_description),
iconResId = R.drawable.ic_alert_circle_24,
onClick = onClick,
)
}
fun createSaveWalletsSwitch(
isChecked: Boolean,
isEnabled: Boolean,
onCheckedChange: (Boolean) -> Unit,
): Item.Switch {
return Item.Switch(
id = "save_wallets_switch",
title = resourceReference(R.string.app_settings_saved_wallet),
description = resourceReference(R.string.app_settings_saved_wallet_footer),
isEnabled = isEnabled,
isChecked = isChecked,
onCheckedChange = onCheckedChange,
)
}
fun createSaveAccessCodeSwitch(
isChecked: Boolean,
isEnabled: Boolean,
onCheckedChange: (Boolean) -> Unit,
): Item.Switch {
return Item.Switch(
id = "save_access_codes_switch",
title = resourceReference(R.string.app_settings_saved_access_codes),
description = resourceReference(R.string.app_settings_saved_access_codes_footer),
isEnabled = isEnabled,
isChecked = isChecked,
onCheckedChange = onCheckedChange,
)
}
}

View file

@ -1,224 +1,113 @@
package com.tangem.tap.features.details.ui.appsettings
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
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 androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.redux.AppSetting
import com.tangem.tap.features.details.ui.appsettings.components.EnrollBiometricsCard
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
import com.tangem.tap.features.details.ui.appsettings.components.CardItem
import com.tangem.tap.features.details.ui.appsettings.components.SettingsAlertDialog
import com.tangem.tap.features.details.ui.appsettings.components.SwitchItem
import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
import com.tangem.tap.features.details.ui.common.TangemSwitch
import com.tangem.wallet.R
import kotlinx.collections.immutable.persistentListOf
@Composable
internal fun AppSettingsScreen(state: AppSettingsScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
SettingsScreensScaffold(
modifier = modifier,
content = { AppSettings(state = state) },
content = {
when (state) {
is AppSettingsScreenState.Content -> AppSettings(state = state)
is AppSettingsScreenState.Loading -> Unit
}
},
titleRes = R.string.app_settings_title,
onBackClick = onBackClick,
)
}
@Composable
private fun AppSettings(state: AppSettingsScreenState) {
var dialogType by remember { mutableStateOf<AppSetting?>(null) }
val onDialogStateChange: (AppSetting?) -> Unit = { dialogType = it }
dialogType?.let {
SettingsAlertDialog(
element = it,
onDialogStateChange = onDialogStateChange,
onSettingToggle = { state.onSettingToggled(it, false) },
)
private fun AppSettings(state: AppSettingsScreenState.Content) {
val alert by rememberUpdatedState(newValue = state.alert)
alert?.let { safeAlert ->
SettingsAlertDialog(alert = safeAlert)
}
Column(modifier = Modifier.fillMaxSize()) {
if (state.showEnrollBiometricsCard) {
EnrollBiometricsCard(onClick = state.onEnrollBiometrics)
SpacerH24()
}
AppSettingsElement(
state = state,
setting = AppSetting.SaveWallets,
onDialogStateChange = onDialogStateChange,
)
SpacerH32()
AppSettingsElement(
state = state,
setting = AppSetting.SaveAccessCode,
onDialogStateChange = onDialogStateChange,
)
}
}
@Suppress("LongMethod")
@Composable
private fun AppSettingsElement(
state: AppSettingsScreenState,
setting: AppSetting,
onDialogStateChange: (AppSetting?) -> Unit,
) {
val titleRes = when (setting) {
AppSetting.SaveWallets -> R.string.app_settings_saved_wallet
AppSetting.SaveAccessCode -> R.string.app_settings_saved_access_codes
}
val subtitleRes = when (setting) {
AppSetting.SaveWallets -> R.string.app_settings_saved_wallet_footer
AppSetting.SaveAccessCode -> R.string.app_settings_saved_access_codes_footer
}
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(horizontal = TangemTheme.dimens.spacing20),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Column(
modifier = Modifier.weight(weight = .9f),
verticalArrangement = Arrangement.Center,
) {
Text(
text = stringResource(id = titleRes),
style = TangemTheme.typography.subtitle1,
color = titleTextColor,
)
SpacerH4()
Text(
text = stringResource(id = subtitleRes),
style = TangemTheme.typography.body2,
color = descriptionTextColor,
)
}
SpacerW32()
TangemSwitch(
checked = checked,
enabled = state.isTogglesEnabled,
onCheckedChange = { isChecked ->
onCheckedChange(
element = setting,
enabled = isChecked,
onSettingToggled = state.onSettingToggled,
onDialogStateChange = onDialogStateChange,
LazyColumn {
items(
items = state.items,
key = Item::id,
) { item ->
when (item) {
is Item.Card -> CardItem(
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing16),
item = item,
)
},
)
}
}
private fun onCheckedChange(
element: AppSetting,
enabled: Boolean,
onSettingToggled: (AppSetting, Boolean) -> Unit,
onDialogStateChange: (AppSetting?) -> Unit,
) {
// Show warning if user wants to disable the switch
if (!enabled) {
onDialogStateChange(element)
} else {
onSettingToggled(element, true)
is Item.Switch -> SwitchItem(
modifier = Modifier.padding(
vertical = TangemTheme.dimens.spacing16,
horizontal = TangemTheme.dimens.spacing20,
),
item = item,
)
}
}
}
}
// region Preview
@Composable
private fun AppSettingsScreenSample(modifier: Modifier = Modifier) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary),
) {
AppSettingsScreen(
state = AppSettingsScreenState(
settings = mapOf(
AppSetting.SaveWallets to true,
AppSetting.SaveAccessCode to false,
),
showEnrollBiometricsCard = false,
isTogglesEnabled = true,
onSettingToggled = { _, _ -> },
onEnrollBiometrics = {},
),
onBackClick = { },
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun AppSettingsScreenPreview_Light() {
private fun AppSettingsScreenPreview_Light(
@PreviewParameter(AppSettingsScreenStateProvider::class) state: AppSettingsScreenState,
) {
TangemTheme {
AppSettingsScreenSample()
AppSettingsScreen(state = state, onBackClick = {})
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun AppSettingsScreenPreview_Dark() {
private fun AppSettingsScreenPreview_Dark(
@PreviewParameter(AppSettingsScreenStateProvider::class) state: AppSettingsScreenState,
) {
TangemTheme(isDark = true) {
AppSettingsScreenSample()
AppSettingsScreen(state = state, onBackClick = {})
}
}
@Composable
private fun AppSettingsScreen_EnrollBiometrics_Sample(modifier: Modifier = Modifier) {
Column(modifier = modifier.background(TangemTheme.colors.background.primary)) {
AppSettingsScreen(
state = AppSettingsScreenState(
settings = mapOf(
AppSetting.SaveWallets to true,
AppSetting.SaveAccessCode to false,
),
showEnrollBiometricsCard = true,
isTogglesEnabled = false,
onSettingToggled = { _, _ -> },
onEnrollBiometrics = {},
),
onBackClick = { },
private class AppSettingsScreenStateProvider : CollectionPreviewParameterProvider<AppSettingsScreenState>(
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
val dialogsFactory = AppSettingsAlertsFactory()
val items = persistentListOf(
itemsFactory.createEnrollBiometricsCard {},
itemsFactory.createSaveWalletsSwitch(isChecked = true, isEnabled = true, { _ -> }),
itemsFactory.createSaveAccessCodeSwitch(isChecked = false, isEnabled = true) { _ -> },
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun AppSettingsScreen_EnrollBiometrics_Preview_Light() {
TangemTheme {
AppSettingsScreen_EnrollBiometrics_Sample()
}
}
AppSettingsScreenState.Content(
items = items,
alert = null,
).let(::add)
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun AppSettingsScreen_EnrollBiometrics_Preview_Dark() {
TangemTheme(isDark = true) {
AppSettingsScreen_EnrollBiometrics_Sample()
}
}
AppSettingsScreenState.Content(
items = items,
alert = dialogsFactory.createDeleteSavedWalletsAlert({}, {}),
).let(::add)
AppSettingsScreenState.Content(
items = items,
alert = dialogsFactory.createDeleteSavedAccessCodesAlert({}, {}),
).let(::add)
},
)
// endregion Preview

View file

@ -1,11 +1,48 @@
package com.tangem.tap.features.details.ui.appsettings
import com.tangem.tap.features.details.redux.AppSetting
import androidx.annotation.DrawableRes
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.extensions.TextReference
import kotlinx.collections.immutable.ImmutableList
internal data class AppSettingsScreenState(
val settings: Map<AppSetting, Boolean> = emptyMap(),
val showEnrollBiometricsCard: Boolean = false,
val isTogglesEnabled: Boolean = false,
val onSettingToggled: (AppSetting, Boolean) -> Unit = { _, _ -> /* no-op */ },
val onEnrollBiometrics: () -> Unit = { /* no-op */ },
)
@Immutable
internal sealed class AppSettingsScreenState {
object Loading : AppSettingsScreenState()
data class Content(
val items: ImmutableList<Item>,
val alert: Alert?,
) : AppSettingsScreenState()
@Immutable
sealed class Item {
abstract val id: String
data class Card(
override val id: String,
@DrawableRes val iconResId: Int,
val title: TextReference,
val description: TextReference,
val onClick: () -> Unit,
) : Item()
data class Switch(
override val id: String,
val title: TextReference,
val description: TextReference,
val isEnabled: Boolean,
val isChecked: Boolean,
val onCheckedChange: (Boolean) -> Unit,
) : Item()
}
data class Alert(
val title: TextReference,
val description: TextReference,
val confirmText: TextReference,
val onConfirm: () -> Unit,
val onDismiss: () -> Unit,
)
}

View file

@ -1,35 +1,31 @@
package com.tangem.tap.features.details.ui.appsettings
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.details.redux.AppSetting
import com.tangem.tap.features.details.redux.AppSettingsState
import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.features.details.redux.DetailsState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import org.rekotlin.Store
internal class AppSettingsViewModel(private val store: Store<AppState>) {
fun updateState(state: DetailsState): AppSettingsScreenState {
return with(state.appSettingsState) {
AppSettingsScreenState(
settings = mapOf(
AppSetting.SaveWallets to saveWallets,
AppSetting.SaveAccessCode to saveAccessCodes,
),
showEnrollBiometricsCard = needEnrollBiometrics,
isTogglesEnabled = !needEnrollBiometrics && !isInProgress,
onSettingToggled = { privacySetting, enabled ->
onSettingsToggled(privacySetting, enabled)
},
onEnrollBiometrics = {
store.dispatchOnMain(DetailsAction.AppSettings.EnrollBiometrics)
},
)
}
}
private val itemsFactory = AppSettingsItemsFactory()
private val alertsFactory = AppSettingsAlertsFactory()
private fun onSettingsToggled(setting: AppSetting, enable: Boolean) {
store.dispatch(DetailsAction.AppSettings.SwitchPrivacySetting(enable = enable, setting = setting))
var uiState: AppSettingsScreenState by mutableStateOf(AppSettingsScreenState.Loading)
private set
fun updateState(state: DetailsState) {
uiState = AppSettingsScreenState.Content(
items = buildItems(state.appSettingsState),
alert = (uiState as? AppSettingsScreenState.Content)?.alert,
)
}
fun checkBiometricsStatus() {
@ -39,4 +35,85 @@ internal class AppSettingsViewModel(private val store: Store<AppState>) {
fun refreshBiometricsStatus() {
store.dispatch(DetailsAction.AppSettings.CheckBiometricsStatus(awaitStatusChange = true))
}
private fun buildItems(state: AppSettingsState): ImmutableList<AppSettingsScreenState.Item> {
val items = buildList {
if (state.needEnrollBiometrics) {
itemsFactory.createEnrollBiometricsCard(onClick = ::enrollBiometrics).let(::add)
}
if (state.isBiometricsAvailable) {
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
itemsFactory.createSaveWalletsSwitch(
isChecked = state.saveWallets,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveWalletsToggled,
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
isChecked = state.saveAccessCodes,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveAccessCodesToggled,
).let(::add)
}
}
return items.toImmutableList()
}
private fun enrollBiometrics() {
store.dispatchOnMain(DetailsAction.AppSettings.EnrollBiometrics)
}
private fun onSaveWalletsToggled(isChecked: Boolean) {
if (isChecked) {
onSettingsToggled(AppSetting.SaveWallets, enable = true)
} else {
updateContentState {
copy(
alert = alertsFactory.createDeleteSavedWalletsAlert(
onDelete = {
onSettingsToggled(AppSetting.SaveWallets, enable = false)
dismissDialog()
},
onDismiss = ::dismissDialog,
),
)
}
}
}
private fun onSaveAccessCodesToggled(isChecked: Boolean) {
if (isChecked) {
onSettingsToggled(AppSetting.SaveAccessCode, enable = true)
} else {
updateContentState {
copy(
alert = alertsFactory.createDeleteSavedAccessCodesAlert(
onDelete = {
onSettingsToggled(AppSetting.SaveAccessCode, enable = false)
dismissDialog()
},
onDismiss = ::dismissDialog,
),
)
}
}
}
private fun onSettingsToggled(setting: AppSetting, enable: Boolean) {
store.dispatch(DetailsAction.AppSettings.SwitchPrivacySetting(enable = enable, setting = setting))
}
private fun dismissDialog() {
updateContentState { copy(alert = null) }
}
private fun updateContentState(block: AppSettingsScreenState.Content.() -> AppSettingsScreenState.Content) {
uiState = when (val state = uiState) {
is AppSettingsScreenState.Content -> block(state)
is AppSettingsScreenState.Loading -> state
}
}
}

View file

@ -1,11 +1,6 @@
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.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Icon
import androidx.compose.material.Surface
@ -14,24 +9,25 @@ 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.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
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.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.wallet.R
import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun EnrollBiometricsCard(onClick: () -> Unit) {
internal fun CardItem(item: Item.Card, modifier: Modifier = Modifier) {
Surface(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing8)
.fillMaxWidth(),
color = TangemTheme.colors.background.primary,
modifier = modifier.fillMaxWidth(),
color = TangemTheme.colors.button.disabled,
shape = TangemTheme.shapes.roundedCornersLarge,
onClick = onClick,
onClick = item.onClick,
) {
Row(
modifier = Modifier.padding(all = 16.dp),
@ -39,20 +35,20 @@ internal fun EnrollBiometricsCard(onClick: () -> Unit) {
horizontalArrangement = Arrangement.SpaceEvenly,
) {
Icon(
painter = painterResource(id = R.drawable.ic_alert_circle_24),
painter = painterResource(id = item.iconResId),
tint = TangemTheme.colors.icon.attention,
contentDescription = null,
)
SpacerW16()
Column {
Text(
text = stringResource(id = R.string.app_settings_enable_biometrics_title),
text = item.title.resolveReference(),
style = TangemTheme.typography.subtitle1,
color = TangemTheme.colors.text.primary1,
)
SpacerH4()
Text(
text = stringResource(id = R.string.app_settings_enable_biometrics_description),
text = item.description.resolveReference(),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.secondary,
)
@ -62,28 +58,29 @@ internal fun EnrollBiometricsCard(onClick: () -> Unit) {
}
// 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() {
private fun CardItemPreview_Light(@PreviewParameter(CardItemProvider::class) item: Item.Card) {
TangemTheme {
EnrollBiometricsCardSample()
CardItem(item = item)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun EnrollBiometricsCardPreview_Dark() {
private fun CardItemPreview_Dark(@PreviewParameter(CardItemProvider::class) item: Item.Card) {
TangemTheme(isDark = true) {
EnrollBiometricsCardSample()
CardItem(item = item)
}
}
private class CardItemProvider : CollectionPreviewParameterProvider<Item.Card>(
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createEnrollBiometricsCard(
onClick = { /* no-op */ },
).let(::add)
},
)
// endregion Preview

View file

@ -1,97 +1,60 @@
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 androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.BasicDialog
import com.tangem.core.ui.components.DialogButton
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.redux.AppSetting
import com.tangem.tap.features.details.ui.appsettings.AppSettingsAlertsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Alert
import com.tangem.wallet.R
@Composable
internal fun SettingsAlertDialog(
element: AppSetting,
onDialogStateChange: (AppSetting?) -> Unit,
onSettingToggle: () -> Unit,
) {
val text = when (element) {
AppSetting.SaveWallets -> R.string.app_settings_off_saved_wallet_alert_message
AppSetting.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)
onSettingToggle()
},
)
},
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,
internal fun SettingsAlertDialog(alert: Alert) {
BasicDialog(
title = alert.title.resolveReference(),
message = alert.description.resolveReference(),
isDismissable = false,
confirmButton = DialogButton(
title = alert.confirmText.resolveReference(),
warning = true,
onClick = alert.onConfirm,
),
dismissButton = DialogButton(
title = stringResource(id = R.string.common_cancel),
onClick = alert.onDismiss,
),
onDismissDialog = alert.onDismiss,
)
}
// region Preview
@Composable
private fun SettingsAlertDialogSample(modifier: Modifier = Modifier) {
Column(
modifier = modifier
.background(TangemTheme.colors.background.primary),
) {
SettingsAlertDialog(
element = AppSetting.SaveAccessCode,
onDialogStateChange = {},
onSettingToggle = { },
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun SettingsAlertDialogPreview_Light() {
private fun AlertDialogPreview_Light(@PreviewParameter(AlertDialogProvider::class) dialog: Alert) {
TangemTheme {
SettingsAlertDialogSample()
SettingsAlertDialog(alert = dialog)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun SettingsAlertDialogPreview_Dark() {
private fun AlertDialogPreview_Dark(@PreviewParameter(AlertDialogProvider::class) dialog: Alert) {
TangemTheme(isDark = true) {
SettingsAlertDialogSample()
SettingsAlertDialog(alert = dialog)
}
}
private class AlertDialogProvider : CollectionPreviewParameterProvider<Alert>(
collection = buildList {
val alertsFactory = AppSettingsAlertsFactory()
alertsFactory.createDeleteSavedAccessCodesAlert({}, {}).let(::add)
alertsFactory.createDeleteSavedWalletsAlert({}, {}).let(::add)
},
)
// endregion Preview

View file

@ -0,0 +1,113 @@
package com.tangem.tap.features.details.ui.appsettings.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.components.SpacerH4
import com.tangem.core.ui.components.SpacerW32
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
import com.tangem.tap.features.details.ui.common.TangemSwitch
@Composable
internal fun SwitchItem(item: Item.Switch, modifier: Modifier = Modifier) {
val titleTextColor by rememberUpdatedState(
newValue = if (item.isEnabled) {
TangemTheme.colors.text.primary1
} else {
TangemTheme.colors.text.secondary
},
)
val descriptionTextColor by rememberUpdatedState(
newValue = if (item.isEnabled) {
TangemTheme.colors.text.secondary
} else {
TangemTheme.colors.text.tertiary
},
)
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Column(
modifier = Modifier.weight(weight = .9f),
verticalArrangement = Arrangement.Center,
) {
Text(
text = item.title.resolveReference(),
style = TangemTheme.typography.subtitle1,
color = titleTextColor,
)
SpacerH4()
Text(
text = item.description.resolveReference(),
style = TangemTheme.typography.body2,
color = descriptionTextColor,
)
}
SpacerW32()
TangemSwitch(
checked = item.isChecked,
enabled = item.isEnabled,
onCheckedChange = item.onCheckedChange,
)
}
}
// region Preview
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun SwitchItemPreview_Light(@PreviewParameter(SwitchItemProvider::class) item: Item.Switch) {
TangemTheme {
SwitchItem(item = item)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun SwitchItemPreview_Dark(@PreviewParameter(SwitchItemProvider::class) item: Item.Switch) {
TangemTheme(isDark = true) {
SwitchItem(item = item)
}
}
private class SwitchItemProvider : CollectionPreviewParameterProvider<Item.Switch>(
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createSaveAccessCodeSwitch(
isChecked = true,
isEnabled = true,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
isChecked = false,
isEnabled = true,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
isChecked = true,
isEnabled = false,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
isChecked = false,
isEnabled = false,
onCheckedChange = { /* no-op */ },
).let(::add)
},
)
// endregion Preview