Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-06 16:25:41 +02:00
parent 9f7f0b519f
commit 3b1e642150
6 changed files with 73 additions and 24 deletions

View file

@ -17,6 +17,7 @@ interface FeedEntryComponent : ComposableContentComponent {
fun BottomSheetContent(
bottomSheetState: State<BottomSheetState>,
onHeaderSizeChange: (Dp) -> Unit,
onExpandSheet: () -> Unit,
modifier: Modifier,
)

View file

@ -172,6 +172,7 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
override fun BottomSheetContent(
bottomSheetState: State<BottomSheetState>,
onHeaderSizeChange: (Dp) -> Unit,
onExpandSheet: () -> Unit,
modifier: Modifier,
) {
val bsState by bottomSheetState
@ -191,6 +192,7 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
bottomSheetState = bottomSheetState,
stackState = stackStack,
onHeaderSizeChange = onHeaderSizeChange,
onExpandSheet = onExpandSheet,
isOpenedInBottomSheet = true,
)
}
@ -213,6 +215,7 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
bottomSheetState = bottomSheetState,
stackState = stack.subscribeAsState(),
onHeaderSizeChange = {},
onExpandSheet = {},
isOpenedInBottomSheet = false,
)
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.feed.ui
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
@ -9,6 +10,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.ExperimentalDecomposeApi
@ -33,6 +35,7 @@ internal fun EntryContent(
bottomSheetState: State<BottomSheetState>,
stackState: State<ChildStack<FeedEntryChildFactory.Child, ComposableModularBottomSheetContentComponent>>,
onHeaderSizeChange: (Dp) -> Unit,
onExpandSheet: () -> Unit,
isOpenedInBottomSheet: Boolean,
) {
if (LocalRedesignEnabled.current) {
@ -40,6 +43,7 @@ internal fun EntryContent(
bottomSheetState = bottomSheetState,
stackState = stackState,
onHeaderSizeChange = onHeaderSizeChange,
onExpandSheet = onExpandSheet,
isOpenedInBottomSheet = isOpenedInBottomSheet,
)
} else {
@ -47,6 +51,7 @@ internal fun EntryContent(
bottomSheetState = bottomSheetState,
stackState = stackState,
onHeaderSizeChange = onHeaderSizeChange,
onExpandSheet = onExpandSheet,
isOpenedInBottomSheet = isOpenedInBottomSheet,
)
}
@ -57,6 +62,7 @@ private fun EntryContentV1(
bottomSheetState: State<BottomSheetState>,
stackState: State<ChildStack<FeedEntryChildFactory.Child, ComposableModularBottomSheetContentComponent>>,
onHeaderSizeChange: (Dp) -> Unit,
onExpandSheet: () -> Unit,
isOpenedInBottomSheet: Boolean,
) {
val density = LocalDensity.current
@ -68,7 +74,7 @@ private fun EntryContentV1(
containerColor = background,
contentWindowInsets = WindowInsetsZero,
topBar = {
Children(
Box(
modifier = Modifier
.then(
if (!isOpenedInBottomSheet) {
@ -84,10 +90,17 @@ private fun EntryContentV1(
}
}
},
stack = stackState.value,
animation = stackAnimation,
) { child ->
child.instance.Title(bottomSheetState)
) {
Children(
stack = stackState.value,
animation = stackAnimation,
) { child ->
child.instance.Title(bottomSheetState)
}
CollapsedTitleClickOverlay(
bottomSheetState = bottomSheetState,
onExpandSheet = onExpandSheet,
)
}
},
content = { contentPadding ->
@ -111,6 +124,7 @@ private fun EntryContentV2(
bottomSheetState: State<BottomSheetState>,
stackState: State<ChildStack<FeedEntryChildFactory.Child, ComposableModularBottomSheetContentComponent>>,
onHeaderSizeChange: (Dp) -> Unit,
onExpandSheet: () -> Unit,
isOpenedInBottomSheet: Boolean,
) {
val density = LocalDensity.current
@ -142,7 +156,7 @@ private fun EntryContentV2(
bottomSheetState = bottomSheetState,
)
}
AnimatedContent(
Box(
modifier = Modifier
.align(Alignment.TopStart)
.then(
@ -161,14 +175,37 @@ private fun EntryContentV2(
}
}
},
targetState = stackState.value.active,
transitionSpec = animationAppBar,
contentKey = { it.key },
label = "FeedEntryAppBar",
) { state ->
state.instance.Title(bottomSheetState)
) {
AnimatedContent(
targetState = stackState.value.active,
transitionSpec = animationAppBar,
contentKey = { it.key },
label = "FeedEntryAppBar",
) { state ->
state.instance.Title(bottomSheetState)
}
CollapsedTitleClickOverlay(
bottomSheetState = bottomSheetState,
onExpandSheet = onExpandSheet,
)
}
}
}
}
}
@Composable
private fun BoxScope.CollapsedTitleClickOverlay(bottomSheetState: State<BottomSheetState>, onExpandSheet: () -> Unit) {
if (bottomSheetState.value == BottomSheetState.COLLAPSED) {
Box(
modifier = Modifier
.matchParentSize()
.clickable(
interactionSource = null,
indication = null,
onClick = onExpandSheet,
)
.clearAndSetSemantics {},
)
}
}

View file

@ -260,10 +260,11 @@ internal class WalletComponent @AssistedInject constructor(
WalletScreen2(
state = uiState,
tangemPayComponent = tangemPayMainBlockComponent,
bottomSheetContent = {
bottomSheetContent = { onExpandSheet ->
BottomSheetContent(
bottomSheetState = bottomSheetState,
onHeaderSizeChange = { headerSize = it },
onExpandSheet = onExpandSheet,
modifier = modifier,
)
},
@ -275,10 +276,11 @@ internal class WalletComponent @AssistedInject constructor(
state = uiState,
promoBannersBlockComponent = promoBannersBlockComponent,
tangemPayComponent = tangemPayMainBlockComponent,
bottomSheetContent = {
bottomSheetContent = { onExpandSheet ->
BottomSheetContent(
bottomSheetState = bottomSheetState,
onHeaderSizeChange = { headerSize = it },
onExpandSheet = onExpandSheet,
modifier = modifier,
)
},
@ -305,11 +307,13 @@ internal class WalletComponent @AssistedInject constructor(
private fun BottomSheetContent(
bottomSheetState: State<BottomSheetState>,
onHeaderSizeChange: (Dp) -> Unit,
onExpandSheet: () -> Unit,
modifier: Modifier = Modifier,
) {
feedEntryComponent.BottomSheetContent(
bottomSheetState = bottomSheetState,
onHeaderSizeChange = onHeaderSizeChange,
onExpandSheet = onExpandSheet,
modifier = modifier,
)
}

View file

@ -95,7 +95,7 @@ internal fun WalletScreen(
state: WalletScreenState,
tangemPayComponent: TangemPayMainBlockComponent,
promoBannersBlockComponent: ComposableContentComponent? = null,
bottomSheetContent: @Composable (() -> Unit),
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
) {
@ -139,7 +139,7 @@ private fun WalletContent(
promoBannersBlockComponent: ComposableContentComponent? = null,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
bottomSheetContent: @Composable (() -> Unit),
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
) {
/*
* Don't pass key to remember, because it will brake scroll animation.
@ -295,7 +295,7 @@ private inline fun BaseScaffoldWithMarkets(
snackbarHostState: SnackbarHostState,
bottomSheetHeaderHeightProvider: () -> Dp,
noinline onBottomSheetStateChange: (BottomSheetState) -> Unit,
crossinline bottomSheetContent: @Composable () -> Unit,
crossinline bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
crossinline content: @Composable (PaddingValues) -> Unit,
) {
val isKeyboardVisible by rememberIsKeyboardVisible()
@ -382,7 +382,7 @@ private inline fun BaseScaffoldWithMarkets(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
// expand bottom sheet when clicked on the header
// expand bottom sheet when clicked on the drag handle
.clickable(
enabled = bottomSheetState.currentValue == TangemSheetValue.PartiallyExpanded,
indication = null,
@ -400,7 +400,9 @@ private inline fun BaseScaffoldWithMarkets(
isSearchFieldFocused = it.isFocused
},
) {
bottomSheetContent()
bottomSheetContent {
coroutineScope.launch { bottomSheetState.expand() }
}
}
}
},

View file

@ -86,7 +86,7 @@ internal fun WalletScreen2(
state: WalletScreenState,
tangemPayComponent: TangemPayMainBlockComponent,
modifier: Modifier = Modifier,
bottomSheetContent: @Composable (() -> Unit),
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
) {
@ -162,7 +162,7 @@ private fun WalletContent2(
modifier: Modifier = Modifier,
bottomSheetHeaderHeightProvider: () -> Dp,
onBottomSheetStateChange: (BottomSheetState) -> Unit,
bottomSheetContent: @Composable (() -> Unit),
bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
) {
val density = LocalDensity.current
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() }
@ -343,7 +343,7 @@ private inline fun BaseScaffoldWithMarkets(
modifier: Modifier = Modifier,
noinline onBottomSheetStateChange: (BottomSheetState) -> Unit,
crossinline appBarContent: @Composable () -> Unit,
crossinline bottomSheetContent: @Composable () -> Unit,
crossinline bottomSheetContent: @Composable (onExpandSheet: () -> Unit) -> Unit,
crossinline content: @Composable (PaddingValues, TangemSheetState) -> Unit,
) {
val density = LocalDensity.current
@ -384,7 +384,9 @@ private inline fun BaseScaffoldWithMarkets(
isSearchFieldFocused = focusState.isFocused
},
) {
bottomSheetContent()
bottomSheetContent {
coroutineScope.launch { bottomSheetState.expand() }
}
}
},
content = { paddingValues ->
@ -456,7 +458,7 @@ private fun BottomSheet(
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
// expand bottom sheet when clicked on the header
// expand bottom sheet when clicked on the drag handle
.clickable(
enabled = bottomSheetState.currentValue == TangemSheetValue.PartiallyExpanded,
indication = null,