Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-26 13:58:15 +03:00
parent 776cb482ad
commit d922493a76
4 changed files with 101 additions and 63 deletions

View file

@ -1,58 +1,36 @@
package com.tangem.tap.features.details.ui.cardsettings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.fragment.app.viewModels
import com.tangem.core.navigation.NavigationAction
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 dagger.hilt.android.AndroidEntryPoint
import org.rekotlin.StoreSubscriber
import javax.inject.Inject
@AndroidEntryPoint
internal class CardSettingsFragment : ComposeFragment(), StoreSubscriber<DetailsState> {
internal class CardSettingsFragment : ComposeFragment() {
@Inject
override lateinit var appThemeModeHolder: AppThemeModeHolder
private val viewModel = CardSettingsViewModel(store)
private var screenState: MutableState<CardSettingsScreenState> =
mutableStateOf(viewModel.updateState(store.state.detailsState.cardSettingsState))
private val viewModel: CardSettingsViewModel by viewModels()
@Composable
override fun ScreenContent(modifier: Modifier) {
LocalLifecycleOwner.current.lifecycle.addObserver(viewModel)
CardSettingsScreen(
modifier = modifier,
state = screenState.value,
state = viewModel.screenState.value,
onBackClick = {
store.dispatch(DetailsAction.ResetCardSettingsData)
store.dispatch(NavigationAction.PopBackTo())
},
)
}
override fun onStart() {
super.onStart()
store.subscribe(this) { state ->
state.skipRepeats { oldState, newState ->
oldState.detailsState == newState.detailsState
}.select { it.detailsState }
}
}
override fun onStop() {
super.onStop()
store.unsubscribe(this)
}
override fun newState(state: DetailsState) {
if (activity == null || view == null) return
screenState.value = viewModel.updateState(state.cardSettingsState)
}
}

View file

@ -1,22 +1,21 @@
package com.tangem.tap.features.details.ui.cardsettings
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.compose.SubcomposeAsyncImage
import coil.request.ImageRequest
import com.tangem.core.ui.res.TangemTheme
import com.tangem.domain.userwallets.Artwork
import com.tangem.tap.features.details.ui.common.DetailsMainButton
import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
import com.tangem.wallet.R
@ -33,7 +32,7 @@ internal fun CardSettingsScreen(
modifier = modifier,
content = {
if (needReadCard) {
CardSettingsReadCard(state.onScanCardClick)
CardSettingsReadCard(state.onScanCardClick, state.cardImage)
} else {
CardSettings(state = state)
}
@ -45,46 +44,57 @@ internal fun CardSettingsScreen(
@Suppress("MagicNumber")
@Composable
private fun CardSettingsReadCard(onScanCardClick: () -> Unit) {
private fun CardSettingsReadCard(onScanCardClick: () -> Unit, cardArtwork: Artwork?) {
Column(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.padding(top = TangemTheme.dimens.size70),
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 40.dp),
.padding(start = TangemTheme.dimens.size16, end = TangemTheme.dimens.size16),
) {
Image(
val circleColor = TangemTheme.colors.stroke.primary
Canvas(
modifier = Modifier
.fillMaxWidth()
.padding(start = 80.dp, end = 80.dp, top = 70.dp)
.rotate(-15f),
painter = painterResource(id = R.drawable.card_placeholder_secondary),
contentDescription = "",
contentScale = ContentScale.FillWidth,
)
Image(
.size(300.dp)
.align(Alignment.Center),
) {
drawCircle(
color = circleColor,
radius = size.minDimension / 2.0f,
)
}
SubcomposeAsyncImage(
model = ImageRequest.Builder(context = LocalContext.current)
.data(cardArtwork?.artworkId)
.crossfade(enable = true)
.build(),
modifier = Modifier
.fillMaxWidth()
.padding(start = 60.dp, end = 60.dp)
.rotate(-1f),
painter = painterResource(id = R.drawable.card_placeholder_black),
contentDescription = "",
contentScale = ContentScale.FillWidth,
.align(Alignment.Center)
.fillMaxWidth(),
loading = { /* no-op */ },
error = { /* no-op */ },
contentDescription = null,
)
}
Spacer(modifier = Modifier.weight(1f))
Column(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 32.dp),
.padding(
start = TangemTheme.dimens.size16,
end = TangemTheme.dimens.size16,
bottom = TangemTheme.dimens.size32,
),
) {
Text(
text = stringResource(id = R.string.scan_card_settings_title),
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.h3,
)
Spacer(modifier = Modifier.size(20.dp))
Spacer(modifier = Modifier.size(TangemTheme.dimens.size20))
Text(
text = stringResource(id = R.string.scan_card_settings_message),
color = TangemTheme.colors.text.secondary,
@ -93,7 +103,7 @@ private fun CardSettingsReadCard(onScanCardClick: () -> Unit) {
.verticalScroll(rememberScrollState())
.weight(weight = 1f, fill = false),
)
Spacer(modifier = Modifier.size(29.dp))
Spacer(modifier = Modifier.size(TangemTheme.dimens.size28))
DetailsMainButton(
title = stringResource(id = R.string.scan_card_settings_button),
onClick = onScanCardClick,
@ -166,7 +176,7 @@ private fun CardSettings(state: CardSettingsScreenState) {
// region Preview
@Composable
private fun CardSettingsScreenStateSample() {
CardSettingsScreen(state = CardSettingsScreenState(onScanCardClick = {}) {}, {})
CardSettingsScreen(state = CardSettingsScreenState(onScanCardClick = {}, onElementClick = {}), {})
}
@Preview(showBackground = true, widthDp = 360)

View file

@ -4,6 +4,7 @@ import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.res.stringResource
import com.tangem.domain.userwallets.Artwork
import com.tangem.tap.features.details.redux.AccessCodeRecoveryState
import com.tangem.tap.features.details.redux.SecurityOption
import com.tangem.tap.features.details.ui.securitymode.toTitleRes
@ -16,6 +17,7 @@ internal data class CardSettingsScreenState(
val accessCodeRecoveryState: AccessCodeRecoveryState? = null,
val onScanCardClick: () -> Unit,
val onElementClick: (CardInfo) -> Unit,
val cardImage: Artwork? = null,
)
internal sealed class CardInfo(

View file

@ -1,18 +1,64 @@
package com.tangem.tap.features.details.ui.cardsettings
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import arrow.core.Either
import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
import com.tangem.domain.common.getTwinCardIdForUser
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
import com.tangem.tap.common.analytics.events.AnalyticsParam
import com.tangem.tap.common.analytics.events.Settings
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.features.details.redux.CardSettingsState
import com.tangem.tap.features.details.redux.DetailsAction
import org.rekotlin.Store
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.features.wallet.redux.WalletAction
import dagger.hilt.android.lifecycle.HiltViewModel
import org.rekotlin.StoreSubscriber
import com.tangem.tap.store
import timber.log.Timber
import javax.inject.Inject
internal class CardSettingsViewModel(private val store: Store<AppState>) {
@HiltViewModel
internal class CardSettingsViewModel @Inject constructor(
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
) :
ViewModel(), DefaultLifecycleObserver, StoreSubscriber<DetailsState> {
fun updateState(state: CardSettingsState?): CardSettingsScreenState {
var screenState: MutableState<CardSettingsScreenState> =
mutableStateOf(updateState(store.state.detailsState.cardSettingsState))
override fun onStart(owner: LifecycleOwner) {
when (val selectedWalletEither = getSelectedWalletUseCase()) {
is Either.Left -> {
Timber.e(selectedWalletEither.value.toString())
}
is Either.Right -> {
store.dispatchOnMain(WalletAction.UpdateUserWalletArtwork(selectedWalletEither.value.walletId))
}
}
store.subscribe(this) { state ->
state.skipRepeats { oldState, newState ->
oldState.detailsState == newState.detailsState &&
oldState.walletState == newState.walletState
}.select { it.detailsState }
}
}
override fun onStop(owner: LifecycleOwner) {
store.unsubscribe(this)
}
override fun newState(state: DetailsState) {
screenState.value = updateState(state.cardSettingsState)
}
private fun updateState(state: CardSettingsState?): CardSettingsScreenState {
return if (state?.manageSecurityState == null) {
CardSettingsScreenState(
cardDetails = null,
@ -21,6 +67,7 @@ internal class CardSettingsViewModel(private val store: Store<AppState>) {
onScanCardClick = {
store.dispatch(DetailsAction.ScanCard)
},
cardImage = store.state.walletState.cardImage,
)
} else {
val cardId = if (state.card.isTangemTwins) {
@ -58,6 +105,7 @@ internal class CardSettingsViewModel(private val store: Store<AppState>) {
onElementClick = {
handleClickingItem(it)
},
cardImage = store.state.walletState.cardImage,
)
}
}