Updated on 2026-08-14
This commit is contained in:
parent
08da87d369
commit
fc73f08b5e
12 changed files with 261 additions and 207 deletions
|
|
@ -12,6 +12,7 @@ import com.tangem.features.disclaimer.api.components.DisclaimerComponent
|
|||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensSource
|
||||
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
||||
import com.tangem.features.markets.tokenlist.MarketsTokenListComponent
|
||||
import com.tangem.features.nft.component.NFTComponent
|
||||
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
|
||||
import com.tangem.features.onramp.component.*
|
||||
|
|
@ -47,6 +48,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val disclaimerComponentFactory: DisclaimerComponent.Factory,
|
||||
private val manageTokensComponentFactory: ManageTokensComponent.Factory,
|
||||
private val marketsTokenDetailsComponentFactory: MarketsTokenDetailsComponent.Factory,
|
||||
private val marketsTokenListComponentFactory: MarketsTokenListComponent.Factory,
|
||||
private val onrampComponentFactory: OnrampComponent.Factory,
|
||||
private val onrampSuccessComponentFactory: OnrampSuccessComponent.Factory,
|
||||
private val buyCryptoComponentFactory: BuyCryptoComponent.Factory,
|
||||
|
|
@ -389,6 +391,13 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = nftSendComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.Markets -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = Unit,
|
||||
componentFactory = marketsTokenListComponentFactory,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -182,6 +182,9 @@ sealed class AppRoute(val path: String) : Route {
|
|||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/wallet_settings/${userWalletId.stringValue}")
|
||||
|
||||
@Serializable
|
||||
data object Markets : AppRoute(path = "/markets")
|
||||
|
||||
@Serializable
|
||||
data class MarketsTokenDetails(
|
||||
val token: TokenMarketParams,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.features.markets.tokenlist
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.features.markets.entry.BottomSheetState
|
||||
|
||||
@Stable
|
||||
interface MarketsTokenListComponent : ComposableContentComponent {
|
||||
|
||||
@Composable
|
||||
fun BottomSheetContent(
|
||||
bottomSheetState: State<BottomSheetState>,
|
||||
onHeaderSizeChange: (Dp) -> Unit,
|
||||
modifier: Modifier,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Unit, MarketsTokenListComponent>
|
||||
}
|
||||
|
|
@ -17,6 +17,9 @@ dependencies {
|
|||
api(projects.features.onramp.api)
|
||||
implementation(projects.core.navigation)
|
||||
|
||||
/* Data */
|
||||
implementation(projects.data.common)
|
||||
|
||||
/* Domain */
|
||||
implementation(projects.domain.appCurrency)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
|
|
|
|||
|
|
@ -5,20 +5,15 @@ import androidx.compose.runtime.Stable
|
|||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.arkivanov.decompose.ExperimentalDecomposeApi
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.childStack
|
||||
import com.arkivanov.decompose.router.stack.pushNew
|
||||
import com.arkivanov.decompose.router.stack.popWhile
|
||||
import com.arkivanov.decompose.value.Value
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarket
|
||||
import com.tangem.domain.markets.toSerializableParam
|
||||
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
||||
import com.tangem.core.decompose.navigation.inner.InnerRouter
|
||||
import com.tangem.features.markets.entry.BottomSheetState
|
||||
import com.tangem.features.markets.entry.MarketsEntryComponent
|
||||
import com.tangem.features.markets.entry.impl.MarketsEntryChildFactory.Child
|
||||
|
|
@ -35,7 +30,12 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor(
|
|||
|
||||
private val stackNavigation = StackNavigation<Child>()
|
||||
|
||||
val stack: Value<ChildStack<Child, Any>> = childStack(
|
||||
private val innerRouter = InnerRouter<Child>(
|
||||
stackNavigation = stackNavigation,
|
||||
popCallback = { onChildBack() },
|
||||
)
|
||||
|
||||
private val stack: Value<ChildStack<Child, Any>> = childStack(
|
||||
key = "main",
|
||||
source = stackNavigation,
|
||||
serializer = Child.serializer(),
|
||||
|
|
@ -46,9 +46,8 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor(
|
|||
child = configuration,
|
||||
appComponentContext = childByContext(
|
||||
componentContext = factoryContext,
|
||||
router = createRouter(configuration),
|
||||
router = innerRouter,
|
||||
),
|
||||
onTokenSelected = ::marketsListTokenSelected,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -68,32 +67,9 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalDecomposeApi::class)
|
||||
private fun marketsListTokenSelected(token: TokenMarket, appCurrency: AppCurrency) {
|
||||
stackNavigation.pushNew(
|
||||
configuration = Child.TokenDetails(
|
||||
params = MarketsTokenDetailsComponent.Params(
|
||||
token = token.toSerializableParam(),
|
||||
appCurrency = appCurrency,
|
||||
showPortfolio = true,
|
||||
analyticsParams = MarketsTokenDetailsComponent.AnalyticsParams(
|
||||
blockchain = null,
|
||||
source = "Market",
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun AppComponentContext.createRouter(child: Child): Router {
|
||||
return when (child) {
|
||||
is Child.TokenDetails -> {
|
||||
MarketTokenDetailsRouter(
|
||||
contextRouter = this.router,
|
||||
stackNavigation = stackNavigation,
|
||||
)
|
||||
}
|
||||
else -> this.router
|
||||
private fun onChildBack() {
|
||||
if (stack.value.active.configuration !is Child.TokenList) {
|
||||
stackNavigation.popWhile { it != Child.TokenList }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
package com.tangem.features.markets.entry.impl
|
||||
|
||||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.popWhile
|
||||
import com.tangem.core.decompose.navigation.Route
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal class MarketTokenDetailsRouter(
|
||||
private val contextRouter: Router,
|
||||
private val stackNavigation: StackNavigation<MarketsEntryChildFactory.Child>,
|
||||
) : Router by contextRouter {
|
||||
|
||||
override fun pop(onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
stackNavigation.popWhile({ it != MarketsEntryChildFactory.Child.TokenList }, onComplete)
|
||||
}
|
||||
|
||||
override fun popTo(route: Route, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
/** Not allowed */
|
||||
}
|
||||
|
||||
override fun popTo(routeClass: KClass<out Route>, onComplete: (isSuccess: Boolean) -> Unit) {
|
||||
/** Not allowed */
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,9 @@ package com.tangem.features.markets.entry.impl
|
|||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarket
|
||||
import com.tangem.core.decompose.navigation.Route
|
||||
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
||||
import com.tangem.features.markets.entry.impl.MarketsEntryChildFactory.Child
|
||||
import com.tangem.features.markets.tokenlist.api.MarketsTokenListComponent
|
||||
import com.tangem.features.markets.tokenlist.MarketsTokenListComponent
|
||||
import kotlinx.serialization.Serializable
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -17,7 +15,7 @@ internal class MarketsEntryChildFactory @Inject constructor(
|
|||
|
||||
@Serializable
|
||||
@Immutable
|
||||
sealed interface Child {
|
||||
sealed interface Child : Route {
|
||||
|
||||
@Serializable
|
||||
@Immutable
|
||||
|
|
@ -28,11 +26,7 @@ internal class MarketsEntryChildFactory @Inject constructor(
|
|||
data class TokenDetails(val params: MarketsTokenDetailsComponent.Params) : Child
|
||||
}
|
||||
|
||||
fun createChild(
|
||||
child: Child,
|
||||
appComponentContext: AppComponentContext,
|
||||
onTokenSelected: (TokenMarket, AppCurrency) -> Unit,
|
||||
): Any {
|
||||
fun createChild(child: Child, appComponentContext: AppComponentContext): Any {
|
||||
return when (child) {
|
||||
is Child.TokenDetails -> {
|
||||
tokenDetailsComponentFactory.create(
|
||||
|
|
@ -43,7 +37,7 @@ internal class MarketsEntryChildFactory @Inject constructor(
|
|||
is Child.TokenList -> {
|
||||
tokenListComponentFactory.create(
|
||||
context = appComponentContext,
|
||||
onTokenSelected = onTokenSelected,
|
||||
params = Unit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
||||
import com.tangem.features.markets.entry.BottomSheetState
|
||||
import com.tangem.features.markets.entry.impl.MarketsEntryChildFactory
|
||||
import com.tangem.features.markets.tokenlist.api.MarketsTokenListComponent
|
||||
import com.tangem.features.markets.tokenlist.MarketsTokenListComponent
|
||||
|
||||
@Composable
|
||||
internal fun EntryBottomSheetContent(
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
package com.tangem.features.markets.tokenlist.api
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarket
|
||||
import com.tangem.features.markets.entry.BottomSheetState
|
||||
|
||||
@Stable
|
||||
interface MarketsTokenListComponent {
|
||||
|
||||
@Composable
|
||||
fun BottomSheetContent(
|
||||
bottomSheetState: State<BottomSheetState>,
|
||||
onHeaderSizeChange: (Dp) -> Unit,
|
||||
modifier: Modifier,
|
||||
)
|
||||
|
||||
interface Factory {
|
||||
fun create(
|
||||
context: AppComponentContext,
|
||||
onTokenSelected: (TokenMarket, AppCurrency) -> Unit,
|
||||
): MarketsTokenListComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,58 @@
|
|||
package com.tangem.features.markets.tokenlist.impl
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.lifecycle.compose.LifecycleStartEffect
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRoute.MarketsTokenDetails.AnalyticsParams
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarket
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
import com.tangem.domain.markets.toSerializableParam
|
||||
import com.tangem.features.markets.entry.BottomSheetState
|
||||
import com.tangem.features.markets.tokenlist.api.MarketsTokenListComponent
|
||||
import com.tangem.features.markets.tokenlist.MarketsTokenListComponent
|
||||
import com.tangem.features.markets.tokenlist.impl.model.MarketsListModel
|
||||
import com.tangem.features.markets.tokenlist.impl.ui.MarketsList
|
||||
import com.tangem.features.markets.tokenlist.impl.ui.MarketsListWithBack
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
class DefaultMarketsTokenListComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted private val onTokenSelected: (TokenMarket, AppCurrency) -> Unit,
|
||||
@Assisted params: Unit,
|
||||
) : AppComponentContext by appComponentContext, MarketsTokenListComponent {
|
||||
|
||||
private val model: MarketsListModel = getOrCreateModel()
|
||||
|
||||
init {
|
||||
model.tokenSelected
|
||||
.onEach { onTokenSelected(it.first, it.second) }
|
||||
.onEach { (token, appCurrency) ->
|
||||
router.push(
|
||||
AppRoute.MarketsTokenDetails(
|
||||
token = token.toSerializableParam(),
|
||||
appCurrency = appCurrency,
|
||||
showPortfolio = true,
|
||||
analyticsParams = AnalyticsParams(
|
||||
blockchain = null,
|
||||
source = "Market",
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
.launchIn(componentScope)
|
||||
}
|
||||
|
||||
|
|
@ -60,11 +84,35 @@ class DefaultMarketsTokenListComponent @AssistedInject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
LifecycleStartEffect(Unit) {
|
||||
model.isVisibleOnScreen.value = true
|
||||
onStopOrDispose {
|
||||
model.isVisibleOnScreen.value = false
|
||||
}
|
||||
}
|
||||
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
|
||||
Scaffold(
|
||||
contentWindowInsets = WindowInsetsZero,
|
||||
containerColor = TangemTheme.colors.background.primary,
|
||||
) {
|
||||
MarketsListWithBack(
|
||||
modifier = Modifier
|
||||
.statusBarsPadding()
|
||||
.imePadding()
|
||||
.padding(it),
|
||||
state = state,
|
||||
bottomSheetState = BottomSheetState.EXPANDED,
|
||||
onBackClick = router::pop,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MarketsTokenListComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
onTokenSelected: (TokenMarket, AppCurrency) -> Unit,
|
||||
): DefaultMarketsTokenListComponent
|
||||
override fun create(context: AppComponentContext, params: Unit): DefaultMarketsTokenListComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.features.markets.tokenlist.impl.di
|
||||
|
||||
import com.tangem.features.markets.tokenlist.api.MarketsTokenListComponent
|
||||
import com.tangem.features.markets.tokenlist.MarketsTokenListComponent
|
||||
import com.tangem.features.markets.tokenlist.impl.DefaultMarketsTokenListComponent
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
|
|||
|
|
@ -3,22 +3,29 @@ package com.tangem.features.markets.tokenlist.impl.ui
|
|||
import android.content.res.Configuration
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ripple
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import com.tangem.core.ui.components.Keyboard
|
||||
import com.tangem.core.ui.components.SpacerH12
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
|
|
@ -62,26 +69,8 @@ internal fun MarketsList(
|
|||
bottomSheetState: BottomSheetState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Content(
|
||||
modifier = modifier,
|
||||
state = state,
|
||||
onHeaderSizeChange = onHeaderSizeChange,
|
||||
)
|
||||
MarketsListSortByBottomSheet(config = state.sortByBottomSheet)
|
||||
KeyboardEvents(
|
||||
isSortByBottomSheetShown = state.sortByBottomSheet.isShown,
|
||||
bottomSheetState = bottomSheetState,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun Content(state: MarketsListUM, onHeaderSizeChange: (Dp) -> Unit, modifier: Modifier = Modifier) {
|
||||
val density = LocalDensity.current
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
val strokeColor = TangemTheme.colors.stroke.primary
|
||||
val scrolledState = remember { mutableStateOf(false) }
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
|
|
@ -106,85 +95,148 @@ private fun Content(state: MarketsListUM, onHeaderSizeChange: (Dp) -> Unit, modi
|
|||
.padding(bottom = 4.dp),
|
||||
state = state.searchBar,
|
||||
)
|
||||
Column(Modifier.padding(horizontal = TangemTheme.dimens.size16)) {
|
||||
AnimatedVisibility(
|
||||
visible = scrolledState.value.not(),
|
||||
) {
|
||||
Column {
|
||||
SpacerH8()
|
||||
Title(isInSearchMode = state.isInSearchMode)
|
||||
SpacerH12()
|
||||
}
|
||||
}
|
||||
Content(state = state)
|
||||
}
|
||||
MarketsListSortByBottomSheet(config = state.sortByBottomSheet)
|
||||
KeyboardEvents(
|
||||
isSortByBottomSheetShown = state.sortByBottomSheet.isShown,
|
||||
bottomSheetState = bottomSheetState,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun MarketsListWithBack(
|
||||
state: MarketsListUM,
|
||||
bottomSheetState: BottomSheetState,
|
||||
onBackClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val background = LocalMainBottomSheetColor.current.value
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.drawBehind { drawRect(background) },
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painter = rememberVectorPainter(
|
||||
ImageVector.vectorResource(R.drawable.ic_close_24),
|
||||
),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = ripple(bounded = false),
|
||||
onClick = onBackClick,
|
||||
),
|
||||
)
|
||||
SearchBar(
|
||||
modifier = Modifier
|
||||
.drawBehind { drawRect(background) }
|
||||
.padding(
|
||||
end = 16.dp,
|
||||
),
|
||||
state = state.searchBar,
|
||||
)
|
||||
}
|
||||
Content(state = state)
|
||||
}
|
||||
MarketsListSortByBottomSheet(config = state.sortByBottomSheet)
|
||||
KeyboardEvents(
|
||||
isSortByBottomSheetShown = state.sortByBottomSheet.isShown,
|
||||
bottomSheetState = bottomSheetState,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun ColumnScope.Content(state: MarketsListUM, modifier: Modifier = Modifier) {
|
||||
val strokeColor = TangemTheme.colors.stroke.primary
|
||||
val scrolledState = remember { mutableStateOf(false) }
|
||||
|
||||
Column(modifier.padding(horizontal = TangemTheme.dimens.size16)) {
|
||||
AnimatedVisibility(
|
||||
visible = scrolledState.value.not(),
|
||||
) {
|
||||
Column {
|
||||
AnimatedVisibility(state.isInSearchMode.not()) {
|
||||
Options(
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
sortByTypeUM = state.selectedSortBy,
|
||||
trendInterval = state.selectedInterval,
|
||||
onIntervalClick = state.onIntervalClick,
|
||||
onSortByClick = state.onSortByButtonClick,
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
state.isInSearchMode.not() &&
|
||||
state.stakingNotificationMaxApy != null &&
|
||||
state.selectedSortBy != SortByTypeUM.Staking,
|
||||
) {
|
||||
val showMore = stringResourceSafe(R.string.common_show_more)
|
||||
val description = stringResourceSafe(
|
||||
R.string.markets_staking_banner_description_placeholder,
|
||||
showMore,
|
||||
)
|
||||
|
||||
val clickableDescription = buildAnnotatedString {
|
||||
append(description.substringBefore(showMore))
|
||||
|
||||
pushStringAnnotation(SHOW_MORE_KEY, "")
|
||||
appendColored(showMore, TangemTheme.colors.text.accent)
|
||||
pop()
|
||||
}
|
||||
|
||||
StakingInMarketsPromoNotification(
|
||||
config = NotificationConfig(
|
||||
iconResId = R.drawable.img_staking_in_market_notification,
|
||||
title = resourceReference(
|
||||
R.string.markets_staking_banner_title,
|
||||
wrappedList(state.stakingNotificationMaxApy.format { percent() }),
|
||||
),
|
||||
subtitle = annotatedReference(clickableDescription),
|
||||
onClick = state.onStakingNotificationClick,
|
||||
onCloseClick = state.onStakingNotificationCloseClick,
|
||||
),
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
SpacerH8()
|
||||
Title(isInSearchMode = state.isInSearchMode)
|
||||
SpacerH12()
|
||||
}
|
||||
}
|
||||
Column {
|
||||
AnimatedVisibility(state.isInSearchMode.not()) {
|
||||
Options(
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
sortByTypeUM = state.selectedSortBy,
|
||||
trendInterval = state.selectedInterval,
|
||||
onIntervalClick = state.onIntervalClick,
|
||||
onSortByClick = state.onSortByButtonClick,
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
state.isInSearchMode.not() &&
|
||||
state.stakingNotificationMaxApy != null &&
|
||||
state.selectedSortBy != SortByTypeUM.Staking,
|
||||
) {
|
||||
val showMore = stringResourceSafe(R.string.common_show_more)
|
||||
val description = stringResourceSafe(
|
||||
R.string.markets_staking_banner_description_placeholder,
|
||||
showMore,
|
||||
)
|
||||
|
||||
val clickableDescription = buildAnnotatedString {
|
||||
append(description.substringBefore(showMore))
|
||||
|
||||
pushStringAnnotation(SHOW_MORE_KEY, "")
|
||||
appendColored(showMore, TangemTheme.colors.text.accent)
|
||||
pop()
|
||||
}
|
||||
|
||||
StakingInMarketsPromoNotification(
|
||||
config = NotificationConfig(
|
||||
iconResId = R.drawable.img_staking_in_market_notification,
|
||||
title = resourceReference(
|
||||
R.string.markets_staking_banner_title,
|
||||
wrappedList(state.stakingNotificationMaxApy.format { percent() }),
|
||||
),
|
||||
subtitle = annotatedReference(clickableDescription),
|
||||
onClick = state.onStakingNotificationClick,
|
||||
onCloseClick = state.onStakingNotificationCloseClick,
|
||||
),
|
||||
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing12),
|
||||
)
|
||||
}
|
||||
}
|
||||
val strokeWidth = TangemTheme.dimens.size0_5
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.height(strokeWidth)
|
||||
.drawBehind {
|
||||
// draw horizontal line
|
||||
if (scrolledState.value) {
|
||||
drawLine(
|
||||
color = strokeColor,
|
||||
start = Offset(0f, size.height),
|
||||
end = Offset(size.width, size.height),
|
||||
strokeWidth = strokeWidth.toPx(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
ItemsList(
|
||||
scrolledState = scrolledState,
|
||||
isInSearchMode = state.isInSearchMode,
|
||||
state = state.list,
|
||||
)
|
||||
}
|
||||
val strokeWidth = TangemTheme.dimens.size0_5
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.height(strokeWidth)
|
||||
.drawBehind {
|
||||
// draw horizontal line
|
||||
if (scrolledState.value) {
|
||||
drawLine(
|
||||
color = strokeColor,
|
||||
start = Offset(0f, size.height),
|
||||
end = Offset(size.width, size.height),
|
||||
strokeWidth = strokeWidth.toPx(),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
ItemsList(
|
||||
scrolledState = scrolledState,
|
||||
isInSearchMode = state.isInSearchMode,
|
||||
state = state.list,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue