Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-21 14:14:24 +02:00
parent 3e900b5d5b
commit 33efe2ae52
12 changed files with 56 additions and 101 deletions

View file

@ -323,7 +323,9 @@ fun BoxScope.FooterOverlay(
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.BottomCenter), .align(Alignment.BottomCenter),
) { ) {
if (gradientHeight > 0.dp) { val isGradientDisplayed = gradientHeight > 0.dp
if (isGradientDisplayed) {
Fade( Fade(
backgroundColor = fadeMax, backgroundColor = fadeMax,
height = gradientHeight, height = gradientHeight,
@ -333,7 +335,7 @@ fun BoxScope.FooterOverlay(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(measuredFooterHeight ?: 0.dp) .height(measuredFooterHeight ?: 0.dp)
.background(fadeMax), .background(if (isGradientDisplayed) fadeMax else Color.Transparent),
) )
} }
} }

View file

@ -21,7 +21,6 @@ import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R import com.tangem.core.ui.R
import com.tangem.core.ui.components.* import com.tangem.core.ui.components.*
@ -39,9 +38,6 @@ import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.utils.WindowInsetsZero import com.tangem.core.ui.utils.WindowInsetsZero
import com.tangem.core.ui.utils.toPx import com.tangem.core.ui.utils.toPx
/** Default reserved height for the [TangemModalBottomSheetWithFooter] footer slot. */
val DEFAULT_FOOTER_HEIGHT: Dp = 80.dp
/** /**
* Modal bottom sheet with [content], [footer] and optional [title]. * Modal bottom sheet with [content], [footer] and optional [title].
* *
@ -54,12 +50,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> TangemModalBottomSheetWi
config: TangemBottomSheetConfig, config: TangemBottomSheetConfig,
containerColor: Color = TangemTheme.colors.background.primary, containerColor: Color = TangemTheme.colors.background.primary,
skipPartiallyExpanded: Boolean = true, skipPartiallyExpanded: Boolean = true,
// FIXME([REDACTED_TASK_KEY]): temp workaround
// The footer slot reserves a fixed [DEFAULT_FOOTER_HEIGHT];
// callers whose footer differs must pass the real height explicitly. Exposed as an opt-in
// parameter so existing usages keep the previous behavior and nothing else is affected.
// Rework so the sheet measures the actual footer height internally and drops this parameter.
footerHeight: Dp = DEFAULT_FOOTER_HEIGHT,
noinline onBack: (() -> Unit)? = null, noinline onBack: (() -> Unit)? = null,
crossinline title: @Composable BoxScope.(T) -> Unit = {}, crossinline title: @Composable BoxScope.(T) -> Unit = {},
crossinline content: @Composable (T) -> Unit, crossinline content: @Composable (T) -> Unit,
@ -75,7 +65,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> TangemModalBottomSheetWi
content = content, content = content,
footer = footer, footer = footer,
skipPartiallyExpanded = skipPartiallyExpanded, skipPartiallyExpanded = skipPartiallyExpanded,
footerHeight = footerHeight,
) )
} else { } else {
DefaultModalBottomSheetWithFooter<T>( DefaultModalBottomSheetWithFooter<T>(
@ -86,7 +75,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> TangemModalBottomSheetWi
footer = footer, footer = footer,
onBack = onBack, onBack = onBack,
skipPartiallyExpanded = skipPartiallyExpanded, skipPartiallyExpanded = skipPartiallyExpanded,
footerHeight = footerHeight,
) )
} }
} }
@ -97,7 +85,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> DefaultModalBottomSheetW
config: TangemBottomSheetConfig, config: TangemBottomSheetConfig,
containerColor: Color, containerColor: Color,
skipPartiallyExpanded: Boolean = true, skipPartiallyExpanded: Boolean = true,
footerHeight: Dp = DEFAULT_FOOTER_HEIGHT,
noinline onBack: (() -> Unit)? = null, noinline onBack: (() -> Unit)? = null,
crossinline title: @Composable BoxScope.(T) -> Unit, crossinline title: @Composable BoxScope.(T) -> Unit,
crossinline content: @Composable (T) -> Unit, crossinline content: @Composable (T) -> Unit,
@ -130,7 +117,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> DefaultModalBottomSheetW
onBack = onBack, onBack = onBack,
content = content, content = content,
footer = footer, footer = footer,
footerHeight = footerHeight,
) )
} }
@ -149,7 +135,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> PreviewModalBottomSheetW
config: TangemBottomSheetConfig, config: TangemBottomSheetConfig,
containerColor: Color, containerColor: Color,
skipPartiallyExpanded: Boolean = true, skipPartiallyExpanded: Boolean = true,
footerHeight: Dp = DEFAULT_FOOTER_HEIGHT,
crossinline title: @Composable BoxScope.(T) -> Unit, crossinline title: @Composable BoxScope.(T) -> Unit,
crossinline content: @Composable (T) -> Unit, crossinline content: @Composable (T) -> Unit,
noinline footer: @Composable (BoxScope.(T) -> Unit)?, noinline footer: @Composable (BoxScope.(T) -> Unit)?,
@ -165,7 +150,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> PreviewModalBottomSheetW
title = title, title = title,
content = content, content = content,
footer = footer, footer = footer,
footerHeight = footerHeight,
) )
} }
@ -177,7 +161,6 @@ inline fun <reified T : TangemBottomSheetConfigContent> BasicModalBottomSheetWit
sheetState: TangemSheetState, sheetState: TangemSheetState,
containerColor: Color, containerColor: Color,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
footerHeight: Dp = DEFAULT_FOOTER_HEIGHT,
noinline onBack: (() -> Unit)? = null, noinline onBack: (() -> Unit)? = null,
crossinline title: @Composable BoxScope.(T) -> Unit, crossinline title: @Composable BoxScope.(T) -> Unit,
crossinline content: @Composable (T) -> Unit, crossinline content: @Composable (T) -> Unit,
@ -195,8 +178,7 @@ inline fun <reified T : TangemBottomSheetConfigContent> BasicModalBottomSheetWit
val isKeyboardOpen by rememberIsKeyboardVisible() val isKeyboardOpen by rememberIsKeyboardVisible()
val buttonHeight by animateDpAsState( val buttonHeight by animateDpAsState(
targetValue = if (footer != null) footerHeight else 0.dp, targetValue = if (footer != null) 80.dp else 0.dp,
label = "FooterHeight",
) )
// Offset calculation for keyboard scroll adjustment: // Offset calculation for keyboard scroll adjustment:
// 1) Button height (footer) // 1) Button height (footer)

View file

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.child import com.tangem.core.decompose.context.child
@ -29,7 +28,6 @@ internal class ActivateCampaignBottomSheetComponent(
chooseTokenComponentFactory: ChooseTokenComponent.Factory, chooseTokenComponentFactory: ChooseTokenComponent.Factory,
private val params: Params, private val params: Params,
val onDismiss: () -> Unit, val onDismiss: () -> Unit,
val onFooterExtraHeightReady: (Dp) -> Unit,
) : ComposableModularContentComponent, AppComponentContext by appComponentContext { ) : ComposableModularContentComponent, AppComponentContext by appComponentContext {
private val model: ActivateCampaignsModel = getOrCreateModel(params) private val model: ActivateCampaignsModel = getOrCreateModel(params)
@ -65,7 +63,6 @@ internal class ActivateCampaignBottomSheetComponent(
ActivateCampaignFooter( ActivateCampaignFooter(
footerUM = state.footerUM, footerUM = state.footerUM,
onFooterTextHeightReady = onFooterExtraHeightReady,
) )
} }

View file

@ -2,23 +2,31 @@ package com.tangem.features.promobanners.impl.campaigns.component
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.extensions.compose.subscribeAsState import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.arkivanov.decompose.router.slot.childSlot import com.arkivanov.decompose.router.slot.childSlot
import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.components.SpacerH32
import com.tangem.core.ui.components.bottomsheets.LocalBottomSheetContentScrollable
import com.tangem.core.ui.components.bottomsheets.LocalTangemBottomSheetContentBottomInset
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import com.tangem.core.ui.components.bottomsheets.modal.DEFAULT_FOOTER_HEIGHT import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetWithFooter
import com.tangem.core.ui.decompose.ComposableModularContentComponent import com.tangem.core.ui.decompose.ComposableModularContentComponent
import com.tangem.core.ui.extensions.rememberLastNonNull import com.tangem.core.ui.extensions.rememberLastNonNull
import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemTheme
@ -52,31 +60,44 @@ internal class DefaultCampaignsComponent @AssistedInject constructor(
val bottomSheet by bottomSheetSlot.subscribeAsState() val bottomSheet by bottomSheetSlot.subscribeAsState()
val activeChild = bottomSheet.child?.instance val activeChild = bottomSheet.child?.instance
val displayedChild = rememberLastNonNull(activeChild) val displayedChild = rememberLastNonNull(activeChild)
val footerExtraHeight by model.footerExtraHeightState.collectAsStateWithLifecycle()
TangemModalBottomSheetWithFooter<TangemBottomSheetConfigContent.Empty>( TangemBottomSheet<TangemBottomSheetConfigContent.Empty>(
config = TangemBottomSheetConfig( config = TangemBottomSheetConfig(
isShown = activeChild != null, isShown = activeChild != null,
onDismissRequest = model::onDismiss, onDismissRequest = model::onDismiss,
content = TangemBottomSheetConfigContent.Empty, content = TangemBottomSheetConfigContent.Empty,
), ),
containerColor = TangemTheme.colors3.bg.primary, containerColor = TangemTheme.colors3.bg.primary,
footerHeight = DEFAULT_FOOTER_HEIGHT + footerExtraHeight, type = TangemBottomSheetType.Modal,
onBack = model::onDismiss, onBack = model::onDismiss,
title = { title = {
displayedChild?.Title() displayedChild?.Title()
}, },
content = { content = {
Box(modifier = Modifier.animateContentSize()) { val bottomInset = LocalTangemBottomSheetContentBottomInset.current
displayedChild?.Content(modifier = Modifier) val bottomReserve = if (bottomInset > 0.dp) bottomInset else 16.dp
val scrollState = rememberScrollState()
val scrollableSignal = LocalBottomSheetContentScrollable.current
if (scrollableSignal != null) {
LaunchedEffect(scrollState) {
snapshotFlow { scrollState.canScrollForward || scrollState.canScrollBackward }
.collect { canScroll -> scrollableSignal.value = canScroll }
}
}
Column(modifier = Modifier.verticalScroll(state = scrollState)) {
Box(modifier = Modifier.animateContentSize()) {
displayedChild?.Content(modifier = Modifier)
}
if (scrollableSignal?.value != true) SpacerH32()
Spacer(modifier = Modifier.height(bottomReserve))
} }
}, },
footer = { footer = {
Box( Box(modifier = Modifier.padding(12.dp)) {
modifier = Modifier
.navigationBarsPadding()
.padding(12.dp),
) {
displayedChild?.Footer() displayedChild?.Footer()
} }
}, },
@ -102,7 +123,6 @@ internal class DefaultCampaignsComponent @AssistedInject constructor(
appComponentContext = context, appComponentContext = context,
chooseTokenComponentFactory = chooseTokenComponentFactory, chooseTokenComponentFactory = chooseTokenComponentFactory,
onDismiss = model::onDismiss, onDismiss = model::onDismiss,
onFooterExtraHeightReady = model::onFooterExtraHeightReady,
params = ActivateCampaignBottomSheetComponent.Params( params = ActivateCampaignBottomSheetComponent.Params(
campaignType = config.campaignType, campaignType = config.campaignType,
userWalletId = config.userWalletId, userWalletId = config.userWalletId,

View file

@ -12,6 +12,7 @@ import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.components.account.AccountIconSize import com.tangem.core.ui.components.account.AccountIconSize
import com.tangem.core.ui.components.currency.icon.CurrencyIconState import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.token.state.TokenItemState
import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.message.ToastMessage import com.tangem.core.ui.message.ToastMessage
@ -219,7 +220,17 @@ internal class ActivateCampaignsModel @Inject constructor(
null null
} }
val tokenItem = TokenItemStateConverter(appCurrency = appCurrency).convert(result.currency) val tokenItem = TokenItemStateConverter(
appCurrency = appCurrency,
subtitleStateProvider = { status ->
TokenItemState.SubtitleState.TextContent(
value = resourceReference(
R.string.domain_receive_assets_onboarding_network_name,
wrappedList(status.currency.network.name),
),
)
},
).convert(result.currency)
uiState.update { state -> uiState.update { state ->
state.copy( state.copy(

View file

@ -1,7 +1,5 @@
package com.tangem.features.promobanners.impl.campaigns.model package com.tangem.features.promobanners.impl.campaigns.model
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate import com.arkivanov.decompose.router.slot.activate
import com.arkivanov.decompose.router.slot.dismiss import com.arkivanov.decompose.router.slot.dismiss
@ -24,8 +22,6 @@ import com.tangem.features.promobanners.impl.campaigns.entity.toPromoCampaignId
import com.tangem.features.promobanners.impl.campaigns.service.CampaignsService import com.tangem.features.promobanners.impl.campaigns.service.CampaignsService
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -43,9 +39,6 @@ internal class CampaignsModel @Inject constructor(
val bottomSheetNavigation: SlotNavigation<CampaignsBottomSheetConfig> = SlotNavigation() val bottomSheetNavigation: SlotNavigation<CampaignsBottomSheetConfig> = SlotNavigation()
val footerExtraHeightState: StateFlow<Dp>
field = MutableStateFlow(0.dp)
init { init {
campaignsService.campaignFlow campaignsService.campaignFlow
.onEach { request -> .onEach { request ->
@ -89,22 +82,16 @@ internal class CampaignsModel @Inject constructor(
}, },
) )
fun onFooterExtraHeightReady(height: Dp) {
footerExtraHeightState.value = height
}
fun onDismiss() { fun onDismiss() {
bottomSheetNavigation.dismiss() bottomSheetNavigation.dismiss()
} }
fun onActivated(campaignType: CampaignType) { fun onActivated(campaignType: CampaignType) {
footerExtraHeightState.value = 0.dp
bottomSheetNavigation.activate(CampaignsBottomSheetConfig.Enrolled(campaignType)) bottomSheetNavigation.activate(CampaignsBottomSheetConfig.Enrolled(campaignType))
} }
fun onAlreadyActivated(campaignType: CampaignType) { fun onAlreadyActivated(campaignType: CampaignType) {
analyticsEventHandler.send(PromoCampaignsAnalyticsEvent.AlreadyEnrolledScreenOpened()) analyticsEventHandler.send(PromoCampaignsAnalyticsEvent.AlreadyEnrolledScreenOpened())
footerExtraHeightState.value = 0.dp
bottomSheetNavigation.activate(CampaignsBottomSheetConfig.AlreadyActivated(campaignType = campaignType)) bottomSheetNavigation.activate(CampaignsBottomSheetConfig.AlreadyActivated(campaignType = campaignType))
} }
} }

View file

@ -78,8 +78,6 @@ internal fun ActivateCampaignContent(um: ActivateCampaignUM, modifier: Modifier
selectedAccount = um.selectedAccount, selectedAccount = um.selectedAccount,
onChooseTokenClick = um.onChooseTokenClick, onChooseTokenClick = um.onChooseTokenClick,
) )
SpacerH32()
} }
} }

View file

@ -8,8 +8,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.LinkAnnotation import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
@ -18,7 +16,6 @@ import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withLink import androidx.compose.ui.text.withLink
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.PrimaryButton import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.SpacerH12 import com.tangem.core.ui.components.SpacerH12
@ -29,28 +26,17 @@ import com.tangem.features.promobanners.impl.campaigns.entity.FooterUM
import com.tangem.features.promobanners.impl.campaigns.entity.TermsUM import com.tangem.features.promobanners.impl.campaigns.entity.TermsUM
@Composable @Composable
internal fun ActivateCampaignFooter( internal fun ActivateCampaignFooter(footerUM: FooterUM, modifier: Modifier = Modifier) {
footerUM: FooterUM,
onFooterTextHeightReady: (Dp) -> Unit,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) { Column(modifier = modifier) {
val terms = footerUM.terms val terms = footerUM.terms
if (terms != null) { if (terms != null) {
val density = LocalDensity.current
Text( Text(
text = termsAnnotatedString(terms), text = termsAnnotatedString(terms),
style = TangemTheme.typography.caption2, style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary, color = TangemTheme.colors.text.secondary,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier modifier = Modifier.fillMaxWidth(),
.fillMaxWidth()
.onSizeChanged {
val termsBlockHeight = with(density) { it.height.toDp() } + 12.dp
onFooterTextHeightReady.invoke(termsBlockHeight)
},
) )
SpacerH12() SpacerH12()
@ -99,7 +85,6 @@ private fun Preview_ActivateCampaignFooter_WithTerms() {
modifier = Modifier modifier = Modifier
.background(TangemTheme.colors3.bg.primary) .background(TangemTheme.colors3.bg.primary)
.padding(16.dp), .padding(16.dp),
onFooterTextHeightReady = {},
) )
} }
} }
@ -114,7 +99,6 @@ private fun Preview_ActivateCampaignFooter_NoTerms() {
modifier = Modifier modifier = Modifier
.background(TangemTheme.colors3.bg.primary) .background(TangemTheme.colors3.bg.primary)
.padding(16.dp), .padding(16.dp),
onFooterTextHeightReady = {},
) )
} }
} }

View file

@ -54,8 +54,6 @@ internal fun AlreadyActivatedCampaignContent(message: TextReference, modifier: M
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp), .padding(horizontal = 16.dp),
) )
SpacerH32()
} }
} }

View file

@ -58,8 +58,6 @@ fun CampaignEnrolledMessageContent(message: TextReference, modifier: Modifier =
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) )
SpacerH32()
} }
} }

View file

@ -65,7 +65,5 @@ fun NotActiveCampaignMessageContent(modifier: Modifier = Modifier) {
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) )
SpacerH32()
} }
} }

View file

@ -1,8 +1,6 @@
package com.tangem.features.promobanners.impl.campaigns.model package com.tangem.features.promobanners.impl.campaigns.model
import androidx.compose.ui.unit.dp
import arrow.core.Either import arrow.core.Either
import com.google.common.truth.Truth.assertThat
import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.decompose.ui.UiMessageSender
import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.UserWalletId
@ -108,11 +106,10 @@ internal class CampaignsModelTest {
} }
@Test @Test
fun `GIVEN footer height set WHEN onAlreadyActivated THEN analytics sent and height reset`() = runTest { fun `WHEN onAlreadyActivated THEN analytics sent`() = runTest {
// Arrange // Arrange
val model = createModel(campaignFlow = emptyFlow()) val model = createModel(campaignFlow = emptyFlow())
advanceUntilIdle() advanceUntilIdle()
model.onFooterExtraHeightReady(100.dp)
// Act // Act
model.onAlreadyActivated(CampaignType.WhaleSwapCashback(campaignId = "1")) model.onAlreadyActivated(CampaignType.WhaleSwapCashback(campaignId = "1"))
@ -121,37 +118,20 @@ internal class CampaignsModelTest {
verify(exactly = 1) { verify(exactly = 1) {
analyticsEventHandler.send(PromoCampaignsAnalyticsEvent.AlreadyEnrolledScreenOpened()) analyticsEventHandler.send(PromoCampaignsAnalyticsEvent.AlreadyEnrolledScreenOpened())
} }
assertThat(model.footerExtraHeightState.value).isEqualTo(0.dp)
model.onDestroy() model.onDestroy()
} }
@Test @Test
fun `GIVEN footer height set WHEN onActivated THEN no analytics and height reset`() = runTest { fun `WHEN onActivated THEN no analytics sent`() = runTest {
// Arrange // Arrange
val model = createModel(campaignFlow = emptyFlow()) val model = createModel(campaignFlow = emptyFlow())
advanceUntilIdle() advanceUntilIdle()
model.onFooterExtraHeightReady(100.dp)
// Act // Act
model.onActivated(CampaignType.WhaleSwapCashback(campaignId = "1")) model.onActivated(CampaignType.WhaleSwapCashback(campaignId = "1"))
// Assert // Assert
verify { analyticsEventHandler wasNot Called } verify { analyticsEventHandler wasNot Called }
assertThat(model.footerExtraHeightState.value).isEqualTo(0.dp)
model.onDestroy()
}
@Test
fun `WHEN onFooterExtraHeightReady THEN height state is updated`() = runTest {
// Arrange
val model = createModel(campaignFlow = emptyFlow())
advanceUntilIdle()
// Act
model.onFooterExtraHeightReady(42.dp)
// Assert
assertThat(model.footerExtraHeightState.value).isEqualTo(42.dp)
model.onDestroy() model.onDestroy()
} }