Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-20 15:03:30 +01:00
parent fc5fbfca7f
commit e8c4e3a4a7
3 changed files with 79 additions and 5 deletions

View file

@ -6,19 +6,20 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import com.arkivanov.decompose.extensions.compose.stack.Children
import com.arkivanov.decompose.extensions.compose.stack.animation.fade
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
import com.arkivanov.decompose.router.stack.ChildStack
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
import com.tangem.core.ui.res.LocalMainBottomSheetColor
import com.tangem.core.ui.utils.WindowInsetsZero
import com.tangem.features.feed.components.FeedEntryChildFactory
import com.tangem.features.feed.ui.utils.contentFeedEntryStackAnimation
import com.tangem.features.feed.ui.utils.topBarFeedEntryStackAnimation
@Composable
internal fun EntryContent(
@ -29,6 +30,8 @@ internal fun EntryContent(
) {
val density = LocalDensity.current
val background = LocalMainBottomSheetColor.current.value
val animationContent = remember { contentFeedEntryStackAnimation() }
val animationAppBar = remember { topBarFeedEntryStackAnimation() }
Surface(contentColor = background) {
Scaffold(
@ -52,7 +55,7 @@ internal fun EntryContent(
}
},
stack = stackState.value,
animation = stackAnimation(fade()),
animation = animationAppBar,
) { child ->
child.instance.Title(bottomSheetState)
}
@ -60,7 +63,7 @@ internal fun EntryContent(
content = { contentPadding ->
Children(
stack = stackState.value,
animation = stackAnimation(fade()),
animation = animationContent,
) { child ->
child.instance.Content(
modifier = Modifier.padding(contentPadding),

View file

@ -48,7 +48,7 @@ import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.delay
private const val SHOW_MORE_KEY = "privacyPolicy"
private const val DELAY_FOR_FOCUS_REQUEST = 200L
private const val DELAY_FOR_FOCUS_REQUEST = 500L
@Composable
internal fun TopBarWithSearch(

View file

@ -0,0 +1,71 @@
package com.tangem.features.feed.ui.utils
import androidx.compose.animation.core.tween
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.FaultyDecomposeApi
import com.arkivanov.decompose.extensions.compose.stack.animation.*
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
import com.tangem.core.ui.utils.toPx
import com.tangem.features.feed.components.FeedEntryChildFactory
private const val DELAY_FOR_TRANSITION = 400
@OptIn(FaultyDecomposeApi::class)
internal fun topBarFeedEntryStackAnimation(): StackAnimation<
FeedEntryChildFactory.Child,
ComposableModularBottomSheetContentComponent,
> =
stackAnimation { to, from, _ ->
val isSearchToTokenList =
(to.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
val isFromSearchTokenList =
(from.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
if (isSearchToTokenList || isFromSearchTokenList) {
fade()
} else {
slide()
}
}
@OptIn(FaultyDecomposeApi::class)
internal fun contentFeedEntryStackAnimation(): StackAnimation<
FeedEntryChildFactory.Child,
ComposableModularBottomSheetContentComponent,
> =
stackAnimation { to, from, _ ->
val isSearchToTokenList =
(to.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
val isFromSearchTokenList =
(from.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
if (isSearchToTokenList || isFromSearchTokenList) {
fadeAndSlideInt()
} else {
slide()
}
}
private fun fadeAndSlideInt(): StackAnimator =
stackAnimator(animationSpec = tween(DELAY_FOR_TRANSITION)) { factor, _, content ->
val alpha = 1f - kotlin.math.abs(factor)
val slidePx = 32.dp.toPx()
val yOffset = when {
factor > 0 -> (slidePx * factor).toInt()
factor < 0 -> (slidePx * factor * -1).toInt()
else -> 0
}
content(
Modifier
.alpha(alpha)
.offsetY(yOffset),
)
}
private fun Modifier.offsetY(pixels: Int): Modifier = layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
layout(placeable.width, placeable.height) {
placeable.placeRelative(x = 0, y = pixels)
}
}