Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-04 16:50:50 +03:00
parent df9ba4e5f1
commit 6271952c4a
25 changed files with 314 additions and 302 deletions

View file

@ -1,50 +1,55 @@
package com.tangem.tap.features.details.ui.appsettings
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.core.ui.theme.AppThemeModeHolder
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 dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
@AndroidEntryPoint
internal class AppSettingsFragment : ComposeFragment(), StoreSubscriber<DetailsState> {
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
class AppSettingsFragment : Fragment(), StoreSubscriber<DetailsState> {
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,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
},
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.fade)
exitTransition = inflater.inflateTransition(R.transition.fade)
viewModel.checkBiometricsStatus()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setContent {
isTransitionGroup = true
TangemTheme {
AppSettingsScreen(
state = screenState.value,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
},
)
}
}
}
override fun TransitionInflater.inflateTransitions(): Boolean {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
return true
}
override fun onStart() {

View file

@ -1,19 +1,9 @@
package com.tangem.tap.features.details.ui.appsettings
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.foundation.layout.*
import androidx.compose.material.Text
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.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@ -31,8 +21,9 @@ import com.tangem.tap.features.details.ui.common.TangemSwitch
import com.tangem.wallet.R
@Composable
fun AppSettingsScreen(state: AppSettingsScreenState, onBackClick: () -> Unit) {
internal fun AppSettingsScreen(state: AppSettingsScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
SettingsScreensScaffold(
modifier = modifier,
content = { AppSettings(state = state) },
titleRes = R.string.app_settings_title,
onBackClick = onBackClick,

View file

@ -2,7 +2,7 @@ package com.tangem.tap.features.details.ui.appsettings
import com.tangem.tap.features.details.redux.AppSetting
data class AppSettingsScreenState(
internal data class AppSettingsScreenState(
val settings: Map<AppSetting, Boolean> = emptyMap(),
val showEnrollBiometricsCard: Boolean = false,
val isTogglesEnabled: Boolean = false,

View file

@ -7,7 +7,7 @@ import com.tangem.tap.features.details.redux.DetailsAction
import com.tangem.tap.features.details.redux.DetailsState
import org.rekotlin.Store
class AppSettingsViewModel(private val store: Store<AppState>) {
internal class AppSettingsViewModel(private val store: Store<AppState>) {
fun updateState(state: DetailsState): AppSettingsScreenState {
return with(state.appSettingsState) {

View file

@ -1,51 +1,49 @@
package com.tangem.tap.features.details.ui.cardsettings
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.core.ui.theme.AppThemeModeHolder
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 dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
class CardSettingsFragment : Fragment(), StoreSubscriber<DetailsState> {
@AndroidEntryPoint
internal class CardSettingsFragment : ComposeFragment(), StoreSubscriber<DetailsState> {
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
private val viewModel = CardSettingsViewModel(store)
private var screenState: MutableState<CardSettingsScreenState> =
mutableStateOf(viewModel.updateState(store.state.detailsState.cardSettingsState))
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)
@Composable
override fun ScreenContent(modifier: Modifier) {
CardSettingsScreen(
modifier = modifier,
state = screenState.value,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
},
)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setContent {
isTransitionGroup = true
TangemTheme {
CardSettingsScreen(
state = screenState.value,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
},
)
}
}
}
override fun TransitionInflater.inflateTransitions(): Boolean {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
return true
}
override fun onStart() {

View file

@ -2,13 +2,7 @@ package com.tangem.tap.features.details.ui.cardsettings
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
@ -18,7 +12,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@ -29,10 +22,15 @@ import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
import com.tangem.wallet.R
@Composable
fun CardSettingsScreen(state: CardSettingsScreenState, onBackClick: () -> Unit) {
internal fun CardSettingsScreen(
state: CardSettingsScreenState,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val needReadCard = state.cardDetails == null
SettingsScreensScaffold(
modifier = modifier,
content = {
if (needReadCard) {
CardSettingsReadCard(state.onScanCardClick)
@ -41,14 +39,13 @@ fun CardSettingsScreen(state: CardSettingsScreenState, onBackClick: () -> Unit)
}
},
titleRes = R.string.card_settings_title,
backgroundColor = TangemTheme.colors.background.secondary,
onBackClick = onBackClick,
)
}
@Suppress("MagicNumber")
@Composable
fun CardSettingsReadCard(onScanCardClick: () -> Unit) {
private fun CardSettingsReadCard(onScanCardClick: () -> Unit) {
Column(
modifier = Modifier.fillMaxSize(),
) {
@ -84,13 +81,13 @@ fun CardSettingsReadCard(onScanCardClick: () -> Unit) {
) {
Text(
text = stringResource(id = R.string.scan_card_settings_title),
color = colorResource(id = R.color.text_primary_1),
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.h3,
)
Spacer(modifier = Modifier.size(20.dp))
Text(
text = stringResource(id = R.string.scan_card_settings_message),
color = colorResource(id = R.color.text_secondary),
color = TangemTheme.colors.text.secondary,
style = TangemTheme.typography.body1,
modifier = Modifier
.verticalScroll(rememberScrollState())
@ -107,7 +104,7 @@ fun CardSettingsReadCard(onScanCardClick: () -> Unit) {
@Suppress("ComplexMethod")
@Composable
fun CardSettings(state: CardSettingsScreenState) {
private fun CardSettings(state: CardSettingsScreenState) {
if (state.cardDetails == null) return
LazyColumn(
@ -166,8 +163,25 @@ fun CardSettings(state: CardSettingsScreenState) {
}
}
// region Preview
@Composable
@Preview
private fun CardSettingsPreview() {
private fun CardSettingsScreenStateSample() {
CardSettingsScreen(state = CardSettingsScreenState(onScanCardClick = {}) {}, {})
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun CardSettingsScreenStatePreview_Light() {
TangemTheme {
CardSettingsScreenStateSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun CardSettingsScreenStatePreview_Dark() {
TangemTheme(isDark = true) {
CardSettingsScreenStateSample()
}
}
// endregion Preview

View file

@ -11,14 +11,14 @@ import com.tangem.tap.features.details.ui.utils.toResetCardDescriptionText
import com.tangem.wallet.R
import com.tangem.tap.features.details.redux.CardInfo as ReduxCardInfo
data class CardSettingsScreenState(
internal data class CardSettingsScreenState(
val cardDetails: List<CardInfo>? = null,
val accessCodeRecoveryState: AccessCodeRecoveryState? = null,
val onScanCardClick: () -> Unit,
val onElementClick: (CardInfo) -> Unit,
)
sealed class CardInfo(
internal sealed class CardInfo(
val titleRes: TextReference,
val subtitle: TextReference,
val clickable: Boolean = false,
@ -68,7 +68,7 @@ sealed class CardInfo(
}
// TODO("Remove and use the same from coreUI")
sealed interface TextReference {
internal sealed interface TextReference {
class Res(@StringRes val id: Int, val formatArgs: List<Any> = emptyList()) : TextReference {
constructor(@StringRes id: Int, vararg formatArgs: Any) : this(id, formatArgs.toList())
}
@ -78,7 +78,7 @@ sealed interface TextReference {
@Composable
@ReadOnlyComposable
fun TextReference.resolveReference(): String {
internal fun TextReference.resolveReference(): String {
return when (this) {
is TextReference.Res -> stringResource(this.id, *this.formatArgs.toTypedArray())
is TextReference.Str -> this.value

View file

@ -10,7 +10,7 @@ import com.tangem.tap.features.details.redux.CardSettingsState
import com.tangem.tap.features.details.redux.DetailsAction
import org.rekotlin.Store
class CardSettingsViewModel(private val store: Store<AppState>) {
internal class CardSettingsViewModel(private val store: Store<AppState>) {
fun updateState(state: CardSettingsState?): CardSettingsScreenState {
return if (state?.manageSecurityState == null) {

View file

@ -1,6 +1,7 @@
package com.tangem.tap.features.details.ui.common
import androidx.activity.compose.BackHandler
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.selection.selectable
import androidx.compose.material.*
@ -12,20 +13,24 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.PrimaryButtonIconEnd
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
import com.tangem.wallet.R
@Composable
fun SettingsScreensScaffold(
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
background: @Composable (() -> Unit)? = null,
fab: @Composable (() -> Unit)? = null,
backgroundColor: Color = TangemTheme.colors.background.secondary,
titleRes: Int? = null,
internal fun SettingsScreensScaffold(
onBackClick: () -> Unit,
content: @Composable () -> Unit,
modifier: Modifier = Modifier,
fab: @Composable (() -> Unit)? = null,
@StringRes titleRes: Int? = null,
) {
BackHandler(true, onBackClick)
val backgroundColor = TangemTheme.colors.background.secondary
BackHandler(onBack = onBackClick)
SystemBarsEffect {
setSystemBarsColor(backgroundColor)
}
Scaffold(
topBar = {
@ -37,33 +42,30 @@ fun SettingsScreensScaffold(
modifier = modifier.systemBarsPadding(),
backgroundColor = backgroundColor,
floatingActionButton = { fab?.invoke() },
) {
if (titleRes != null) {
Box(modifier = modifier.fillMaxSize()) {
background?.invoke()
Column(modifier = modifier.fillMaxWidth()) {
Text(
text = stringResource(id = titleRes),
modifier = modifier.padding(
start = TangemTheme.dimens.spacing20,
end = TangemTheme.dimens.spacing20,
bottom = TangemTheme.dimens.spacing54,
),
style = TangemTheme.typography.h1,
color = TangemTheme.colors.text.primary1,
)
content()
}
) { paddings ->
Column(
modifier = Modifier
.padding(paddings)
.fillMaxSize(),
) {
if (titleRes != null) {
Text(
text = stringResource(id = titleRes),
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing20)
.padding(bottom = TangemTheme.dimens.spacing36),
style = TangemTheme.typography.h1,
color = TangemTheme.colors.text.primary1,
)
}
} else {
content()
}
}
}
@Composable
fun ScreenTitle(titleRes: Int, modifier: Modifier = Modifier) {
internal fun ScreenTitle(titleRes: Int, modifier: Modifier = Modifier) {
Text(
text = stringResource(id = titleRes),
modifier = modifier.padding(start = 20.dp, end = 20.dp),
@ -73,7 +75,7 @@ fun ScreenTitle(titleRes: Int, modifier: Modifier = Modifier) {
}
@Composable
fun EmptyTopBarWithNavigation(
internal fun EmptyTopBarWithNavigation(
onBackClick: () -> Unit,
backgroundColor: Color = TangemTheme.colors.background.primary,
) {
@ -95,7 +97,12 @@ fun EmptyTopBarWithNavigation(
}
@Composable
fun DetailsMainButton(title: String, onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true) {
internal fun DetailsMainButton(
title: String,
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
) {
PrimaryButtonIconEnd(
text = title,
enabled = enabled,
@ -107,7 +114,7 @@ fun DetailsMainButton(title: String, onClick: () -> Unit, modifier: Modifier = M
}
@Composable
fun DetailsRadioButtonElement(title: String, subtitle: String, selected: Boolean, onClick: () -> Unit) {
internal fun DetailsRadioButtonElement(title: String, subtitle: String, selected: Boolean, onClick: () -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()

View file

@ -1,45 +1,48 @@
package com.tangem.tap.features.details.ui.details
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.core.ui.theme.AppThemeModeHolder
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import com.tangem.wallet.R
import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
class DetailsFragment : Fragment(), StoreSubscriber<DetailsState> {
@AndroidEntryPoint
internal class DetailsFragment : ComposeFragment(), StoreSubscriber<DetailsState> {
private val detailsViewModel = DetailsViewModel(store)
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Analytics.send(Settings.ScreenOpened())
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.fade)
exitTransition = inflater.inflateTransition(R.transition.fade)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setContent {
isTransitionGroup = true
TangemTheme {
DetailsScreen(
state = detailsViewModel.detailsScreenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
)
}
}
}
@Composable
override fun ScreenContent(modifier: Modifier) {
DetailsScreen(
modifier = modifier,
state = detailsViewModel.detailsScreenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
)
}
override fun TransitionInflater.inflateTransitions(): Boolean {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
return true
}
override fun onStart() {

View file

@ -1,18 +1,7 @@
package com.tangem.tap.features.details.ui.details
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
@ -27,12 +16,10 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
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.SystemBarsEffect
import com.tangem.core.ui.res.TangemColorPalette
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.ui.common.ScreenTitle
@ -41,20 +28,17 @@ import com.tangem.wallet.R
import kotlinx.coroutines.launch
@Composable
fun DetailsScreen(state: DetailsScreenState, onBackClick: () -> Unit) {
SystemBarsEffect {
setSystemBarsColor(color = TangemColorPalette.Light1)
}
internal fun DetailsScreen(state: DetailsScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
SettingsScreensScaffold(
modifier = modifier,
content = { Content(state = state) },
onBackClick = onBackClick,
)
}
@Composable
fun Content(state: DetailsScreenState) {
Box {
private fun Content(state: DetailsScreenState, modifier: Modifier = Modifier) {
Box(modifier = modifier) {
Column(
modifier = Modifier
.fillMaxSize()
@ -78,7 +62,7 @@ fun Content(state: DetailsScreenState) {
Text(
text = "${stringResource(id = state.appNameRes)} ${state.tangemVersion}",
style = TangemTheme.typography.caption,
color = colorResource(id = R.color.text_tertiary),
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 40.dp),
)
}
@ -87,7 +71,7 @@ fun Content(state: DetailsScreenState) {
}
@Composable
fun WalletConnectDetailsItem(onItemsClick: (SettingsElement) -> Unit) {
private fun WalletConnectDetailsItem(onItemsClick: (SettingsElement) -> Unit) {
Row(
modifier = Modifier
.defaultMinSize(minHeight = 84.dp)
@ -100,7 +84,7 @@ fun WalletConnectDetailsItem(onItemsClick: (SettingsElement) -> Unit) {
painter = painterResource(id = R.drawable.ic_walletconnect),
contentDescription = stringResource(id = R.string.wallet_connect_title),
modifier = Modifier.padding(start = 20.dp, end = 20.dp),
tint = colorResource(id = R.color.all_colors_azure),
tint = TangemColorPalette.Azure,
)
Column(
modifier = Modifier.defaultMinSize(minHeight = 56.dp),
@ -111,20 +95,20 @@ fun WalletConnectDetailsItem(onItemsClick: (SettingsElement) -> Unit) {
text = stringResource(id = R.string.wallet_connect_title),
modifier = Modifier.padding(end = 20.dp, bottom = 4.dp),
style = TangemTheme.typography.h3,
color = colorResource(id = R.color.text_primary_1),
color = TangemTheme.colors.text.primary1,
)
Text(
text = stringResource(id = R.string.wallet_connect_subtitle),
modifier = Modifier.padding(end = 20.dp, bottom = 4.dp),
style = TangemTheme.typography.body1,
color = colorResource(id = R.color.text_secondary),
color = TangemTheme.colors.text.secondary,
)
}
}
}
@Composable
fun DetailsItem(item: SettingsElement, appCurrency: String, onItemsClick: () -> Unit) {
private fun DetailsItem(item: SettingsElement, appCurrency: String, onItemsClick: () -> Unit) {
Row(
modifier = Modifier
.height(56.dp)
@ -137,20 +121,20 @@ fun DetailsItem(item: SettingsElement, appCurrency: String, onItemsClick: () ->
painter = painterResource(id = item.iconRes),
contentDescription = stringResource(id = item.titleRes),
modifier = Modifier.padding(start = 20.dp, end = 20.dp),
tint = colorResource(id = R.color.icon_secondary),
tint = TangemTheme.colors.icon.secondary,
)
Column(modifier = Modifier.padding(end = 20.dp)) {
Text(
text = stringResource(id = item.titleRes),
modifier = Modifier,
style = TangemTheme.typography.subtitle1,
color = colorResource(id = R.color.text_primary_1),
color = TangemTheme.colors.text.primary1,
)
if (item == SettingsElement.AppCurrency) {
Text(
text = appCurrency,
style = TangemTheme.typography.body2,
color = colorResource(id = R.color.text_secondary),
color = TangemTheme.colors.text.secondary,
)
}
}
@ -158,7 +142,7 @@ fun DetailsItem(item: SettingsElement, appCurrency: String, onItemsClick: () ->
}
@Composable
fun TangemSocialAccounts(links: List<SocialNetworkLink>, onSocialNetworkClick: (SocialNetworkLink) -> Unit) {
private fun TangemSocialAccounts(links: List<SocialNetworkLink>, onSocialNetworkClick: (SocialNetworkLink) -> Unit) {
LazyRow(
modifier = Modifier.padding(start = 8.dp, end = 8.dp),
verticalAlignment = Alignment.CenterVertically,
@ -170,14 +154,14 @@ fun TangemSocialAccounts(links: List<SocialNetworkLink>, onSocialNetworkClick: (
modifier = Modifier
.padding(8.dp)
.clickable { onSocialNetworkClick(it) },
tint = colorResource(id = R.color.icon_informative),
tint = TangemTheme.colors.icon.informative,
)
}
}
}
@Composable
fun BoxScope.ShowSnackbarIfNeeded(snackbarErrorState: EventError) {
private fun BoxScope.ShowSnackbarIfNeeded(snackbarErrorState: EventError) {
val snackbarHostState = remember { SnackbarHostState() }
val coroutineScope = rememberCoroutineScope()
SnackbarHost(
@ -206,9 +190,9 @@ fun BoxScope.ShowSnackbarIfNeeded(snackbarErrorState: EventError) {
}
}
// region Preview
@Composable
@Preview
private fun Preview() {
private fun DetailsScreenContentSample() {
DetailsScreen(
state = DetailsScreenState(
elements = SettingsElement.values().toList(),
@ -220,4 +204,21 @@ private fun Preview() {
),
onBackClick = {},
)
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun DetailsScreenContentPreview_Light() {
TangemTheme(isDark = false) {
DetailsScreenContentSample()
}
}
@Preview(showBackground = true, widthDp = 360)
@Composable
private fun DetailsScreenContentPreview_Dark() {
TangemTheme(isDark = true) {
DetailsScreenContentSample()
}
}
// endregion Preview

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.mutableStateOf
import com.tangem.wallet.R
@Immutable
data class DetailsScreenState(
internal data class DetailsScreenState(
val elements: List<SettingsElement>,
val tangemLinks: List<SocialNetworkLink>,
val tangemVersion: String,
@ -19,7 +19,7 @@ data class DetailsScreenState(
}
@Immutable
enum class SettingsElement(
internal enum class SettingsElement(
val iconRes: Int,
val titleRes: Int,
) {
@ -37,12 +37,12 @@ enum class SettingsElement(
}
@Immutable
data class SocialNetworkLink(
internal data class SocialNetworkLink(
val network: SocialNetwork,
val url: String,
)
sealed class EventError {
internal sealed class EventError {
object Empty : EventError()
data class DemoReferralNotAvailable(val onErrorShow: () -> Unit) : EventError()
}
@ -58,7 +58,7 @@ sealed class SocialNetwork(val id: String, val iconRes: Int) {
object Discord : SocialNetwork("Discord", R.drawable.ic_discord)
}
object TangemSocialAccounts {
internal object TangemSocialAccounts {
val accountsEn: List<SocialNetworkLink> = listOf(
SocialNetworkLink(SocialNetwork.Telegram, "https://t.me/tangem_chat"),
SocialNetworkLink(SocialNetwork.Twitter, "https://twitter.com/tangem"),

View file

@ -28,7 +28,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.rekotlin.Store
class DetailsViewModel(private val store: Store<AppState>) {
internal class DetailsViewModel(private val store: Store<AppState>) {
var detailsScreenState: MutableState<DetailsScreenState> = mutableStateOf(updateState(store.state.detailsState))
private set

View file

@ -1,47 +1,45 @@
package com.tangem.tap.features.details.ui.resetcard
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.core.ui.theme.AppThemeModeHolder
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import com.tangem.wallet.R
import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
class ResetCardFragment : Fragment(), StoreSubscriber<DetailsState> {
@AndroidEntryPoint
internal class ResetCardFragment : ComposeFragment(), StoreSubscriber<DetailsState> {
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
private val viewModel = ResetCardViewModel(store)
private var screenState: MutableState<ResetCardScreenState> =
mutableStateOf(viewModel.updateState(store.state.detailsState.cardSettingsState))
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)
@Composable
override fun ScreenContent(modifier: Modifier) {
ResetCardScreen(
modifier = modifier,
state = screenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setContent {
isTransitionGroup = true
TangemTheme {
ResetCardScreen(
state = screenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
)
}
}
}
override fun TransitionInflater.inflateTransitions(): Boolean {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
return true
}
override fun onStart() {

View file

@ -1,26 +1,12 @@
package com.tangem.tap.features.details.ui.resetcard
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.IconToggleButton
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
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.tooling.preview.Preview
@ -34,17 +20,17 @@ import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
import com.tangem.wallet.R
@Composable
fun ResetCardScreen(state: ResetCardScreenState, onBackClick: () -> Unit) {
internal fun ResetCardScreen(state: ResetCardScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
SettingsScreensScaffold(
modifier = modifier,
content = { ResetCardView(state = state) },
onBackClick = onBackClick,
backgroundColor = Color.Transparent,
)
}
@Suppress("LongMethod", "MagicNumber")
@Composable
fun ResetCardView(state: ResetCardScreenState) {
private fun ResetCardView(state: ResetCardScreenState) {
Column(
modifier = Modifier
.fillMaxSize()

View file

@ -2,7 +2,7 @@ package com.tangem.tap.features.details.ui.resetcard
import com.tangem.tap.features.details.ui.cardsettings.TextReference
data class ResetCardScreenState(
internal data class ResetCardScreenState(
val accepted: Boolean = false,
val descriptionText: TextReference,
val onAcceptWarningToggleClick: (Boolean) -> Unit,

View file

@ -7,7 +7,7 @@ import com.tangem.tap.features.details.ui.cardsettings.TextReference
import com.tangem.tap.features.details.ui.utils.toResetCardDescriptionText
import org.rekotlin.Store
class ResetCardViewModel(private val store: Store<AppState>) {
internal class ResetCardViewModel(private val store: Store<AppState>) {
fun updateState(state: CardSettingsState?): ResetCardScreenState {
val descriptionText = state?.cardInfo

View file

@ -1,47 +1,45 @@
package com.tangem.tap.features.details.ui.securitymode
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.core.ui.theme.AppThemeModeHolder
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.store
import com.tangem.wallet.R
import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
class SecurityModeFragment : Fragment(), StoreSubscriber<DetailsState> {
@AndroidEntryPoint
internal class SecurityModeFragment : ComposeFragment(), StoreSubscriber<DetailsState> {
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
private val viewModel = SecurityModeViewModel(store)
private var screenState: MutableState<SecurityModeScreenState> =
mutableStateOf(viewModel.updateState(store.state.detailsState.cardSettingsState?.manageSecurityState))
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)
@Composable
override fun ScreenContent(modifier: Modifier) {
SecurityModeScreen(
modifier = modifier,
state = screenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setContent {
isTransitionGroup = true
TangemTheme {
SecurityModeScreen(
state = screenState.value,
onBackClick = { store.dispatch(NavigationAction.PopBackTo()) },
)
}
}
}
override fun TransitionInflater.inflateTransitions(): Boolean {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
return true
}
override fun onStart() {

View file

@ -1,10 +1,6 @@
package com.tangem.tap.features.details.ui.securitymode
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
@ -20,8 +16,13 @@ import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
import com.tangem.wallet.R
@Composable
fun SecurityModeScreen(state: SecurityModeScreenState, onBackClick: () -> Unit) {
internal fun SecurityModeScreen(
state: SecurityModeScreenState,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
SettingsScreensScaffold(
modifier = modifier,
content = { SecurityModeOptions(state = state) },
// titleRes = R.string.card_settings_security_mode,
onBackClick = onBackClick,
@ -29,7 +30,7 @@ fun SecurityModeScreen(state: SecurityModeScreenState, onBackClick: () -> Unit)
}
@Composable
fun SecurityModeOptions(state: SecurityModeScreenState) {
private fun SecurityModeOptions(state: SecurityModeScreenState) {
Column(
modifier = Modifier
.fillMaxSize()
@ -55,7 +56,7 @@ fun SecurityModeOptions(state: SecurityModeScreenState) {
}
@Composable
fun SecurityOption(option: SecurityOption, state: SecurityModeScreenState) {
private fun SecurityOption(option: SecurityOption, state: SecurityModeScreenState) {
val selected = option == state.selectedSecurityMode
val title = option.toTitleRes()

View file

@ -3,7 +3,7 @@ package com.tangem.tap.features.details.ui.securitymode
import com.tangem.tap.features.details.redux.SecurityOption
import com.tangem.wallet.R
data class SecurityModeScreenState(
internal data class SecurityModeScreenState(
val availableOptions: List<SecurityOption>,
val selectedSecurityMode: SecurityOption,
val isSaveChangesEnabled: Boolean,
@ -11,7 +11,7 @@ data class SecurityModeScreenState(
val onSaveChangesClicked: () -> Unit,
)
fun SecurityOption.toTitleRes(): Int {
internal fun SecurityOption.toTitleRes(): Int {
return when (this) {
SecurityOption.LongTap -> R.string.details_manage_security_long_tap
SecurityOption.PassCode -> R.string.details_manage_security_passcode

View file

@ -6,7 +6,7 @@ import com.tangem.tap.features.details.redux.ManageSecurityState
import com.tangem.tap.features.details.redux.SecurityOption
import org.rekotlin.Store
class SecurityModeViewModel(val store: Store<AppState>) {
internal class SecurityModeViewModel(val store: Store<AppState>) {
fun updateState(state: ManageSecurityState?): SecurityModeScreenState {
if (state == null) {

View file

@ -1,24 +1,30 @@
package com.tangem.tap.features.details.ui.walletconnect
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.compose.ui.Modifier
import androidx.transition.TransitionInflater
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.core.ui.theme.AppThemeModeHolder
import com.tangem.tap.common.analytics.events.WalletConnect
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState
import com.tangem.tap.store
import com.tangem.wallet.R
import dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
@AndroidEntryPoint
internal class WalletConnectFragment : ComposeFragment(), StoreSubscriber<WalletConnectState> {
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
class WalletConnectFragment : Fragment(), StoreSubscriber<WalletConnectState> {
private val viewModel = WalletConnectViewModel(store)
private var screenState: MutableState<WalletConnectScreenState> =
mutableStateOf(viewModel.updateState(store.state.walletConnectState))
@ -26,32 +32,31 @@ class WalletConnectFragment : Fragment(), StoreSubscriber<WalletConnectState> {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Analytics.send(WalletConnect.ScreenOpened())
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(android.R.transition.fade)
exitTransition = inflater.inflateTransition(android.R.transition.fade)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setContent {
isTransitionGroup = true
TangemTheme {
WalletConnectScreen(
state = screenState.value,
onBackClick = {
if (screenState.value.isLoading) {
store.dispatch(
WalletConnectAction.FailureEstablishingSession(
store.state.walletConnectState.newSessionData?.session?.session,
),
)
}
store.dispatch(NavigationAction.PopBackTo())
},
@Composable
override fun ScreenContent(modifier: Modifier) {
WalletConnectScreen(
modifier = modifier,
state = screenState.value,
onBackClick = {
if (screenState.value.isLoading) {
store.dispatch(
WalletConnectAction.FailureEstablishingSession(
store.state.walletConnectState.newSessionData?.session?.session,
),
)
}
}
}
store.dispatch(NavigationAction.PopBackTo())
},
)
}
override fun TransitionInflater.inflateTransitions(): Boolean {
enterTransition = inflateTransition(R.transition.fade)
exitTransition = inflateTransition(R.transition.fade)
return true
}
override fun onStart() {

View file

@ -26,10 +26,15 @@ import com.tangem.wallet.R
import kotlinx.collections.immutable.persistentListOf
@Composable
fun WalletConnectScreen(state: WalletConnectScreenState, onBackClick: () -> Unit) {
internal fun WalletConnectScreen(
state: WalletConnectScreenState,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
SettingsScreensScaffold(
modifier = modifier,
content = {
if (state.sessions.isEmpty()) {
EmptyScreen(state)

View file

@ -3,7 +3,7 @@ package com.tangem.tap.features.details.ui.walletconnect
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession
import kotlinx.collections.immutable.ImmutableList
data class WalletConnectScreenState(
internal data class WalletConnectScreenState(
val sessions: ImmutableList<WcSessionForScreen>,
val isLoading: Boolean = false,
val onRemoveSession: (String) -> Unit = {},

View file

@ -8,7 +8,7 @@ import kotlinx.collections.immutable.toImmutableList
import org.rekotlin.Store
import timber.log.Timber
class WalletConnectViewModel(private val store: Store<AppState>) {
internal class WalletConnectViewModel(private val store: Store<AppState>) {
fun updateState(state: WalletConnectState): WalletConnectScreenState {
Timber.d("WC2 Sessions: ${state.wc2Sessions}")
val sessions = state.sessions.map { wcSession -> WcSessionForScreen.fromSession(wcSession) } + state.wc2Sessions