Updated on 2026-08-14
This commit is contained in:
parent
59ad4c5c5c
commit
98ec93e259
34 changed files with 407 additions and 210 deletions
|
|
@ -0,0 +1,73 @@
|
|||
package com.tangem.common.ui.amountScreen.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.SecondaryButtonIconStart
|
||||
import com.tangem.core.ui.components.SpacerW12
|
||||
import com.tangem.core.ui.extensions.shareText
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
||||
@Composable
|
||||
fun SendDoneButtons(
|
||||
txUrl: String,
|
||||
onExploreClick: () -> Unit,
|
||||
onShareClick: () -> Unit,
|
||||
isVisible: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val context = LocalContext.current
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isVisible && txUrl.isNotBlank(),
|
||||
modifier = modifier,
|
||||
enter = slideInVertically().plus(fadeIn()),
|
||||
exit = slideOutVertically().plus(fadeOut()),
|
||||
label = "Animate show sent state buttons",
|
||||
) {
|
||||
Row(modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12)) {
|
||||
SecondaryButtonIconStart(
|
||||
text = stringResource(id = R.string.common_explore),
|
||||
iconResId = R.drawable.ic_web_24,
|
||||
onClick = onExploreClick,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
SpacerW12()
|
||||
SecondaryButtonIconStart(
|
||||
text = stringResource(id = R.string.common_share),
|
||||
iconResId = R.drawable.ic_share_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
context.shareText(txUrl)
|
||||
onShareClick()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 328)
|
||||
@Preview(showBackground = true, widthDp = 328, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun SendDoneButtons_Preview() {
|
||||
TangemThemePreview {
|
||||
SendDoneButtons(
|
||||
txUrl = "txUrl",
|
||||
onShareClick = {},
|
||||
onExploreClick = {},
|
||||
isVisible = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,7 @@ internal fun InputRowImageBase(
|
|||
InputRowAsyncImage(
|
||||
imageUrl = imageUrl,
|
||||
modifier = Modifier
|
||||
.size(TangemTheme.dimens.spacing36)
|
||||
.padding(vertical = TangemTheme.dimens.size1),
|
||||
.size(TangemTheme.dimens.spacing36),
|
||||
)
|
||||
Column {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ fun InputRowImageChevron(
|
|||
modifier: Modifier = Modifier,
|
||||
subtitleColor: Color = TangemTheme.colors.text.primary1,
|
||||
captionColor: Color = TangemTheme.colors.text.tertiary,
|
||||
showChevron: Boolean = true,
|
||||
) {
|
||||
InputRowImageBase(
|
||||
subtitle = subtitle,
|
||||
|
|
@ -45,11 +46,13 @@ fun InputRowImageChevron(
|
|||
captionColor = captionColor,
|
||||
) {
|
||||
SpacerWMax()
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_chevron_right_24),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
if (showChevron) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_chevron_right_24),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.atoms.radiobutton.TangemRadioButton
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.annotatedReference
|
||||
|
|
@ -65,13 +66,14 @@ fun InputRowImageSelector(
|
|||
)
|
||||
.padding(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
SpacerWMax()
|
||||
TangemRadioButton(isSelected = isSelected, isEnabled = false, onClick = onSelect)
|
||||
}
|
||||
}
|
||||
|
||||
//region preview
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Preview(widthDp = 328)
|
||||
@Preview(widthDp = 328, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun InputRowImageSelectorPreview(
|
||||
@PreviewParameter(InputRowImageSelectorPreviewDataProvider::class) data: InputRowImageSelectorPreviewData,
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ data class TangemDimens internal constructor(
|
|||
val spacing30: Dp = 30.dp,
|
||||
val spacing32: Dp = 32.dp,
|
||||
val spacing34: Dp = 34.dp,
|
||||
val spacing36: Dp = 34.dp,
|
||||
val spacing36: Dp = 36.dp,
|
||||
val spacing38: Dp = 38.dp,
|
||||
val spacing40: Dp = 40.dp,
|
||||
val spacing44: Dp = 44.dp,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
class GetExplorerTransactionUrlUseCase(
|
||||
private val repository: TxHistoryRepository,
|
||||
) {
|
||||
@Deprecated("Replace with invoke [UserWalletId, Network]")
|
||||
operator fun invoke(txHash: String, networkId: Network.ID): Either<TxStatusError, String> {
|
||||
return either {
|
||||
catch(
|
||||
|
|
|
|||
|
|
@ -16,17 +16,16 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.ui.SendDoneButtons
|
||||
import com.tangem.common.ui.amountScreen.utils.getCryptoReference
|
||||
import com.tangem.common.ui.amountScreen.utils.getFiatString
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.Keyboard
|
||||
import com.tangem.core.ui.components.SecondaryButtonIconStart
|
||||
import com.tangem.core.ui.components.SpacerW12
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
|
|
@ -220,46 +219,6 @@ private fun SendingText(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SendDoneButtons(
|
||||
txUrl: String,
|
||||
onExploreClick: () -> Unit,
|
||||
onShareClick: () -> Unit,
|
||||
isVisible: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val context = LocalContext.current
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isVisible && txUrl.isNotBlank(),
|
||||
modifier = modifier,
|
||||
enter = slideInVertically().plus(fadeIn()),
|
||||
exit = slideOutVertically().plus(fadeOut()),
|
||||
label = "Animate show sent state buttons",
|
||||
) {
|
||||
Row(modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12)) {
|
||||
SecondaryButtonIconStart(
|
||||
text = stringResource(id = R.string.common_explore),
|
||||
iconResId = R.drawable.ic_web_24,
|
||||
onClick = onExploreClick,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
SpacerW12()
|
||||
SecondaryButtonIconStart(
|
||||
text = stringResource(id = R.string.common_share),
|
||||
iconResId = R.drawable.ic_share_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
context.shareText(txUrl)
|
||||
onShareClick()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getButtonData(
|
||||
uiState: SendUiState,
|
||||
currentState: SendUiCurrentScreen,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ dependencies {
|
|||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.transaction)
|
||||
implementation(projects.domain.txhistory)
|
||||
|
||||
/** Common */
|
||||
implementation(projects.common.ui)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.staking.impl.di
|
||||
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.features.staking.impl.navigation.DefaultStakingRouter
|
||||
import com.tangem.features.staking.api.navigation.StakingRouter
|
||||
import dagger.Module
|
||||
|
|
@ -17,7 +18,9 @@ internal object StakingRouterModule {
|
|||
|
||||
@Provides
|
||||
@ActivityScoped
|
||||
fun provideStakingRouter(): StakingRouter {
|
||||
return DefaultStakingRouter()
|
||||
fun provideStakingRouter(urlOpener: UrlOpener): StakingRouter {
|
||||
return DefaultStakingRouter(
|
||||
urlOpener = urlOpener,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,15 @@
|
|||
package com.tangem.features.staking.impl.navigation
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.features.staking.impl.presentation.StakingFragment
|
||||
|
||||
internal class DefaultStakingRouter : InnerStakingRouter {
|
||||
|
||||
internal class DefaultStakingRouter(
|
||||
private val urlOpener: UrlOpener,
|
||||
) : InnerStakingRouter {
|
||||
override fun getEntryFragment(): Fragment = StakingFragment.create()
|
||||
|
||||
override fun openUrl(url: String) {
|
||||
urlOpener.openUrl(url)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,5 +4,5 @@ import com.tangem.features.staking.api.navigation.StakingRouter
|
|||
|
||||
interface InnerStakingRouter : StakingRouter {
|
||||
|
||||
// TODO staking
|
||||
fun openUrl(url: String)
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.UiDependencies
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
|
|
@ -15,7 +16,6 @@ import com.tangem.features.staking.impl.presentation.state.StakingStateRouter
|
|||
import com.tangem.features.staking.impl.presentation.ui.StakingScreen
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
|
|
@ -28,7 +28,10 @@ internal class StakingFragment : ComposeFragment() {
|
|||
override lateinit var uiDependencies: UiDependencies
|
||||
|
||||
@Inject
|
||||
lateinit var router: StakingRouter
|
||||
lateinit var stakingRouter: StakingRouter
|
||||
|
||||
@Inject
|
||||
lateinit var appRouter: AppRouter
|
||||
|
||||
@Inject
|
||||
lateinit var stateController: StakingStateController
|
||||
|
|
@ -38,7 +41,7 @@ internal class StakingFragment : ComposeFragment() {
|
|||
|
||||
private val viewModel by viewModels<StakingViewModel>()
|
||||
private val innerStakingRouter: InnerStakingRouter
|
||||
get() = requireNotNull(router as? InnerStakingRouter) {
|
||||
get() = requireNotNull(stakingRouter as? InnerStakingRouter) {
|
||||
"innerStakingRouter should be instance of InnerStakingRouter"
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +52,7 @@ internal class StakingFragment : ComposeFragment() {
|
|||
viewModel.setRouter(
|
||||
innerStakingRouter,
|
||||
StakingStateRouter(
|
||||
fragmentManager = WeakReference(parentFragmentManager),
|
||||
appRouter = appRouter,
|
||||
stateController = stateController,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
enum class InnerConfirmationStakingState {
|
||||
ASSENT,
|
||||
IN_PROGRESS,
|
||||
COMPLETED,
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ internal class StakingStateController @Inject constructor() {
|
|||
initialInfoState = StakingStates.InitialInfoState.Empty(),
|
||||
amountState = AmountState.Empty(),
|
||||
rewardsValidatorsState = StakingStates.RewardsValidatorsState.Empty(),
|
||||
confirmStakingState = StakingStates.ConfirmStakingState.Empty(),
|
||||
confirmationState = StakingStates.ConfirmationState.Empty(),
|
||||
isBalanceHidden = false,
|
||||
event = consumedEvent(),
|
||||
bottomSheetConfig = null,
|
||||
|
|
|
|||
|
|
@ -1,49 +1,37 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import java.lang.ref.WeakReference
|
||||
import com.tangem.common.routing.AppRouter
|
||||
|
||||
internal class StakingStateRouter(
|
||||
private val fragmentManager: WeakReference<FragmentManager>,
|
||||
private val appRouter: AppRouter,
|
||||
private val stateController: StakingStateController,
|
||||
) {
|
||||
|
||||
private fun closeStaking() {
|
||||
fragmentManager.get()?.popBackStack()
|
||||
fun onBackClick() {
|
||||
appRouter.pop()
|
||||
stateController.clear()
|
||||
}
|
||||
|
||||
fun onBackClick(isSuccess: Boolean = false) {
|
||||
val type = stateController.uiState.value.currentStep
|
||||
when {
|
||||
isSuccess -> closeStaking()
|
||||
else -> when (type) {
|
||||
StakingStep.Amount -> showInitial()
|
||||
StakingStep.Confirm -> showAmount()
|
||||
else -> closeStaking()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onNextClick() {
|
||||
when (stateController.uiState.value.currentStep) {
|
||||
StakingStep.InitialInfo -> showAmount()
|
||||
StakingStep.RewardsValidators,
|
||||
StakingStep.Validators,
|
||||
StakingStep.Amount,
|
||||
-> showConfirm()
|
||||
StakingStep.Confirm -> showSuccess()
|
||||
StakingStep.Success -> closeStaking()
|
||||
-> showConfirmation()
|
||||
StakingStep.Confirmation -> {
|
||||
// TODO staking handle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onPrevClick() {
|
||||
when (stateController.uiState.value.currentStep) {
|
||||
StakingStep.InitialInfo -> onBackClick()
|
||||
StakingStep.Amount -> showInitial()
|
||||
StakingStep.Confirm -> showAmount()
|
||||
StakingStep.Success -> closeStaking()
|
||||
StakingStep.Validators -> showConfirm()
|
||||
else -> closeStaking()
|
||||
StakingStep.Confirmation -> showAmount()
|
||||
StakingStep.Validators -> showConfirmation()
|
||||
StakingStep.RewardsValidators -> showInitial()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,12 +51,7 @@ internal class StakingStateRouter(
|
|||
stateController.update { it.copy(currentStep = StakingStep.Validators) }
|
||||
}
|
||||
|
||||
fun showConfirm() {
|
||||
stateController.update { it.copy(currentStep = StakingStep.Confirm) }
|
||||
}
|
||||
|
||||
fun showSuccess() {
|
||||
// stateController.update { it.copy(currentStep = StakingStep.Success) }
|
||||
// TODO staking [REDACTED_TASK_KEY]
|
||||
fun showConfirmation() {
|
||||
stateController.update { it.copy(currentStep = StakingStep.Confirmation) }
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ internal data class StakingUiState(
|
|||
val initialInfoState: StakingStates.InitialInfoState,
|
||||
val amountState: AmountState,
|
||||
val rewardsValidatorsState: StakingStates.RewardsValidatorsState,
|
||||
val confirmStakingState: StakingStates.ConfirmStakingState,
|
||||
val confirmationState: StakingStates.ConfirmationState,
|
||||
val isBalanceHidden: Boolean,
|
||||
val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
val event: StateEvent<StakingEvent>,
|
||||
|
|
@ -29,11 +29,11 @@ internal data class StakingUiState(
|
|||
fun copyWrapped(
|
||||
initialInfoState: StakingStates.InitialInfoState = this.initialInfoState,
|
||||
amountState: AmountState = this.amountState,
|
||||
confirmStakingState: StakingStates.ConfirmStakingState = this.confirmStakingState,
|
||||
confirmationState: StakingStates.ConfirmationState = this.confirmationState,
|
||||
): StakingUiState = copy(
|
||||
initialInfoState = initialInfoState,
|
||||
amountState = amountState,
|
||||
confirmStakingState = confirmStakingState,
|
||||
confirmationState = confirmationState,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -74,27 +74,21 @@ internal sealed class StakingStates {
|
|||
) : RewardsValidatorsState()
|
||||
}
|
||||
|
||||
/** Confirm state */
|
||||
sealed class ConfirmStakingState : StakingStates() {
|
||||
/** Confirmation state */
|
||||
sealed class ConfirmationState : StakingStates() {
|
||||
data class Data(
|
||||
override val isPrimaryButtonEnabled: Boolean,
|
||||
val innerState: InnerConfirmationStakingState,
|
||||
val feeState: FeeState,
|
||||
val validatorState: ValidatorState,
|
||||
val notifications: ImmutableList<StakingNotification>,
|
||||
val footerText: String,
|
||||
val innerState: InnerConfirmStakingState,
|
||||
) : ConfirmStakingState() {
|
||||
|
||||
enum class InnerConfirmStakingState {
|
||||
CONFIRM,
|
||||
IN_PROGRESS,
|
||||
SUCCESS,
|
||||
}
|
||||
}
|
||||
val transactionDoneState: TransactionDoneState,
|
||||
) : ConfirmationState()
|
||||
|
||||
data class Empty(
|
||||
override val isPrimaryButtonEnabled: Boolean = false,
|
||||
) : ConfirmStakingState()
|
||||
) : ConfirmationState()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +96,6 @@ enum class StakingStep {
|
|||
InitialInfo,
|
||||
RewardsValidators,
|
||||
Amount,
|
||||
Confirm,
|
||||
Confirmation,
|
||||
Validators,
|
||||
Success,
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.features.staking.impl.presentation.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
internal sealed class TransactionDoneState {
|
||||
|
||||
data class Content(
|
||||
val timestamp: Long,
|
||||
val txUrl: String,
|
||||
) : TransactionDoneState()
|
||||
|
||||
data object Empty : TransactionDoneState()
|
||||
}
|
||||
|
|
@ -6,12 +6,29 @@ import com.tangem.domain.staking.model.Yield
|
|||
@Immutable
|
||||
internal sealed class ValidatorState {
|
||||
|
||||
abstract val isClickable: Boolean
|
||||
|
||||
data class Content(
|
||||
override val isClickable: Boolean,
|
||||
val chosenValidator: Yield.Validator,
|
||||
val availableValidators: List<Yield.Validator>,
|
||||
) : ValidatorState()
|
||||
|
||||
data object Loading : ValidatorState()
|
||||
data object Loading : ValidatorState() {
|
||||
override val isClickable: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
data object Error : ValidatorState()
|
||||
data object Error : ValidatorState() {
|
||||
override val isClickable: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
fun copySealed(isClickable: Boolean): ValidatorState {
|
||||
return if (this is Content) {
|
||||
copy(isClickable = isClickable)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import com.tangem.features.staking.impl.presentation.state.ValidatorState
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal object ConfirmStakingStatePreviewData {
|
||||
internal object ConfirmationStatePreviewData {
|
||||
|
||||
private val validatorList = listOf(
|
||||
Yield.Validator(
|
||||
|
|
@ -62,8 +62,9 @@ internal object ConfirmStakingStatePreviewData {
|
|||
),
|
||||
)
|
||||
|
||||
val confirmStakingState = StakingStates.ConfirmStakingState.Data(
|
||||
val assentStakingState = StakingStates.ConfirmationState.Data(
|
||||
isPrimaryButtonEnabled = true,
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
feeState = FeeState.Content(
|
||||
fee = fee,
|
||||
rate = BigDecimal.ONE,
|
||||
|
|
@ -72,6 +73,7 @@ internal object ConfirmStakingStatePreviewData {
|
|||
isFeeConvertibleToFiat = true,
|
||||
),
|
||||
validatorState = ValidatorState.Content(
|
||||
isClickable = true,
|
||||
chosenValidator = validatorList[0],
|
||||
availableValidators = validatorList,
|
||||
),
|
||||
|
|
@ -82,6 +84,6 @@ internal object ConfirmStakingStatePreviewData {
|
|||
days = 2,
|
||||
),
|
||||
),
|
||||
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM,
|
||||
transactionDoneState = TransactionDoneState.Empty,
|
||||
)
|
||||
}
|
||||
|
|
@ -31,4 +31,8 @@ object StakingClickIntentsStub : StakingClickIntents {
|
|||
override fun openRewardsValidators() {}
|
||||
|
||||
override fun selectRewardValidator(rewardValue: String) {}
|
||||
|
||||
override fun onExploreClick() {}
|
||||
|
||||
override fun onShareClick() {}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class SetConfirmStateInProgressTransformer : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmStakingState = prevState.confirmStakingState.copyWrapped(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun StakingStates.ConfirmStakingState.copyWrapped(): StakingStates.ConfirmStakingState {
|
||||
return if (this is StakingStates.ConfirmStakingState.Data) {
|
||||
copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.IN_PROGRESS,
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,9 +10,10 @@ import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
|||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class SetConfirmStateConfirmTransformer(
|
||||
internal class SetConfirmationStateAssentTransformer(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val stakingGasEstimate: StakingGasEstimate,
|
||||
|
|
@ -20,15 +21,16 @@ internal class SetConfirmStateConfirmTransformer(
|
|||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmStakingState = prevState.confirmStakingState.copyWrapped(stakingGasEstimate),
|
||||
confirmationState = prevState.confirmationState.copyWrapped(stakingGasEstimate),
|
||||
)
|
||||
}
|
||||
|
||||
private fun StakingStates.ConfirmStakingState.copyWrapped(
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(
|
||||
gasEstimate: StakingGasEstimate,
|
||||
): StakingStates.ConfirmStakingState {
|
||||
if (this is StakingStates.ConfirmStakingState.Data) {
|
||||
): StakingStates.ConfirmationState {
|
||||
if (this is StakingStates.ConfirmationState.Data) {
|
||||
return copy(
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
feeState = FeeState.Content(
|
||||
fee = Fee.Common(
|
||||
Amount(
|
||||
|
|
@ -42,8 +44,8 @@ internal class SetConfirmStateConfirmTransformer(
|
|||
appCurrency = appCurrencyProvider(),
|
||||
isFeeApproximate = false,
|
||||
),
|
||||
validatorState = validatorState.copySealed(isClickable = true),
|
||||
isPrimaryButtonEnabled = true,
|
||||
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM,
|
||||
)
|
||||
} else {
|
||||
return this
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.transaction.StakingGasEstimate
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.features.staking.impl.presentation.state.TransactionDoneState
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class SetConfirmationStateCompletedTransformer(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val stakingGasEstimate: StakingGasEstimate,
|
||||
private val txUrl: String,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmationState = prevState.confirmationState.copyWrapped(stakingGasEstimate),
|
||||
)
|
||||
}
|
||||
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(
|
||||
gasEstimate: StakingGasEstimate,
|
||||
): StakingStates.ConfirmationState {
|
||||
if (this is StakingStates.ConfirmationState.Data) {
|
||||
return copy(
|
||||
isPrimaryButtonEnabled = true,
|
||||
innerState = InnerConfirmationStakingState.COMPLETED,
|
||||
feeState = FeeState.Content(
|
||||
fee = Fee.Common(
|
||||
Amount(
|
||||
currencySymbol = gasEstimate.token.symbol,
|
||||
value = gasEstimate.amount,
|
||||
decimals = gasEstimate.token.decimals,
|
||||
),
|
||||
),
|
||||
rate = cryptoCurrencyStatusProvider().value.fiatRate,
|
||||
isFeeConvertibleToFiat = cryptoCurrencyStatusProvider().currency.network.hasFiatFeeRate,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
isFeeApproximate = false,
|
||||
),
|
||||
validatorState = validatorState.copySealed(
|
||||
isClickable = false,
|
||||
),
|
||||
transactionDoneState = TransactionDoneState.Content(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
txUrl = txUrl,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class SetConfirmationStateInProgressTransformer : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
confirmationState = prevState.confirmationState.copyWrapped(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun StakingStates.ConfirmationState.copyWrapped(): StakingStates.ConfirmationState {
|
||||
return if (this is StakingStates.ConfirmationState.Data) {
|
||||
copy(
|
||||
isPrimaryButtonEnabled = false,
|
||||
innerState = InnerConfirmationStakingState.IN_PROGRESS,
|
||||
validatorState = validatorState.copySealed(isClickable = false),
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,20 +10,22 @@ import com.tangem.utils.transformer.Transformer
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class SetConfirmStateLoadingTransformer(
|
||||
internal class SetConfirmationStateLoadingTransformer(
|
||||
private val yield: Yield,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val possibleConfirmStakingState = prevState.confirmStakingState as? StakingStates.ConfirmStakingState.Data
|
||||
val possibleValidatorState = possibleConfirmStakingState?.validatorState as? ValidatorState.Content
|
||||
val possibleConfirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data
|
||||
val possibleValidatorState = possibleConfirmationState?.validatorState as? ValidatorState.Content
|
||||
val chosenValidator = possibleValidatorState?.chosenValidator ?: yield.validators[0]
|
||||
|
||||
return prevState.copy(
|
||||
confirmStakingState = StakingStates.ConfirmStakingState.Data(
|
||||
confirmationState = StakingStates.ConfirmationState.Data(
|
||||
isPrimaryButtonEnabled = false,
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
feeState = FeeState.Loading,
|
||||
validatorState = ValidatorState.Content(
|
||||
isClickable = false,
|
||||
chosenValidator = chosenValidator,
|
||||
availableValidators = yield.validators,
|
||||
),
|
||||
|
|
@ -34,7 +36,7 @@ internal class SetConfirmStateLoadingTransformer(
|
|||
),
|
||||
),
|
||||
footerText = "",
|
||||
innerState = StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM,
|
||||
transactionDoneState = TransactionDoneState.Empty,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.common.extensions.remove
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
|
|
@ -20,7 +21,7 @@ import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
|||
import com.tangem.features.staking.impl.presentation.state.ValidatorState
|
||||
import com.tangem.features.staking.impl.presentation.state.converters.RewardsValidatorStateConverter
|
||||
import com.tangem.features.staking.impl.presentation.state.converters.YieldBalancesConverter
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmationStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.extensions.orZero
|
||||
|
|
@ -61,7 +62,7 @@ internal class SetInitialDataStateTransformer(
|
|||
currentStep = StakingStep.InitialInfo,
|
||||
initialInfoState = createInitialInfoState(),
|
||||
amountState = createInitialAmountState(),
|
||||
confirmStakingState = createInitialConfirmationState(),
|
||||
confirmationState = createInitialConfirmationState(),
|
||||
rewardsValidatorsState = rewardsValidatorStateConverter.convert(Unit),
|
||||
bottomSheetConfig = null,
|
||||
)
|
||||
|
|
@ -98,9 +99,10 @@ internal class SetInitialDataStateTransformer(
|
|||
return amountStateConverter.convert("")
|
||||
}
|
||||
|
||||
private fun createInitialConfirmationState(): StakingStates.ConfirmStakingState {
|
||||
return ConfirmStakingStatePreviewData.confirmStakingState.copy(
|
||||
private fun createInitialConfirmationState(): StakingStates.ConfirmationState {
|
||||
return ConfirmationStatePreviewData.assentStakingState.copy(
|
||||
validatorState = ValidatorState.Content(
|
||||
isClickable = true,
|
||||
chosenValidator = yield.validators.first(),
|
||||
availableValidators = yield.validators,
|
||||
),
|
||||
|
|
@ -116,7 +118,7 @@ internal class SetInitialDataStateTransformer(
|
|||
val formattedMinApr = BigDecimalFormatter.formatPercent(
|
||||
percent = minApr,
|
||||
useAbsoluteValue = true,
|
||||
)
|
||||
).remove("%")
|
||||
val formattedMaxApr = BigDecimalFormatter.formatPercent(
|
||||
percent = maxApr,
|
||||
useAbsoluteValue = true,
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ internal class ValidatorSelectChangeTransformer(
|
|||
private val selectedValidator: Yield.Validator,
|
||||
) : Transformer<StakingUiState> {
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val confirmState = prevState.confirmStakingState as? StakingStates.ConfirmStakingState.Data ?: return prevState
|
||||
val validatorState = confirmState.validatorState as? ValidatorState.Content ?: return prevState
|
||||
val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data ?: return prevState
|
||||
val validatorState = confirmationState.validatorState as? ValidatorState.Content ?: return prevState
|
||||
|
||||
return prevState.copy(
|
||||
confirmStakingState = confirmState.copy(
|
||||
confirmationState = confirmationState.copy(
|
||||
validatorState = validatorState.copy(
|
||||
chosenValidator = selectedValidator,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.staking.impl.presentation.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
|
|
@ -14,23 +15,26 @@ import com.tangem.common.ui.amountScreen.models.AmountState
|
|||
import com.tangem.common.ui.amountScreen.preview.AmountStatePreviewData
|
||||
import com.tangem.common.ui.amountScreen.ui.AmountBlock
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmationStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.NotificationsBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.StakingFeeBlock
|
||||
import com.tangem.features.staking.impl.presentation.ui.block.ValidatorBlock
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.TransactionDoneState
|
||||
|
||||
@Composable
|
||||
internal fun StakingConfirmContent(
|
||||
internal fun StakingConfirmationContent(
|
||||
amountState: AmountState,
|
||||
state: StakingStates.ConfirmStakingState,
|
||||
state: StakingStates.ConfirmationState,
|
||||
clickIntents: StakingClickIntents,
|
||||
) {
|
||||
if (state !is StakingStates.ConfirmStakingState.Data) return
|
||||
if (state !is StakingStates.ConfirmationState.Data) return
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
|
@ -40,6 +44,16 @@ internal fun StakingConfirmContent(
|
|||
.verticalScroll(rememberScrollState()),
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = state.transactionDoneState is TransactionDoneState.Content,
|
||||
modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
val transactionDoneStateContent = state.transactionDoneState as TransactionDoneState.Content
|
||||
TransactionDoneTitle(
|
||||
titleRes = R.string.sent_transaction_sent_title,
|
||||
date = transactionDoneStateContent.timestamp,
|
||||
)
|
||||
}
|
||||
AmountBlock(
|
||||
amountState = amountState,
|
||||
isClickDisabled = true,
|
||||
|
|
@ -68,12 +82,12 @@ private fun FooterText(text: String) {
|
|||
@Preview(widthDp = 360, showBackground = true)
|
||||
@Preview(widthDp = 360, showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview_StakingConfirmContent() {
|
||||
private fun Preview_StakingConfirmationContent() {
|
||||
TangemThemePreview {
|
||||
Column(Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
StakingConfirmContent(
|
||||
StakingConfirmationContent(
|
||||
amountState = AmountStatePreviewData.amountState,
|
||||
state = ConfirmStakingStatePreviewData.confirmStakingState,
|
||||
state = ConfirmationStatePreviewData.assentStakingState,
|
||||
clickIntents = StakingClickIntentsStub,
|
||||
)
|
||||
}
|
||||
|
|
@ -17,19 +17,22 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
|||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.common.ui.amountScreen.ui.SendDoneButtons
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SpacerW12
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerYieldBalanceState
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStep
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
|
||||
@Composable
|
||||
internal fun StakingNavigationButtons(uiState: StakingUiState, modifier: Modifier = Modifier) {
|
||||
val confirmInnerState = (uiState.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState
|
||||
val isSuccessState = confirmInnerState == InnerConfirmationStakingState.COMPLETED
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
|
|
@ -38,6 +41,15 @@ internal fun StakingNavigationButtons(uiState: StakingUiState, modifier: Modifie
|
|||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
) {
|
||||
val confirmationDataState = uiState.confirmationState as? StakingStates.ConfirmationState.Data
|
||||
val transactionDoneState = confirmationDataState?.transactionDoneState as? TransactionDoneState.Content
|
||||
|
||||
SendDoneButtons(
|
||||
txUrl = transactionDoneState?.txUrl.orEmpty(),
|
||||
onExploreClick = uiState.clickIntents::onExploreClick,
|
||||
onShareClick = uiState.clickIntents::onShareClick,
|
||||
isVisible = isSuccessState,
|
||||
)
|
||||
StakingNavigationButton(
|
||||
uiState = uiState,
|
||||
modifier = Modifier,
|
||||
|
|
@ -50,13 +62,19 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
|||
val hapticFeedback = LocalHapticFeedback.current
|
||||
|
||||
val isButtonsVisible = isPrevButtonVisible(uiState.currentStep)
|
||||
val isStakingState = uiState.currentStep == StakingStep.Confirm
|
||||
|
||||
val innerConfirmState = (uiState.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState
|
||||
val isInProgressInnerState = innerConfirmState == InnerConfirmationStakingState.IN_PROGRESS
|
||||
val isInAssentInnerState = innerConfirmState == InnerConfirmationStakingState.ASSENT
|
||||
|
||||
val showTangemIcon = uiState.currentStep == StakingStep.Confirmation &&
|
||||
(isInProgressInnerState || isInAssentInnerState)
|
||||
|
||||
val (buttonTextId, buttonClick) = getButtonData(
|
||||
currentState = uiState,
|
||||
)
|
||||
val isButtonEnabled = isButtonEnabled(uiState)
|
||||
val buttonIcon = if (isStakingState) {
|
||||
val buttonIcon = if (showTangemIcon) {
|
||||
TangemButtonIconPosition.End(R.drawable.ic_tangem_24)
|
||||
} else {
|
||||
TangemButtonIconPosition.None
|
||||
|
|
@ -82,7 +100,6 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
|||
SpacerW12()
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = buttonClick != null,
|
||||
enter = fadeIn(),
|
||||
|
|
@ -93,7 +110,7 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
|||
icon = buttonIcon,
|
||||
enabled = isButtonEnabled && buttonClick != null,
|
||||
onClick = {
|
||||
if (isStakingState) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
if (showTangemIcon) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
if (buttonClick != null) buttonClick()
|
||||
},
|
||||
showProgress = false,
|
||||
|
|
@ -116,18 +133,27 @@ private fun getButtonData(currentState: StakingUiState): Pair<Int, (() -> Unit)?
|
|||
}
|
||||
StakingStep.Amount,
|
||||
-> R.string.common_next to currentState.clickIntents::onNextClick
|
||||
StakingStep.Confirm -> R.string.common_stake to currentState.clickIntents::onNextClick
|
||||
StakingStep.Confirmation -> {
|
||||
val confirmationState = currentState.confirmationState
|
||||
if (confirmationState is StakingStates.ConfirmationState.Data) {
|
||||
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
|
||||
R.string.common_close to currentState.clickIntents::onBackClick
|
||||
} else {
|
||||
R.string.common_stake to currentState.clickIntents::onNextClick
|
||||
}
|
||||
} else {
|
||||
R.string.common_close to currentState.clickIntents::onBackClick
|
||||
}
|
||||
}
|
||||
StakingStep.Validators -> R.string.common_continue to currentState.clickIntents::onNextClick
|
||||
StakingStep.Success -> R.string.common_close to currentState.clickIntents::onBackClick
|
||||
else -> R.string.common_next to null
|
||||
StakingStep.RewardsValidators -> R.string.common_next to null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPrevButtonVisible(step: StakingStep): Boolean = when (step) {
|
||||
StakingStep.InitialInfo,
|
||||
StakingStep.RewardsValidators,
|
||||
StakingStep.Confirm,
|
||||
StakingStep.Success,
|
||||
StakingStep.Confirmation,
|
||||
-> false
|
||||
StakingStep.Amount,
|
||||
StakingStep.Validators,
|
||||
|
|
@ -138,9 +164,8 @@ private fun isButtonEnabled(uiState: StakingUiState): Boolean {
|
|||
return when (uiState.currentStep) {
|
||||
StakingStep.InitialInfo -> uiState.initialInfoState.isPrimaryButtonEnabled
|
||||
StakingStep.Amount -> uiState.amountState.isPrimaryButtonEnabled
|
||||
StakingStep.Confirm -> uiState.confirmStakingState.isPrimaryButtonEnabled
|
||||
StakingStep.Confirmation -> uiState.confirmationState.isPrimaryButtonEnabled
|
||||
StakingStep.RewardsValidators -> uiState.rewardsValidatorsState.isPrimaryButtonEnabled
|
||||
StakingStep.Success -> true
|
||||
StakingStep.Validators -> true
|
||||
}
|
||||
}
|
||||
|
|
@ -67,15 +67,13 @@ private fun SendAppBar(uiState: StakingUiState) {
|
|||
StakingStep.InitialInfo,
|
||||
StakingStep.RewardsValidators,
|
||||
StakingStep.Validators,
|
||||
StakingStep.Confirm,
|
||||
StakingStep.Confirmation,
|
||||
-> stringResource(id = R.string.common_stake)
|
||||
StakingStep.Success -> ""
|
||||
}
|
||||
val backIcon = when (uiState.currentStep) {
|
||||
StakingStep.Amount,
|
||||
StakingStep.Validators,
|
||||
StakingStep.Confirm,
|
||||
StakingStep.Success,
|
||||
StakingStep.Confirmation,
|
||||
-> {
|
||||
R.drawable.ic_close_24
|
||||
}
|
||||
|
|
@ -153,20 +151,19 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
|
|||
isBalanceHiding = uiState.isBalanceHidden,
|
||||
clickIntents = uiState.clickIntents,
|
||||
)
|
||||
StakingStep.Confirm -> StakingConfirmContent(
|
||||
StakingStep.Confirmation -> StakingConfirmationContent(
|
||||
amountState = uiState.amountState,
|
||||
state = uiState.confirmStakingState,
|
||||
state = uiState.confirmationState,
|
||||
clickIntents = uiState.clickIntents,
|
||||
)
|
||||
StakingStep.Validators -> {
|
||||
val confirmState = uiState.confirmStakingState
|
||||
if (confirmState !is StakingStates.ConfirmStakingState.Data) return@AnimatedContent
|
||||
val confirmState = uiState.confirmationState
|
||||
if (confirmState !is StakingStates.ConfirmationState.Data) return@AnimatedContent
|
||||
StakingValidatorListContent(
|
||||
state = confirmState.validatorState,
|
||||
clickIntents = uiState.clickIntents,
|
||||
)
|
||||
}
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import com.tangem.core.ui.res.TangemThemePreview
|
|||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.ValidatorState
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmStakingStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.previewdata.ConfirmationStatePreviewData
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
|
||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -124,6 +124,6 @@ private fun StakingValidatorListContent_Preview(
|
|||
|
||||
private class StakingValidatorListContentPreviewProvider : PreviewParameterProvider<ValidatorState> {
|
||||
override val values: Sequence<ValidatorState>
|
||||
get() = sequenceOf(ConfirmStakingStatePreviewData.confirmStakingState.validatorState)
|
||||
get() = sequenceOf(ConfirmationStatePreviewData.assentStakingState.validatorState)
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -35,6 +35,7 @@ internal fun ValidatorBlock(validatorState: ValidatorState, onClick: () -> Unit)
|
|||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.action)
|
||||
.clickable(
|
||||
enabled = validatorState.isClickable,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
onClick = onClick,
|
||||
|
|
@ -63,6 +64,7 @@ internal fun ValidatorBlock(validatorState: ValidatorState, onClick: () -> Unit)
|
|||
),
|
||||
),
|
||||
imageUrl = validatorState.chosenValidator.image.orEmpty(),
|
||||
showChevron = validatorState.isClickable,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,4 +23,8 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
|
|||
fun openRewardsValidators()
|
||||
|
||||
fun selectRewardValidator(rewardValue: String)
|
||||
|
||||
fun onExploreClick()
|
||||
|
||||
fun onShareClick()
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase
|
|||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
|
|
@ -56,6 +57,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val initializeStakingProcessUseCase: InitializeStakingProcessUseCase,
|
||||
private val sendTransactionUseCase: SendTransactionUseCase,
|
||||
private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), DefaultLifecycleObserver, StakingClickIntents {
|
||||
|
||||
|
|
@ -97,18 +99,15 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onNextClick() {
|
||||
handleOnNextConfirmClick()
|
||||
handleOnNextConfirmationClick()
|
||||
stakingStateRouter.onNextClick()
|
||||
if (value.currentStep == StakingStep.Confirm) {
|
||||
if (isAssentState()) {
|
||||
initStaking()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleOnNextConfirmClick() {
|
||||
if (value.currentStep == StakingStep.Confirm &&
|
||||
(value.confirmStakingState as? StakingStates.ConfirmStakingState.Data)?.innerState ==
|
||||
StakingStates.ConfirmStakingState.Data.InnerConfirmStakingState.CONFIRM
|
||||
) {
|
||||
private fun handleOnNextConfirmationClick() {
|
||||
if (isAssentState()) {
|
||||
viewModelScope.launch {
|
||||
stakingTransaction?.unsignedTransaction?.let {
|
||||
sendStakingTransaction(TransactionData.Compiled(value = it.hexToBytes()))
|
||||
|
|
@ -120,7 +119,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
private fun initStaking() {
|
||||
viewModelScope.launch {
|
||||
stateController.update(
|
||||
SetConfirmStateLoadingTransformer(
|
||||
SetConfirmationStateLoadingTransformer(
|
||||
yield = yield,
|
||||
),
|
||||
)
|
||||
|
|
@ -144,7 +143,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
val stakingGasEstimate = stakingTransaction.gasEstimate ?: error("Can't get fee info")
|
||||
|
||||
stateController.update(
|
||||
SetConfirmStateConfirmTransformer(
|
||||
SetConfirmationStateAssentTransformer(
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
stakingGasEstimate = stakingGasEstimate,
|
||||
|
|
@ -196,6 +195,20 @@ internal class StakingViewModel @Inject constructor(
|
|||
stakingStateRouter.onNextClick()
|
||||
}
|
||||
|
||||
override fun onExploreClick() {
|
||||
val confirmationDataState = uiState.value.confirmationState as? StakingStates.ConfirmationState.Data
|
||||
val transactionDoneState = confirmationDataState?.transactionDoneState as? TransactionDoneState.Content
|
||||
val txUrl = transactionDoneState?.txUrl
|
||||
|
||||
if (txUrl != null) {
|
||||
innerRouter.openUrl(txUrl)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onShareClick() {
|
||||
// TODO staking analytics event
|
||||
}
|
||||
|
||||
fun setRouter(router: InnerStakingRouter, stateRouter: StakingStateRouter) {
|
||||
innerRouter = router
|
||||
this.stakingStateRouter = stateRouter
|
||||
|
|
@ -254,7 +267,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun sendStakingTransaction(txData: TransactionData) {
|
||||
stateController.update(SetConfirmStateInProgressTransformer())
|
||||
stateController.update(SetConfirmationStateInProgressTransformer())
|
||||
|
||||
sendTransactionUseCase(
|
||||
txData = txData,
|
||||
|
|
@ -265,29 +278,35 @@ internal class StakingViewModel @Inject constructor(
|
|||
Timber.e(error.toString())
|
||||
val gasEstimate = stakingTransaction?.gasEstimate ?: return@fold
|
||||
stateController.update(
|
||||
SetConfirmStateConfirmTransformer(
|
||||
SetConfirmationStateAssentTransformer(
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
stakingGasEstimate = gasEstimate,
|
||||
),
|
||||
)
|
||||
// uiState = eventStateFactory.getSendTransactionErrorState(
|
||||
// error = error,
|
||||
// onConsume = { uiState = eventStateFactory.onConsumeEventState() },
|
||||
// )
|
||||
// analyticsEventHandler.send(SendAnalyticEvents.TransactionError(cryptoCurrency.symbol))
|
||||
},
|
||||
ifRight = {
|
||||
ifRight = { txHash ->
|
||||
val gasEstimate = stakingTransaction?.gasEstimate ?: return@fold
|
||||
|
||||
val txUrl = getExplorerTransactionUrlUseCase(
|
||||
txHash = txHash,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
).getOrElse { "" }
|
||||
stateController.update(
|
||||
SetConfirmStateConfirmTransformer(
|
||||
SetConfirmationStateCompletedTransformer(
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
stakingGasEstimate = gasEstimate,
|
||||
txUrl = txUrl,
|
||||
),
|
||||
)
|
||||
// sendScreenAnalyticSender.sendTransaction()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun isAssentState(): Boolean {
|
||||
return value.currentStep == StakingStep.Confirmation &&
|
||||
(value.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState ==
|
||||
InnerConfirmationStakingState.ASSENT
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue